Model (TurboQuant Attention)
An LLM-Serving Trick, Transplanted to Diffusion
- model
- MODEL
Here's the honest summary before you get excited: this node clones your model and installs an approximate attention implementation inspired by the TurboQuant paper - random orthogonal rotation of q/k/v plus coordinate-wise scalar quantization. It is not KV-cache compression, it is not a memory-savings hack that fell out of an LLM inference engine, and the defaults are deliberately conservative because aggressive settings can damage image quality and run slower than baseline. If that still sounds interesting, read on.
It's an experiment, and the pack is upfront about that. The idea is the same one TurboQuant used to make attention cheaper in LLM serving: rotate the key/query space with a random orthogonal matrix (which makes the values spread more evenly), then quantize to fewer bits per coordinate, trading a little accuracy for speed or memory. In ComfyUI this is done as an attention override you slot between your model loader and a normal KSampler - no core patching, no special sampler.
How it works
At runtime the node rotates q, k, and v, quantizes k (and optionally v), then passes the transformed tensors back into ComfyUI's original optimized attention kernel. That last bit matters: it deliberately avoids materializing dense logits in Python, which is what made earlier prototypes OOM on diffusion-sized layers. The QJL residual-correction stage exists in the config but is forced off in the runtime path for the same reason. Guards (min_token_product/max_token_product, memory_margin_mb, max_head_dim) decide which attention calls actually get patched - most won't, which is by design.
The inputs that matter
You're not going to touch most of these, and that's fine. The ones that matter:
bits- bits per coordinate (1–8, default 8). Lower is more aggressive and more dangerous.quantize_values- keepdisable. Quantizing values as well as keys is the fastest route to wrecked output.attention_scope-selfis the usual target for diffusion latent attention.log_every- set to1(andlog_fallbackstoenable) to actually see whether your attention calls are being patched at all.
Output is a MODEL you feed into a KSampler.
Installing it
Part of the Skoogeer-Noise pack. Manager → search "Skoogeer-Noise", or:
cd ComfyUI/custom_nodes
git clone https://github.com/ttulttul/Skoogeer-Noise
Restart ComfyUI. Only torch, numpy>=1.26, einops, pyyaml>=6.0.3 - no model downloads.
Common gotchas
The biggest one is expectations. People hear "TurboQuant" and expect LLM-serving-style speedups and VRAM savings; this is an attention approximation for diffusion, with quality tradeoffs baked in. If output looks subtly off and you can't tell why, the patch is probably active and degrading things. If nothing changes at all, that's also likely - the token-product thresholds skip most layers. Use the logging knobs to find out which. And treat bits <= 4 as "here there be dragons": the changelog itself warns these settings can be slower than baseline while also hurting quality. This is a tinkerer's node, not a daily-driver.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | Model to clone and patch with a TurboQuant-inspired attention approximation. | |
| bits | INT | 81–8 | Bits per rotated coordinate for the scalar quantizer. Higher is safer for image quality; lower is more aggressive. |
| qjl_dim | INT | 641–4096 | Projection width for the QJL-style residual correction on logits. |
| use_qjl | COMBO | Enable the 1-bit residual correction term for key logits. Currently forced off in the runtime path. | |
| quantize_values | COMBO | Quantize values as well as keys. Disable is safer for image quality and is the default. | |
| min_token_product | INT | 655360–1073741824 | Only patch attention calls where query_tokens * key_tokens meets this threshold. |
| max_token_product | INT | 2621440–1073741824 | Skip attention calls above this query_tokens * key_tokens threshold. Conservative default avoids the largest, most memory-sensitive layers. |
| attention_scope | COMBO | Which attention calls to patch. | |
| layer_start | INT | -1-1–4096 | First transformer block index to patch. -1 disables the lower bound. |
| layer_end | INT | -1-1–4096 | Last transformer block index to patch. -1 disables the upper bound. |
| rotation_seed | INT | 00–18446744073709550000 | Seed used for the random orthogonal rotation and Gaussian residual projection. |
| max_head_dim | INT | 2561–4096 | Skip heads larger than this to avoid excessive projection overhead. |
| force_fp32 | COMBO | Cast q/k/v to fp32 inside the override for extra numerical stability. | |
| memory_margin_mb | INT | 10240–65536 | Keep this much free CUDA memory in reserve before allowing the TurboQuant workspace allocation. |
| log_every | INT | 500–1000000 | Emit a TurboQuant runtime summary every N attention calls. Set 1 for per-call summaries, 0 to disable periodic summaries. |
| log_fallbacks | COMBO | Log individual skip/fallback reasons when TurboQuant does not activate. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |