| --- |
| title: Zerogpu Workflow |
| emoji: π |
| colorFrom: blue |
| colorTo: blue |
| sdk: gradio |
| sdk_version: 6.20.0 |
| python_version: '3.12.12' |
| app_file: app.py |
| pinned: false |
| short_description: gr.Workflow serialization experiment on ZeroGPU |
| --- |
| |
| # gr.Workflow serialization experiment on ZeroGPU |
|
|
| This Space demonstrates that `gr.Workflow` (canvas UI) executes all node runs sequentially, process-wide, instead of in parallel. The workflow is defined in `workflow.json`: a text input (`Prompt`) feeds a two-node chain, and the final text lands in an output node (`Result`). |
|
|
| - `generate`: a `@spaces.GPU` function that sleeps 5 seconds (stand-in for GPU inference). It records its start/end timestamps and the attached GPU name in its output. |
| - `visualize`: a plain CPU function that sleeps 3 seconds and passes the text through, also with timestamps. |
|
|
| ## How to reproduce |
|
|
| 1. Open this Space in two browser tabs. |
| 2. Type a distinct input in each tab's `Prompt` node (e.g. `tab1` / `tab2`) and click Run in both tabs within a second or two. |
|
|
| ## What to observe |
|
|
| If runs were parallel, both tabs' `Result` nodes would fill in roughly 8 seconds after clicking, and the Space page would show 2 concurrent GPUs while both `generate` calls are in flight. |
|
|
| What actually happens (the bug): |
|
|
| - The concurrent-GPU indicator stays at 1. |
| - The timestamps embedded in the `Result` text show strict serialization across tabs: tab2's `generate` starts right when tab1's `generate` ends, and the `visualize` steps queue behind both (`gen1 -> gen2 -> vis1 -> vis2`). |
| - Tab 1's `Result` stays on "Waiting for output..." far longer than its own work takes β its rendering is blocked while tab 2's nodes run. |
| - While any node is running, the whole app is unresponsive for everyone (page loads stall too). |
|
|
| Root cause: each canvas node runs via `POST /gradio_api/component_server/`, whose handler calls the synchronous workflow server functions directly on the asyncio event loop, with no threadpool offload. One running node therefore blocks the entire server process. |
|
|