H3 MS VAE Split Decode
Splitting the H3 Decode Across GPUs
- vae
- gpus
- VAE
The split transformer gets the attention because that's where the minutes are. But H3's decode tail isn't nothing - a 192-frame scene spends about 51 seconds on decode, audio and muxing, and unlike sampling it's a fixed cost you pay after you've watched the progress bar hit 100%. Splitting that across cards took it to 34 seconds. Smaller win, less glamorous, and it's the kind of dead time that makes you stop iterating.
H3 MS VAE Split Decode does exactly one thing: it decodes H3 video latents with the temporal chunks spread over several GPUs. Same input, same output, same pixels.
Why the VAE splits so cleanly
The H3 video VAE already decodes in overlapping temporal chunks. Each chunk goes through the decoder independently - any spatial tiling happens inside the chunk, and chunks don't share state. The only coupling is the ordered overlap blend at the end, which writes into the output buffer in chunk order.
That's almost embarrassingly parallel, so the node does the obvious thing: with N GPU ranks, chunk i belongs to rank i % N. Rank 0 is ComfyUI's own process on the VAE's device; every other GPU gets a persistent worker process, and each worker receives all its chunks as one job up front. ComfyUI's process decodes its own chunks and replays the blend-and-write loop, taking each worker's chunks as they arrive.
Processes, not threads, and that's not a style choice. The pack's own measurement: two threads in one process came out at ~24 seconds against 19.3 for a single GPU, because Python's GIL starved both cards. A worker process gets its own GIL, its own CUDA context and its own CUDA_VISIBLE_DEVICES.
Decoded chunks come back through POSIX shared memory - or, when /dev/shm is too small to hold them, over each worker's authenticated socket instead.
Inputs and output
vae is the H3 video VAE, after Select VAE Device. The output is a VAE that feeds VAE Decode and MiniMaxH3ImageToVideo's vae input, same as if this node weren't there.
enabled (default on) falls back to a single-GPU decode. That's a genuinely useful A/B switch rather than a formality: set it off and compare.
second_gpu is the CUDA index of the second GPU, -1 for automatic - and it's ignored the moment you connect a GPU set from H3 MS GPU Set, so don't set both.
The optional gpus input takes that GPU set. The optional max_gpus (default 4, max 8) caps how many GPUs decode, counting ComfyUI's own process as one. Don't raise it expecting free speed: a 192-frame clip has 11 chunks and the ordered blend runs on one GPU, so the gain flattens after three or four cards. The default of 4 is the honest ceiling, not a conservative one.
Install
Ships with the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/martonsagi/Comfy-H3-MultiStream ComfyUI-H3-MultiStream
Restart; it's under advanced/latent. No Python dependencies beyond what ComfyUI installs, but this node requires Linux - the worker transport uses AF_UNIX sockets and POSIX shared memory. On Windows, run the rest of the pack and expect a single-GPU decode.
Where people get burned
The most common one in containers: /dev/shm defaults to 64 MB in Docker, which is far too small for decoded chunks. You'll see a warning about chunks returning over the worker sockets instead of shared memory. It still works and stays bit-identical, just a little slower. Fix it properly with:
docker run --shm-size=8g ...
or, in Kubernetes, an emptyDir with medium: Memory mounted at /dev/shm.
VAE worker on GPU N did not connect or exited with ... means a worker died. Each one writes a timestamped vae-worker-gpu<N>.log in a private temp directory - the console prints the path when the worker starts, and Show status lists it. The last lines also go to the console. The worker restarts on the next decode, or you can release it deliberately from the menu or with H3 MS Release Resources.
Two resource notes that matter in combination with the rest of the pack. Each worker's card needs roughly 5.2 GiB free for the decode, which is why H3 MultiStream's vram_reserve_gb default sits at 2 GB - raise it if the split decode starts coming up short on a card the transformer split has already filled. And a worker release is refused while a decode is genuinely in progress, so a script hammering the release endpoint mid-render will get told no rather than get a corrupted frame.
First decode after starting ComfyUI is the slow one: the workers have to start and load the VAE, and there's a start timeout (300 seconds by default) for exactly that. After that they stick around until ComfyUI exits.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| vae | VAE | — | |
| enabled | BOOLEAN | true | — |
| second_gpu | INT | -1-1–15 | CUDA index of the second GPU; -1 = automatic. Ignored when a GPU set is connected. |
| gpusopt | H3MS_GPUS | GPU selection from H3 MS GPU Set. Without it: every visible GPU (or second_gpu). | |
| max_gpusopt | INT | 41–8 | At most this many GPUs decode (ComfyUI's process counts as one; each other GPU runs a worker process). The gain flattens after 3-4 GPUs. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| VAE | VAE | — |