Nodes/ComfyUI-ZML-Image/ZML_多线程子工作流
ComfyUI Node

ZML_多线程子工作流

Run a sub-workflow 64 threads at a time — ComfyUI's threading workaround

By zml-w·Created about a year ago·Updated 2 months ago· 218
ZML_多线程子工作流
  • 变量包
  • 图像列表
  • 任意数据列表
  • 执行状态
JSON工作流
执行次数1
并行线程数1
执行完成后清理缓存true
返回图像开启
控制台日志开启

ComfyUI has a famous weakness: a graph executes node-by-node in a single pass, so "do this same cheap thing 300 times" runs sequentially and takes forever. ZML_ParallelJsonContainer is the author's workaround - paste a workflow (in API JSON form) into the node, tell it how many times to run and on how many threads, and it fans the jobs out across a ThreadPoolExecutor. The README names the motivation outright: it exists "to solve ComfyUI's inability to multithread," with examples like running 32 threads to watermark images in parallel, or 8 threads calling an image API concurrently.

Before you get excited about parallelizing your FLUX sampler: read the limits. The node runs sub-workflow nodes directly in worker threads, so it only works for API-call nodes and pure-logic nodes - anything that loads models or touches CUDA concurrently will thrash or crash. The README says this explicitly. It's a concurrency tool for the parts of your workflow that are I/O-bound or trivial, not for GPU sampling. For the API-call case it's genuinely great - your 300 image-API requests go out in parallel instead of one at a time.

How it works

  • JSON工作流 - paste a workflow in ComfyUI's API format. You get this from a workflow JSON by stripping the UI layout (or from the "Export (API)" menu). Placeholders like {{变量名}} get substituted per-run.
  • 执行次数 (1–3000) - how many times to run it.
  • 并行线程数 (1–64) - max concurrent threads.
  • 执行完成后清理缓存 (default on) - after all jobs, run the full cleanup (unload models, gc, empty CUDA cache). The tooltip adds a useful warning: keep it on, especially if you disable returning images, or the cleanup can be ineffective.
  • 返回图像 (开启/关闭) - whether to collect output images. Disable it when you only want the side effects, which saves a lot of memory.
  • 控制台日志 - per-task success lines on/off.
  • 变量包 (optional VAR_BUNDLE) - the variable definitions. A bundle maps a placeholder name to a variable type: list (cycle values by index), math_int/math_float (start + index·step), or seed (fixed / incrementing / random). You build these with the pack's ZML_ParallelVariable* nodes - e.g. ZML_ParallelVariableAny for arbitrary values.

The sub-workflow marks its results with two special sink nodes: ZML_SubflowExportImage (emits the output image) and ZML_SubflowExportAny (emits arbitrary data). The container watches for those classes and collects their outputs.

Outputs: 图像列表 (list of images), 任意数据列表 (list of strings), and 执行状态 (per-task status lines, ✅/❌).

When it shines and when it doesn't

Shines: parallel HTTP calls (this is the big one - the README's "8 threads calling the banana API" example), batch watermarking, anything that's waiting on I/O. Doesn't shine: GPU sampling, model loading, video decoding - anything that would collide in a thread pool. If your "sub-workflow" contains a KSampler, don't.

Install

Ships in ComfyUI-ZML-Image:

cd ComfyUI/custom_nodes
git clone https://github.com/zml-w/ComfyUI-ZML-Image
# restart ComfyUI

or ComfyUI Manager → search "ComfyUI-ZML-Image". No extra dependencies (uses Python's concurrent.futures). Chinese-first UI - 执行次数 is "execution count," 并行线程数 is "parallel threads" - translation patch at https://github.com/zml-w/ZZZ_ZML_English_Patch.

The catch that trips people: threads are Python threads, so compute-bound sub-workflow code gets no speedup (GIL), and the 执行完成后清理缓存 warning about returning images is worth reading twice - the tooltip is the author flagging a real memory leak path, not ceremony.

Categoryimage/ZML_图像/子工作流

Inputs (7)

NameTypeDefaultDescription
JSON工作流STRING
执行次数INT11–3000
并行线程数INT11–64
执行完成后清理缓存BOOLEANtrue所有任务执行完成后执行全面清理,包括卸载模型、Python垃圾回收、CUDA缓存释放,以减少工作流执行造成的内存显存残留。尽量在关闭返回图像时开启这个功能,不然可能会失效。
返回图像COMBO开启2 options: 开启, 关闭
控制台日志COMBO开启2 options: 开启, 关闭
变量包optVAR_BUNDLE

Outputs (3)

NameTypeDescription
图像列表IMAGE
任意数据列表STRING
执行状态STRING