Spaces:
Running on Zero
fix: Launch the probe again, with SSR off
Browse filesMounting the probe instead of launching it failed startup outright: "No
@spaces.GPU function detected during startup". So mounting does not register the
handler the platform's validation looks for, and the original note in this file
was right -- the probe must be launch()ed. My reversal of it was wrong and is
corrected in place, with what was actually observed, so the next person does not
try mounting again.
Keeping the part of that change that stands on its own: ssr_mode=False. Gradio 6
defaults to SSR and spawns a Node subprocess ("Node proxy -> Python :7862" in the
startup log) into the process ZeroGPU forks its CUDA worker from, and a fork
parent holding a subprocess is a plausible cause of the worker's "No CUDA GPUs
are available". That is now the only variable changed against the last build
that reached GPU acquisition.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- app_space.py +21 -13
|
@@ -10,13 +10,16 @@ ControlAI, and each of the four below was learned by having the Space fail:
|
|
| 10 |
function detected". Hence the hidden probe button.
|
| 11 |
2. That function must be a module-level `def`. Nested inside a `with
|
| 12 |
gr.Blocks():` block, the same detection fails.
|
| 13 |
-
3.
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
| 20 |
4. Never pass the model-holding object as an *argument* to a `@spaces.GPU`
|
| 21 |
function. ZeroGPU marshals arguments across a process boundary and will try
|
| 22 |
to share the model's CUDA tensors, failing with `_share_cuda_: only
|
|
@@ -217,12 +220,17 @@ with gr.Blocks() as _gpu_demo:
|
|
| 217 |
|
| 218 |
def main() -> None:
|
| 219 |
port = int(os.environ.get("PORT", 7860))
|
| 220 |
-
#
|
| 221 |
-
#
|
| 222 |
-
#
|
| 223 |
-
|
| 224 |
-
|
| 225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
|
| 227 |
|
| 228 |
if __name__ == "__main__":
|
|
|
|
| 10 |
function detected". Hence the hidden probe button.
|
| 11 |
2. That function must be a module-level `def`. Nested inside a `with
|
| 12 |
gr.Blocks():` block, the same detection fails.
|
| 13 |
+
3. The probe must be `launch()`ed, on its own port, and **not** merely mounted.
|
| 14 |
+
Mounting it with `gr.mount_gradio_app` was tried: the Space fails to start
|
| 15 |
+
with "No @spaces.GPU function detected during startup", so mounting does not
|
| 16 |
+
register the handler the way the platform's validation looks for. Do not
|
| 17 |
+
mount it into the FastAPI app and *also* run uvicorn on the same port,
|
| 18 |
+
though -- that is two servers and collides with "address already in use".
|
| 19 |
+
Launch with `ssr_mode=False`: Gradio 6 defaults to SSR, which spawns a Node
|
| 20 |
+
subprocess into the very process ZeroGPU then `fork()`s its CUDA worker
|
| 21 |
+
from, and a fork parent holding a subprocess is a plausible cause of the
|
| 22 |
+
worker's "No CUDA GPUs are available".
|
| 23 |
4. Never pass the model-holding object as an *argument* to a `@spaces.GPU`
|
| 24 |
function. ZeroGPU marshals arguments across a process boundary and will try
|
| 25 |
to share the model's CUDA tensors, failing with `_share_cuda_: only
|
|
|
|
| 220 |
|
| 221 |
def main() -> None:
|
| 222 |
port = int(os.environ.get("PORT", 7860))
|
| 223 |
+
# Launched, not mounted: mounting fails startup validation ("No @spaces.GPU
|
| 224 |
+
# function detected"). Separate port, non-blocking, and ssr_mode=False so no
|
| 225 |
+
# Node subprocess lands in the process ZeroGPU forks its CUDA worker from.
|
| 226 |
+
_gpu_demo.launch(
|
| 227 |
+
server_name="0.0.0.0",
|
| 228 |
+
server_port=port + 1,
|
| 229 |
+
prevent_thread_lock=True,
|
| 230 |
+
share=False,
|
| 231 |
+
ssr_mode=False,
|
| 232 |
+
)
|
| 233 |
+
uvicorn.run(app, host="0.0.0.0", port=port, log_level="info")
|
| 234 |
|
| 235 |
|
| 236 |
if __name__ == "__main__":
|