H3 LBH Automatic FFN Chunks
The switch that keeps the last H3 step from eating your VRAM
- model
- MODEL
This node exists because of one awkward fact about the workflow it ships in. You generate three MiniMax H3 steps at a small latent size, upscale, then finish the fourth step at 544×960 - and that fourth step has the most tokens of anything in the graph. The feed-forward block is where the peak VRAM goes, and it's the thing that decides whether a 12GB card finishes or dies at 95%.
So: H3 LBH Automatic FFN Chunks patches the model so each block's FFN computes in row chunks, with a different chunk count for the low-resolution pass than for the high one.
How it works
It's a model patch, not a sampler setting. The node clones your MODEL, grabs diffusion_model.blocks, and replaces every block's mlp.forward with a version that looks at how many rows it was handed:
- rows ≤
seq_threshold, or a chunk count of 1 → run the native fused SwiGLU op in one shot. - otherwise →
torch.chunkthe rows, run each slice through the same fc1/fc2 pair, and write the results into one output tensor.
Which chunk count you get depends on split_rows: at or below it you use low_chunks, above it high_chunks. The defaults (1 low, 8 high, split 8192, threshold 4096) mean the small pass is effectively unchunked and the high-res pass is split eight ways. That's the "one chunk up to 8192 rows; eight above; threshold 4096" line in the pack's own component table.
Why bother? In a SwiGLU FFN the intermediate is wider than the hidden size, so peak memory scales with rows × intermediate. Chunking doesn't change total maths, it changes how much of that intermediate is resident at once. You're trading extra kernel launches for a lower peak - the standard bargain, and the reason this costs a few percent of speed to buy headroom. Both the repo and the ComfyUI side of this are unremarkable plumbing; the pack credits the chunking idea to its own ComfyUI-H3-X2-Stream and to kijai's KJNodes MiniMaxChunkFeedForward.
The inputs that matter
model is the only required wiring. In the shipped example it's the second node in the chain - loader → this → the SLA node → QKV reuse → sigma shift → pad → samplers - which is a good place for it, because it should see the same model object everything downstream sees.
The four integers are the whole tuning surface, and honestly you should leave them alone. low_chunks 1 says "don't bother at low resolution". high_chunks 8 is the author's validated number; drop it to 4 if the high pass still OOMs, accept that it gets slower, and go up toward 16 only if you have headroom and hate waiting. split_rows is the boundary between the two, seq_threshold the point below which chunking is pointless. Output is a single MODEL wire.
Install
ComfyUI Manager: search H3 LBH X2 Stream (registry id h3-lbh-x2-stream), install, restart. For the full examples you also want the sibling H3 X2 Stream, which provides the INT8 X2 decode and the saving node. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/sepiablue-ai/ComfyUI-H3-LBH-X2-Stream
then restart ComfyUI. The pack's real Python requirements are small - einops>=0.8.0 and safetensors>=0.7.0; av and comfy-kitchen come in through X2 Stream's own requirements, not this one. What it does need is a recent ComfyUI: the whole pack assumes native H3, SLA, dynamic VRAM, ConvRot W4A4 and Sol-Attn, and the author validated on 0.38.0/0.39.0. Models are not bundled and not downloaded - MATLOW fused INT8 H3, a Qwen3-VL NVFP4 text encoder, three VAEs and the LBH 3D FP16 upscaler all go in by hand.
Common issues
"H3 Resolution Chunk FFN requires a MiniMax H3 diffusion model." You fed it something that isn't the H3 DiT - a different checkpoint, or a MODEL wire from a loader you didn't mean to use. It checks that every block has mlp.fc2 before patching anything, so this is a clean early failure rather than a weird crash mid-sample.
Do not stack a second FFN chunker. If you also run ComfyUI-H3-X2-Stream's FFN node or KJNodes' MiniMaxChunkFeedForward, both write to the same mlp.forward attribute, so they don't nest into double savings - keep one.
It won't fix an OOM that isn't the FFN. This patch touches the feed-forward path only. If you're still short of memory during the high-res step, the lever is the other direction: lower the handoff target size, or reduce cache_mib on the QKV node. The pack's own numbers were measured on a 12GB 4070 with roughly 48 GiB of system RAM, which is a useful reminder that H3 wants a lot of host memory no matter how well you chunk.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| low_chunks | INT | 11–64 | — |
| high_chunks | INT | 81–64 | — |
| split_rows | INT | 8192256–262144 | — |
| seq_threshold | INT | 4096256–262144 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |