Distributed Image List Start
Turn a pile of images into a work queue for every GPU you own
- images
- mask
- values
- image
- mask
- item_index
- context
- value_1
- value_2
- value_3
- value_4
- value_5
- value_6
- value_7
- value_8
- value_9
- value_10
You have 300 images to run through a slow per-image pass. You have two GPUs, and one of them is a lot worse than the other. Chunking the list 150/150 sounds fair until you watch the fast card sit at 0% for the last twenty minutes, because it finished its share and has nothing to do. That idle-tail problem is exactly what Distributed Image List Start exists to kill.
What it actually is
This is the opening half of a paired region. You put Start before your per-image work, Distributed Image List End after it, and a single context wire between them. Everything inside the region runs once per image, and the scheduling across your master GPU, your local/remote workers and compatible cloud pools is a shared pull queue - whoever frees up first takes the next source image. Faster participants simply do more of the list, and End hands results back in the original input order, not completion order.
That last bit matters more than it sounds. In the classic Distributed setup you wire Distributed Seed → sampler and Distributed Collector → after VAE Decode, and every participant runs the whole workflow with a different seed. It works, but the collector waits for the slowest participant - the imbalance complaint that follows every multi-GPU Comfy thread. The image-list region is the newer answer: same idea, work-stealing instead of fixed shares. And to head off the usual confusion - none of this pools your VRAM or makes one image render faster. It's throughput, not horsepower.
The inputs worth touching
images is the one that matters. Feed it an IMAGE batch or a ComfyUI image list; each frame becomes one job. A batch is split into individual frames rather than handed over as a tensor, which is the whole point.
Then there's mask and value_1 … value_10, which follow one rule you should internalise: 1 value is shared by every image, or exactly one value per image. Two values for five images is an error, not a silent repeat - the node never pads or recycles. Only value_1 is visible at first; connecting it reveals value_2, and so on up to ten. Each one accepts an image, mask, string, int, float or boolean, which is how you drag a filename, a prompt, a strength or a seed through the region per item.
Note the asymmetry: a batch on a value input stays one value, so a 2-image batch on value_1 travels with every job - handy when each source image needs the same references.
The outputs
image, mask and item_index (zero-based) are your per-item inputs inside the region; context is the execution reference that must be wired directly into the paired End - it's a dedicated DISTRIBUTED_IMAGE_LIST_CONTEXT socket, not editable text. The value_N outputs mirror whichever value_N inputs you connected, same type, and unused ones are hidden. Anything you want to keep downstream has to leave through End, not from Start.
Install
ComfyUI Manager → search ComfyUI-Distributed, or:
cd ComfyUI/custom_nodes
git clone https://github.com/robertvoy/ComfyUI-Distributed.git
# restart ComfyUI
No models, no extra pip dependencies - the pack's requirements are empty, which is unusual and pleasant. If you're using remote or cloud workers, launch the master with --enable-cors-header, then follow the pack's worker setup guide. Master and every direct worker need the same feature-capable version, so this isn't a "update the master and forget the tower in the corner" situation.
Where people get burned
- Put preview and save nodes after End. Only the enclosed region is distributed; list creation and saving stay on the master.
- You can't ship models across the wire. Values that can't be transported exactly - models, latents, conditioning - are rejected. Loaders go inside the region, connected directly to your processing nodes, and every participant needs those files locally.
- The list is materialised up front, capped at 4,096 frames. Not streaming input, so "point it at a folder of 40,000" isn't this node.
- Direct-worker returns are capped at 50 MiB per tensor. 4K float32 RGB comes out over that before base64 encoding, so mixed master/worker 4K upscaling can't use this path - and nothing gets quietly downcast to fit.
- Nested regions are rejected, and Collector/Distributed Upscale nodes can't share a prompt with a region in this first version. Chain regions sequentially instead.
Workflow shape: batch → Start → your processing → End → preview/save. Enable your workers in the Distributed panel, then queue. Driving it from a script? Submit through /distributed/queue, not a plain /prompt - an ordinary all-output request doesn't get the region's relaxed execution rules.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| imagesopt | IMAGE | Image list or image batch; each frame becomes one job. | |
| maskopt | MASK | 1 mask shared by every image, or one mask per image. | |
| valuesopt | COMFY_AUTOGROW_V3 | — |
Outputs (14)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| item_index | INT | — |
| context | DISTRIBUTED_IMAGE_LIST_CONTEXT | — |
| value_1 | * | — |
| value_2 | * | — |
| value_3 | * | — |
| value_4 | * | — |
| value_5 | * | — |
| value_6 | * | — |
| value_7 | * | — |
| value_8 | * | — |
| value_9 | * | — |
| value_10 | * | — |