Patch Sol-Attn (SGLang)
The most opinionated attention node in the pack
- model
- MODEL
Kijai's Sol-Attn is the aggressive one in the attention family: instead of making attention faster at the same quality like Flash or Sage, it only keeps a small fraction of attention blocks exact and approximates the rest, trading output fidelity for speed you can actually feel. This node is the worker-native version for H3 - same idea, but the attention runs inside the SGLang workers where the H3 transformer actually lives, not in a host-side patch that never reaches it. It's also comfortably the most parameter-heavy node in this pack. If that sounds like a lot to look at, the defaults are sensible; you can run it with just tau and start_percent and still get the point.
The inputs that actually matter
Full list in the node, but a beginner sets these:
tau(default 1.3) - the sparsity threshold, and the single most important knob. Higher is sparser, and the tooltips give you the exact trade: 1.0 keeps ~16% of blocks exact, 1.5 ~7%, 2.0 ~2.7%. Below ~1.0 you're barely approximating anything.start_percent(default 0.2) andend_percent(default 0.9) - attention runs dense beforestart_percent(early denoising is fragile; the paper uses 0.2) and afterend_percent(the final polish pass).min_tokens(default 4096) - sequences shorter than this stay fully dense.sink_conditioning(defaultexact_kv_and_rows) - H3-only: keeps the packed text/audio/reference conditioning rows exact.exact_kvis cheaper (~3% overhead),exact_kv_and_rowsalso runs those query rows dense, making the generated audio stream exact (~20% overhead). Leave the default unless you're chasing every last second.dense_blocksand the optionaltau_profile- power-user territory: force specific transformer blocks to stay dense (0-2,-1style ranges) or give per-block tau values via a multiline text node. First and last blocks are the most approximation-sensitive, which is why they're called out.
The INT8 toggles (int8_qk, int8_pv) quantize the exact branch - the tooltip's claim is they're basically free at tau ≤ 1.5 but a net loss at tau ≥ 2.0 where the quantize pass outweighs the shrinking exact branch. use_tma needs SM90+ and Triton 3.3+ and is off by default because it hasn't measured faster on any tested GPU.
The trap: morton is off
The one hard failure mode is spelled out in the code: morton is not supported yet. Enable Morton token reordering and the node raises NotImplementedError and stops - cleanly and clearly, but it stops. Leave it false. The morton_curve choice (2d_frame vs 3d) only matters if you could enable it in the first place, so don't touch it on this pack version.
Installing it
Shared pack install (Manager, "H3 SGLang Pack", or git clone https://github.com/TensorClay/ComfyUI-H3-SGLang-Pack.git into ComfyUI/custom_nodes, restart), plus one sibling dependency that's easy to miss because it's not a pip install:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/kijai/ComfyUI-SolAttn_triton.git
The Sol-Attn provider has to sit beside this pack in custom_nodes - the pack looks for ComfyUI-SolAttn_triton at a fixed relative path and needs its Triton kernel files. Miss it and the worker has no Sol-Attn to call.
Worth it?
The README's benchmark gives Sol-Attn the best warm-run number of the three attention options (35.82s vs 37.33s for automatic) on a light workload - a real but modest edge, and it's the option whose whole point is scaling that win up with sparsity. For a heavy H3 render where a 33B model's attention is the dominant cost, that's the case where it earns its complexity. Same note as the other two attention nodes: changing attention settings restarts the worker pool, so your next generation pays a cold-start cost.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| tau | FLOAT | 1.300–4 | Threshold beta. Higher is sparser: 1.0 ~ 16% of blocks kept exact, 1.5 ~ 7%, 2.0 ~ 2.7%. |
| start_percent | FLOAT | 0.200–1 | Run dense before this point. The paper uses 0.2. |
| end_percent | FLOAT | 0.900–1 | — |
| min_tokens | INT | 40960–1048576 | Sequences shorter than this stay dense. |
| int8_qk | BOOLEAN | true | INT8 QK in the exact branch (Sage-style: smoothed K, per-token scales). Measured free in quality; helps at tau<=1.5, a net loss at tau>=2.0 where the quantize pass outweighs the shrinking exact branch. |
| sink_conditioning | COMBO | exact_kv_and_rows | MiniMax-H3 only. exact_kv: every query sees the packed text/audio/reference rows exactly (~3% cost). exact_kv_and_rows: also runs those query rows dense, making the generated audio stream exact (~20% cost). No effect on other models. |
| morton | BOOLEAN | false | Reorder video tokens into Morton (Z-order) so each 64-token block is a compact 3D neighbourhood instead of a 2-row strip, which makes routing far more accurate at a given density. Exactly neutral for dense attention. Wan and MiniMax-H3 only; logged and skipped elsewhere. |
| morton_curve | COMBO | 2d_frame | 3d interleaves t/h/w equally. 2d_frame Z-orders within each frame and leaves frame order alone -- use it when the temporal axis is not uniformly spaced (MiniMax-H3's frame spacing is non-uniform; try this if 3d degrades at some frame counts). |
| int8_pv | BOOLEAN | true | Also run the exact branch's P@V in INT8, with a per-row P scale and per-channel V scale. PV and QK cost the same, so this is the other half of the int8 win. Only applies when int8_qk is on. |
| verbose | BOOLEAN | false | — |
| use_tma | BOOLEAN | false | Use the TMA descriptor kernels instead of the pointer ones. Descriptors address strided inputs directly, so this no longer copies q/k/v and peak VRAM matches the pointer path. Off by default because it has not measured faster on any tested GPU. Requires SM90+ and Triton 3.3+; ignored otherwise. 'verbose' logs the path used. |
| dense_blocks | STRING | Transformer blocks to keep dense, e.g. '0-2,-1' for the first three and the last. Negative indices count from the end. The first and last blocks are the most approximation-sensitive: their error reaches the output with no later block to absorb it. Empty means sparsify all. | |
| tau_profileopt | STRING | Per-block tau, overriding the base value. 'blocks=tau' entries separated by ';' or newlines, so a multiline text node works: '0-30=2.0' then '39-42=0.9'. '#' starts a comment. Block sensitivity varies several-fold across depth, so one tau either over-serves the insensitive blocks or under-serves the fragile ones — use the Block Probe to find them. Leave unconnected for a single tau everywhere. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |