Static Pipeline Split (2-GPU DiT)
Stop shuffling weights between your two GPUs
- model
- model
Multi-GPU in ComfyUI usually means dynamic sharding: a pack like ComfyUI-MultiGPU's DisTorch streams weight blocks between your cards on demand, trading PCIe bandwidth for capacity. That works fine on safetensors. It gets ugly on packed quantized weights - int8 ConvRot, GGUF - where the quantized tensors live behind a virtual-VRAM ledger. Anyone who's watched a 34 GB int8 video DiT hard-crash mid-prompt knows the shape of it.
StaticPipelineSplit is a single node that takes the other route: split the transformer once at load time, then never move a weight again.
It's a two-GPU node, not an N-GPU one, and it's brand new - zero footprint on r/comfyui, an anonymous GitHub handle. So treat it as a targeted fix for a specific crash class rather than a general accelerator.
The mechanism, briefly
You drop it after your DiT loader: UNETLoader → StaticPipelineSplit → sampler. The node clones your MODEL and arms monkey-patches that fire when it actually loads:
partially_loadbecomes a no-op,partially_unloadreports memory freed that it didn't free, andunpatch_modelcan't touch weights. The DiT becomes load-bearing furniture - nothing in ComfyUI's memory manager evicts it partway through a run, which is what stops a VAE load from unpatching your quantized blocks underneath you.- Blocks are placed by byte budget:
Non cuda:0, the rest on cuda:1 - the README's example is 23/27 on 2× 20 GB cards. Only activations cross PCIe per step, at the block boundary (~140 MB there), never the weights.
For long clips the weights don't grow but activations do, so it drops into a hybrid residency mode: a couple of hot blocks stay pinned per card while the rest live on CPU as lossless packed-int8 copies and stream in for the duration of their own forward pass. That's the ~1 s/step overhead the README measures; the frames profiles choose where on that curve you land.
There's also activation-space LoRA (y = W·x + α·B(A·x)), which keeps weights packed instead of forcing the usual dequantize-patch-requantize cycle every layer every step - the tax that makes LoRAs miserable on quantized models, and the reason ConvRot int8 was still finishing LoRA support at the July 2026 corpus edge.
The four fields you actually set
model(required, MODEL) - straight off your loader.frames(INT, default 0, max 4000) - the length of one sampling pass, not the total of a multi-segment Director chain. Pass the chain total and you'll over-stream the model, which is the crash class the node exists to avoid.0means "unknown" and picks the short, all-resident profile.primary_gb/secondary_gb(FLOAT, default 0) - weight budget in GiB for cuda:0 and cuda:1, for asymmetric pairs like a 3090 + 4090. The tooltips are explicit: set both or neither, and the code enforces it - give it only one and it logs a warning and ignores you. Rule of thumb: VRAM minus ~4 GB of activation headroom.
Output is a single model. Wire it wherever the loader's MODEL used to go. Nothing else changes in your graph.
One thing the README table hides: the shipped code has four tiers, not three - <110 all-resident, 110–191, a dedicated 192–259 band that gives both cards more activation room, and ≥260. The extra split exists because a 243-frame chained segment OOM'd on device 1 with the mid-tier budget.
Installing it
No pip step, no model downloads, no requirements.txt. It's pure Python that patches ComfyUI at import. Manager may or may not find it; the manual route always works:
cd ComfyUI/custom_nodes
git clone https://github.com/ylzbj1-stack/ComfyUI-StaticPipeline
# restart ComfyUI
(The README still shows a https://github.com/<YOU>/... placeholder in that command. Use the real URL.)
Then launch with these - the author calls the second one mandatory:
MGPU_CPU_THRESHOLD_PERCENT=999 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
There are three optional patches in patches/, applied with git apply <file> from your ComfyUI root: an adaln table cache that fixes ~496 MB of duplicate tables per forward (a real win even single-GPU), in-place support in weight_adapter/bypass.py that the chunked LoRA needs, and a Windows cudart64 fix for ComfyUI-MultiGPU. Patching core means re-applying after every update.
Where it bites
Placement is one-shot per loaded model. Change your frame tier and you need to restart the instance, not just re-queue. The second submission on the same instance skips reload and Triton recompile - the README's "~5.7 min saved per clip" figure is exactly that cache hit.
Windows + WDDM caps you around 19 GiB per 20 GB card, and SageAttention allocates a ~514 MiB fp32 temporary over the full key tensor, scaling with frames. That's the biggest OOM trigger on long clips and it has nothing to do with the split.
The video VAE will not fit alongside the DiT on 2× 20 GB. It runs lowvram-streamed, which is expected - but give the VAEs ~3 GiB of headroom anyway, because the author measured decode dropping from 137 s to 46 s that way. Moving the audio VAE to cuda:1 does not work: that ledger only registers device 0.
Because it hooks deep into the patcher and ships a bespoke crash class as its sales pitch, test it on a short clip before you point a production chain at it.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| frames | INT | 00–4000 | — |
| primary_gbopt | FLOAT | 0.00–160 | Asymmetric GPU pairs: weight budget (GiB) for cuda:0, leaving the rest of that card for activations. Set BOTH this and secondary_gb, or leave both 0 to use the profile budgets. |
| secondary_gbopt | FLOAT | 0.00–160 | Weight budget (GiB) for cuda:1 on asymmetric pairs. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |