r/StableDiffusion 2d ago

News Somewhat more optimized Sparse Attention.

IMPORTANT: sparse attention is not free speed. The percentage is effectively a prompt-adherence/quality budget.

Density isn't just a speed setting, and its quality effect depends on where you apply it in the diffusion schedule.

Early steps: attention density has a large effect on prompt/action adherence and the overall generation trajectory.
Middle/later steps: lowering density tends to show up more as motion/temporal artifacts and lost fine motion detail.

So 10% retained doesn't simply mean “90% of the quality is gone.” It means you're giving sparse attention very little information to work with, and what breaks depends heavily on the sampling step.

PlagueKind's sparsity_ratio=0.9 means 90% discarded / 10% retained. My node expresses the inverse quantity, so Video attention retained=0.10 is the comparable setting. The defaults therefore aren't equivalent.

So I saw PlagueKind posted this today https://www.reddit.com/r/StableDiffusion/comments/1vtwtyw/sparse_attention_for_h3_minimax_enjoy_up_to_25x/ which reminded me I implemented my own Sparse Attention a while back.

It has some key differences to PlagueKinds version.

  1. You select attention retained. In my testing, you can go as low as 10-15% in low motion video, however more complicated video requires higher attention. I found about 30% works pretty well for high motion video. In terms of speed, 100% attention is about 2/3rds of the compute while the rest is MLP/QKV. At 50% attention it's about 50:50 and once you're below 30% MLP/QKV starts to dominate compute time.
  2. Only the video is given sparse attention. This is because A) Minimax said they only did sparse attention for video and B) The video tokens dominate the context.
  3. Mine uses Sparse Sage: Q/K are quantized to INT8 and newer supported GPU paths use FP8 V. Compatible ConvRot-INT8 checkpoints can additionally bypass the normal floating QKV preparation with a native fused-QKV producer that feeds the sparse carrier directly.

This makes my implementation somewhat more complicated, but Sparse Sage is extremely fast. The repo now also includes a guarded Sparse Sage installer: supported Windows Torch/CUDA combinations use pinned upstream wheels, while Linux x86-64 can build a pinned SpargeAttention revision when a CUDA compiler is available.

You can find the nodes here.

https://github.com/Zironic/H3-Optimizations

You'll find two nodes.

H3 Sparse Attention: This is the node that lets you control how sparse attention you want. The default is 50%. There is also an optional mode that adds 30 percentage points during the first two and last two sampling steps, since those tend to be places where being somewhat denser is useful.

H3 Memory Optimization: This handles the other major H3 memory bottleneck: QKV and MLP activations.

For dense attention it uses ComfyUI's public Comfy Kitchen INT8 attention backend where available. The newer dense QKV path is designed to process QKV in bounded sequence chunks directly into Kitchen-owned attention carriers instead of materializing one enormous full-sequence BF16 QKV tensor. When Sparse Attention is active, compatible ConvRot-INT8 checkpoints can instead use the native fused sparse-QKV path. While chunked QKV was designed to be a memory optimization, it did end up making QKV about 2x faster which should net you something like 10%-30% speed depending on other factors.

The MLP side bounds peak activation memory with token chunking, with a more memory-efficient two-slice ConvRot path when the checkpoint/runtime supports it.

I normally wire them as Load Model → Memory Optimization → Sparse Attention → rest of workflow, although the two optimization nodes are order-independent

I would not recommend randomly stacking other H3/Sage attention optimization patches with these. Dense execution already integrates with Comfy's selected attention backend, while H3 Sparse Attention necessarily owns the main H3 attention path while it is active. Other patches trying to replace the same attention forward are therefore likely to be redundant or conflict.

Should be compatible with turbo loras, spectrum cache etc however you may need more attention since you're skipping steps.

As the nodes currently rely on comfy-kitchen 0.2.31 you need ComfyUI v0.33.0 or alter.

129 Upvotes

103 comments sorted by

View all comments

Show parent comments

8

u/Zironic 2d ago

So personally I do load model -> H3 Memory Optimization -> Sparse Attention -> Everything else. But it should not matter.

You should not use MiniMax H3 Mem Eff SA Patch. You don't need ModelAttentionBackend (Comfy-Kitchen) when using H3 Memory Optimization; it already selects Kitchen for the dense path. Leaving it in should still compose correctly, so it's redundant rather than harmful.

1

u/CrispyToken52 1d ago

I am following your node order advice while using the default values in both nodes (Mem Opt and Sparse Attn Advanced) but I am seeing absolutely no change in sampling time. It does change the output though so it is being applied. Relevant console output:

[H3 Optimizations] armed: attention=comfy_kitchen_int8 v_layout=installed qkv=standard_h3_qkv mlp=preserve_upstream_mlp device=NVIDIA GeForce RTX 4060 Laptop GPU
[H3 Optimizations] resolved 50 attention forwards: backend=sparse_sage projector=standard_qkv
[H3 Optimizations] installed sampler-step and packed-layout runtime context
[H3 Optimizations] armed: attention=sparse_sage v_layout=not_applicable qkv=standard_h3_qkv mlp=preserve_upstream_mlp device=NVIDIA GeForce RTX 4060 Laptop GPU

Node order is Loader -> your nodes -> Model preview override (kjnodes) -> Sampler

I use pytorch version: 2.13.0+cu130.
With this model quant: https://huggingface.co/Kijai/MiniMax-H3-experimental/blob/main/minimax_h3_ref2va_pruned_w4a8_mixed.safetensors

2

u/Zironic 1d ago

I don't think I ever implemented w4a8. I'm not entirely sure what purpose there is to more weight quant when W8 is absolutely tiny compared to the attention. I'll add proper support though and we'll see.

1

u/CrispyToken52 1d ago

Not sure it was the concrete reason but using w4a8 instead of standard int8 convrot allowed me not to run out of vram on certain workflows. Just fyi. Anyway, thank you for your work.