FP8 sparse attention with complementary approximation for video diffusion.
Attention dominates the cost of video diffusion. Block-sparse attention skips most key blocks, but whatever it skips is probability mass the softmax expected, and that error grows with sparsity. Sol-Attn2 keeps the skipped part as a compressed tail. A threshold router chooses key blocks with a dynamic budget per query block. Selected blocks are computed exactly by an FP8 tensor-core kernel. Every unselected block is compressed on the fly into a fixed set of 64 surrogate key/value tokens, which join the same softmax as the exact tokens. The compensation costs one extra 64-token block per query block, whatever the sequence length. Routing and the tail work training-free; FP8 attention with an exact backward makes the op both fast and trainable, and a short distillation (QAD) adapts the model to it.
The forward and backward kernels form FP8 probabilities with no exponential instruction (ExpCast), and the backward replays exactly the bytes the forward produced. On MiniMax H3, Sol-Attn2 works training-free and improves further after lightweight quantization-aware distillation (QAD). With the LoRA merged into the weights (Sol-H3 engine) it speeds up MiniMax H3 denoising of a 12-second video by 1.97× on one GB200, and by 1.78× in the HyperFlow pipeline with the LoRA kept as separate branches. On a 1080p, 15-second video (219K tokens) at matched 10% density it denoises 2.8× faster than dense, 1.39× faster than Sol-Attn 1.0 and 1.26× faster than cuDNN block-sparse attention.
Same prompt and seed, 8-step HyperFlow sampling, 5-second clips. Left: dense attention (the teacher). Right: Sol-Attn2 in every denoising call after 400 steps of QAD, at about 11% of block pairs. Use Play both to watch the two in lockstep. Three prompts come from our held-out set; three are long multi-shot prompts from the VDN blog, used verbatim (the clips are 5 s, so later shots of those prompts may not appear).
Fitness ad: a woman seated on a gym floor flexes, then picks up a supplement container and presents it to the camera.
Watercolour and pencil concept art of a village that comes to life as the camera pushes in.
Poolside lifestyle: a woman in sunglasses sips from a water bottle against a blurred city skyline, with an on-screen caption.
Handheld photoreal: a man rides a dachshund around a skate bowl.
Night action: a motorcycle rider in a red jacket leans into a left-hand bend under amber streetlights, the camera tracking alongside.
Mixed media: a 2D-animated maid hosts a livestream inside a photoreal café.
Reference-to-video (Ref2VA) on the Sol-H3 engine: the same four reference images, LightX2V 8-step Ref2VA adapter, 1344×768, 5 s with audio. One warm transformer call takes 3.35 s dense and 2.13 s with Sol-Attn2 (1.58×; attention 1.97 → 0.84 s), so the 8-step denoiser goes from 26.7 to 17.0 s (1.57×). Left dense, right Sol-Attn2 at 10–10.5% density. No training of any kind; the reference, text and audio rows stay dense.
Starting training-free
Everything in this section works on a released model with no training. Video tokens are reordered into 4×4×4 spatio-temporal cubes, so every 64 consecutive tokens form a compact patch of the video. Attention is organised over 64×64 tiles: for a query block i and a key block j, the tile is either computed exactly, or the key block is folded into the compressed tail of query block i. Text and audio queries stay dense.
Fix one query row q with softmax scale s. Each key token t has a score. Each key block j (token set B_j, n_j=|B_j| tokens) has a weight sum and a value-weighted sum:
The attention output is a ratio of two sums over blocks, and the log of the denominator is the row's log-sum-exp:
Block sparsity computes Z_j, A_j exactly for a selected set E and skips the rest. Sparse-only attention silently replaces the denominator by \sum_{j\in E}Z_j, so the skipped mass is not just lost: the remaining weights are inflated to fill it.
The router and the tail both need Z_j without visiting every token, so they summarise a block by its mean key \bar k_j and mean value \bar v_j. Jensen's inequality bounds the block mass by its summary:
Two consequences. The count term \log n_j must be kept: 64 tokens with the same score carry 64 times the mass of one, and without the term a partial block or a small pooled unit looks as heavy as a full block. The Jensen gap, the amount by which the summary underestimates the mass, grows with the spread of scores inside the block; pooling at a finer granularity shrinks it. The router therefore pools queries and keys into groups of 8 and uses the log-mean-exp of the 8×8 pooled scores s_{ab}, plus the count term, as the block mass:
Block j holds a share m_{ij}-L_i of row i's mass, with L_i=\log\sum_j e^{m_{ij}} computed from the same estimates. One global constant ε compares that share with the uniform share 1/N_B:
A block is kept when it holds more than e^{\varepsilon}\approx1.6 times the uniform share (ε = 0.47). The constant yields about 10% density, while each query block keeps as many blocks as its attention needs: peaked rows keep a few, diffuse rows keep more. The \log N_B term lets the same ε hold across video lengths.
Instead of skipping the unselected blocks T_i, Sol-Attn2 estimates their sums (\hat Z_T,\hat A_T) and keeps them in the same normaliser:
The exact part and the tail share one denominator, so neither is renormalised on its own; in the kernel this is simply one more key block in the online softmax. With \hat Z_T=0 the formula reduces to sparse-only attention.
Building the tail. Per query block, every unselected unit u (an 8-token chunk) contributes its count, mean key and mean value. The units are split into 64 slots c, and each slot is weighted at an anchor query \bar q with the count-corrected mass from above:
The 64 surrogates (k_F^c, v_F^c, b_F^c) enter the kernel as one more key block, and every query row r reads them with its own query: s\,q_r^\top k_F^c + b_F^c = \log S_c + s\,(q_r-\bar q)^\top k_F^c. At the anchor this is the exact slot mass, count term included; away from it, it is a first-order expansion of \log Z. The tail costs one extra 64-token block per query block, whatever the video length, and in training it receives gradients like any other key block.
| Sol-Attn (1.0) | Sol-Attn2 | |
|---|---|---|
| Skipped blocks | one mean atom each | 64 surrogates, one extra tile |
| Compensation cost per query block | O(NB) atoms, grows with length | O(1): one 64-token tile |
| Token layout | raster | 4×4×4 cubes |
| Precision | BF16 | FP8 |
| Kernel | forward | forward + backward |
| Attention call, 12 s video | 46.99 ms | 19.40 ms (2.4×) |
| Denoiser, 12 s video (Sol-H3) | 29.07 s | 23.16 s (1.26×) |
Sol-Attn 1.0 also selected blocks by score above the row mean + τ·std. That rule standardises each row's scores, which removes the row's temperature: peaked and diffuse rows get similar block counts, the opposite of what their mass needs (correlation between block count and blocks needed for 70% of the mass: −0.37, against +0.57 for the share threshold). The share rule keeps the temperature because it normalises by the row's own log-sum-exp.
QK and PV run on FP8 E4M3 tensor cores. The probabilities P that feed PV must themselves be FP8. A standard kernel computes 2^{u} on the special-function unit and then converts it. We skip the exponential: read as an integer, an E4M3 byte is already a piecewise-linear base-2 logarithm, so one affine map of the score, rounded to the nearest integer, is the FP8 code of 2^{u}.
Four scores become one 32-bit word of FP8 probabilities in eight instructions: two packed FMAs, four float-to-integer conversions and two byte packs. A basis per thread group, with a sticky rebase, keeps u in range. We call this ExpCast. The row sum is accumulated from the same bytes, so numerator and denominator agree exactly.
A softmax kernel subtracts the running row maximum, so every probability is at most 1. E4M3, however, reaches 448 ≈ 28.8, and with ExpCast every value below 2−6.9 rounds to code 0. Anchored at the maximum, the format wastes almost nine octaves of headroom above 1 while flushing the long tail of small attention weights to zero, and with ~10% of tiles selected that tail carries real mass. We place the ExpCast basis a few octaves below the running maximum instead (offset 4): the largest probabilities become values up to 24 = 16, still far below 448, and four more octaves of small weights survive. Numerator and denominator are both computed from the same bytes, so the shift cancels exactly in the normalisation.
Measured on the deployed route: the FP8 error of dense attention against FP64 drops from 9.1% to 4.7%, and step-0 validation loss improves by 2.8% (paired ratio 0.972 [0.950, 0.995], 24 of 32 samples better), for about 3% more kernel time because fewer tiles qualify for the fastest rounding path. Offsets 4–7 give similar accuracy; 4 is the cheapest.
Training-free Sol-Attn2 already beats the baselines, but sparsity and FP8 still leave an error that a few hundred steps of distillation can repair. Two pieces make that possible: a backward pass that differentiates the FP8 forward as it actually ran, and a light quantization-aware distillation (QAD) recipe.
A standard FP8 attention backward recomputes the probabilities from the saved row statistics, P = \exp(S - L), in high precision. That is the gradient of a softmax the forward never computed: our forward fed PV with ExpCast bytes, sticky per-group bases and its own row sums. Training against a different function lets the student exploit the mismatch. Our backward differentiates the forward as it actually ran:
Concretely, for every tile the backward re-runs the forward's own rounding sequence to regenerate the exact FP8 bytes of P, so dV = P^\top dO uses what the forward used. For the score gradient it differentiates the continuous curve through those bytes, holding quantisation scales and bases fixed:
The tail participates like any other key block: gradients of its 64 surrogates flow back through the slot compression to the unselected keys and values. The backward runs as two deterministic passes:
The replayed probabilities are bit-identical to the forward's on every gate capture. On the deployed route the full forward + backward takes 42.3 ms (5 s) and 153.8 ms (12 s), against 43.4 / 197.4 ms for FastVideo's BF16 block-sparse Triton kernels and 96.6 / 539.8 ms for dense BF16 SDPA.
| Attention forward + backward, H56 | 5 s (ms) | 12 s (ms) |
|---|---|---|
| Sol-Attn2 FP8, full CuTe reverse | 42.3 | 153.8 |
| FastVideo block-sparse BF16 (Triton) | 43.4 | 197.4 |
| Dense BF16 SDPA | 96.6 | 539.8 |
Same measurement method; Sol-Attn2 from HSG job 7849871, references from job 7836883. Sol-Attn2 includes routing and tail construction. Its forward alone is 5.5 / 19.1 ms.
Our quantization-aware distillation (QAD) is deliberately light. The teacher is the same 8-step HyperFlow model running dense BF16 attention, live, in the same job. The student is that model with Sol-Attn2 (routing, tail and FP8 attention with its exact backward) in every attention call, plus a rank-256 LoRA as the only trainable weights. Both see the same noisy latents at exactly the eight timesteps the sampler uses, and the student matches the teacher's video and audio predictions under a relative MSE. The clean latents are clips generated by MiniMax H3 itself, so no real video data is needed. 400 steps take about 48 B200 GPU-hours.
| Method | New attention parameters | Training signal (as described by the authors) |
|---|---|---|
| SLA | linear-attention branch | fine-tuning with the diffusion objective |
| SpargeAttention2 | none | distillation-inspired fine-tuning objective, proposed because diffusion-loss fine-tuning degrades quality |
| VDN | linear memory branch, output projections, gates | staged teacher alignment, then 8-step distillation |
| Sol-Attn2 | none (LoRA only) | output matching to its own dense self at the 8 sampling timesteps, on self-generated clips, starting from an already distilled 8-step model |
Descriptions of other methods follow their papers' abstracts (SLA arXiv 2509.24006, SpargeAttention2 arXiv 2602.13515, VDN arXiv 2609.20744). Sol-Attn2 adds no modules to the network, so a model that is already step-distilled keeps its sampler; QAD only repairs the error introduced by sparsity and FP8.
Real Sol-Attn2 routes from MiniMax H3 (56 heads; 12-second and 5-second videos, 83k and 35k tokens) on one GB200, all measured in one job. Complete call starts from BF16 Q/K/V and includes everything: quantisation, routing and the tail. Kernel only times the attention kernel on prepared operands. Sparse baselines execute the same 64×64 tiles as our route.
| Attention forward, one GB200 (ms) | Complete call 12 s | 5 s | Kernel only 12 s | 5 s |
|---|---|---|---|---|
| Sol-Attn2 (FP8 sparse, incl. tail) | 19.40 | 5.46 | 13.30 | 3.37 |
| cuDNN Sage (FP8 sparse) | 41.45 | 12.32 | 16.22 | 4.06 |
| cuDNN BSA (BF16 sparse) | 31.05 | 8.05 | 22.41 | 5.17 |
| Sol-Attn (BF16 sparse, SM100) | 46.99 | 9.47 | 46.13 | 9.01 |
| VC-Attn (FP8 dense) | 68.96 | 13.37 | 67.84 | 12.64 |
| cuDNN FA (BF16 dense) | 133.29 | 24.14 | 133.29 | 24.14 |
Sparse baselines run behind our router (BF16 routing, index build and layout conversion), so the complete call compares whole attention ops on the same route. cuDNN FA is PyTorch SDPA with the cuDNN backend. All rows from one HSG job (7892561) plus the complete-call job 7893191: same q/k/v and route, CUDA-event median of 40. In kernel-only mode the cuDNN kernels execute exactly our selected tiles; cuDNN's SM100 FP8 path needs a fixed number of key blocks per query block, so it gets the mean count (equal work).
Why ExpCast matters. Both kernels below run exactly the same selected tiles; Nsight Compute reports how busy each hardware unit of the SM is, as a share of its peak.
| Nsight Compute, 12 s video, same job | cuDNN Sage FP8 | Sol-Attn2 FP8 |
|---|---|---|
| Special-function unit (exp2) busy | 58.7% | 0.8% |
| Tensor cores busy | 38.5% | 71.3% |
| Instruction issue slots busy | 39.1% | 55.9% |
| Kernel time (under the profiler) | 15.6 ms | 10.9 ms |
The special-function unit (MUFU) is the small per-SM unit that evaluates transcendental functions such as exp2, at a fraction of the rate of ordinary arithmetic. cuDNN issues one exp2 per score, which keeps that unit busy 59% of the time; it becomes the bottleneck, and the tensor cores wait for P. ExpCast turns the same work into a fused multiply-add and an integer conversion on the regular ALU and FMA pipes, so the tensor cores stay busy 71% of the time.
One Sol-Attn2 call is five steps. The figure marks which ones already run fused and which still run as separate kernels, with measured times for one 12-second call (56 heads, 83k tokens).
Why it saves compute. Dense attention multiplies every query block with every key block: N_B^2 tiles of QK and PV. Counted in tile-equivalents, Sol-Attn2 runs three much smaller pieces:
The router works on 8-token means, so it does 1/64 of the dense score work (an 8×8 instead of a 64×64 product per tile) in pooled precision. At density ρ ≈ 0.1 the exact part is a tenth of the dense tiles, and those run on FP8 tensor cores at twice the BF16 rate without any exponential instruction. The tail adds one tile per query block, so its cost grows linearly with length while everything else grows quadratically. Against Sol-Attn 1.0 the same tiles get cheaper (FP8 instead of BF16, no exp2 bottleneck) and the router gets more accurate for about the same cost.
Denoiser time, dense versus Sol-Attn2 on the same pipeline, sampler, GPU count and video; Sol-Attn2 runs in every denoising call.
| Pipeline | Steps | GPUs | Video | Dense | Sol-Attn2 | Speedup |
|---|---|---|---|---|---|---|
| HyperFlow | 8 | 1 | 5 s | 24.51 s | 17.83 s | 1.37× |
| HyperFlow | 8 | 1 | 12 s | 86.20 s | 48.33 s | 1.78× |
| Sol-H3, merged LoRA | 4 | 1 | 5 s | 12.00 s | 8.20 s | 1.46× |
| Sol-H3, merged LoRA | 4 | 1 | 12 s | 45.72 s | 23.22 s | 1.97× |
One GB200. HyperFlow: MiniMax H3 with the HyperFlow 8-step adapter applied as LoRA branches, 736×1312, HSG job 7894980. Sol-H3: NVlabs/Sana sol-engine with the FastH3 4-step adapter merged into the weights, 1344×768, HSG job 7895280. Medians of three warm requests.
Against Sol-Attn 1.0, each row below times dense, Sol-Attn 1.0 and Sol-Attn2 in the same job, so all three share one GPU, prompt and seed.
| Pipeline | Steps | Video | Dense | Sol-Attn 1.0 | Sol-Attn2 | Sol-Attn2 vs 1.0 |
|---|---|---|---|---|---|---|
| HyperFlow | 8 | 5 s | 25.27 s | 20.20 s (1.25×) | 18.25 s (1.38×) | 1.11× |
| HyperFlow | 8 | 12 s | 86.75 s | 58.90 s (1.47×) | 48.81 s (1.78×) | 1.21× |
| Sol-H3, merged LoRA | 4 | 5 s | 11.86 s | 9.21 s (1.29×) | 8.22 s (1.44×) | 1.12× |
| Sol-H3, merged LoRA | 4 | 12 s | 44.66 s | 29.07 s (1.54×) | 23.16 s (1.93×) | 1.26× |
Denoiser time on one GB200, medians of three warm requests, all calls sparse; speedups in parentheses are against dense. Sol-Attn 1.0 is its BF16 kernel with the mean + τ·std threshold plus the diagonal band (τ calibrated to about 10% density), on the same 4×4×4 cube layout, layers and dense text/audio query rows as Sol-Attn2. HSG jobs 7918238 (HyperFlow) and 7918503 (Sol-H3). Per attention call the gap is 2.4× (47.0 vs 19.4 ms at 12 s); end to end it shrinks to 1.1–1.3× because attention is only part of each call.
Sol-H3 ships its own Sol-Attn 1.0 backends: sol_bsa (its default: Sol-Attn 1.0 routing, cuDNN block-sparse attention for the selected blocks, then the mean-atom residual) and sol (its CuTe kernel). Both run here with Sol-H3's own settings (raster order, prefix sink, diagonal threshold) on the same layers and call schedule as Sol-Attn2. At Sol-H3's default τ = 1.0 they keep about twice our density, so the table also lists τ = 1.6, where the routed density matches ours.
| Sol-H3, merged LoRA, 4 steps | τ | Density | 12 s denoiser | vs dense, 5 s | vs dense, 12 s |
|---|---|---|---|---|---|
Sol-H3 sol_bsa (default) | 1.0 | 0.20–0.21 | 31.06 s | 1.22× | 1.49× |
Sol-H3 sol | 1.0 | 0.20–0.21 | 36.41 s | 1.10× | 1.27× |
Sol-H3 sol_bsa | 1.6 | 0.09–0.10 | 27.26 s | 1.30× | 1.69× |
Sol-H3 sol | 1.6 | 0.09–0.10 | 30.98 s | 1.23× | 1.53× |
| Sol-Attn2 | – | 0.105 | 23.85 s | 1.43× | 1.95× |
One GB200, medians of three warm requests, all calls sparse, blocks 3–46. Each speedup divides by the dense run in the same process (dense 12 s: 46.0–47.5 s). Density for Sol-H3 is its routed fraction before the prefix sink is added (the sink adds 0.01–0.03); for Sol-Attn2 it is selected over eligible blocks outside the dense text/audio rows. cuDNN frontend 29106622 (Sol-H3's pin), block-sparse attention only. HSG jobs 7919812 and 7920385. Sol-H3's quality at τ = 1.6 was not evaluated.
At 1088×1920 and 15 seconds the packed sequence is 219,524 tokens (3,431 KV blocks of 64), and dense attention takes 87% of the denoiser. Every sparse arm below is set to the same video density, 0.100, and runs on the Sol-H3 engine with all of its optimizations except the attention backend: LoRA merged, kernel fusions and AdaLN precompute on. Sol-Attn2 denoises 2.8× faster than dense, 1.39× faster than Sol-Attn 1.0 and 1.26× faster than Sol-H3's cuDNN block-sparse backend.
| 1080p 15 s, Sol-H3 full opt, 4 steps | Video density | Denoiser | Request | Attention | Denoiser vs dense | vs Sol-Attn 1.0 |
|---|---|---|---|---|---|---|
| Dense | – | 211.1 s | 229.5 s | 182.7 s | 1.00× | 0.50× |
| Sol-Attn, w. dense warmup | 0.100 | 132.1 s | 150.7 s | 105.0 s | 1.60× | 0.80× |
| Sol-Attn, full sparse | 0.100 | 105.6 s | 124.1 s | 78.9 s | 2.00× | 1.00× |
| Sol-Attn w. cuDNN BSA backend | 0.100 | 97.7 s | 116.1 s | 70.0 s | 2.24× | 1.08× |
| Sol-Attn2 | 0.100 | 75.8 s | 94.2 s | 49.4 s | 2.78× | 1.39× |
One GB200 per run, FastH3 4-step adapter, one prompt, seed 1000; each arm runs in a fresh process, medians of two timed requests after warm-up. Video density is the same for every arm: selected over eligible video (query block, KV block) pairs, band included, text/audio rows and columns excluded, measured from each arm's own route on every sparse call; each arm's threshold was solved to hit 0.100 (Sol-Attn2 ε 0.2127, Sol-Attn 1.0 τ 1.3047, sol_bsa τ 1.6243). Text/audio sink off. Per transformer call, attention takes 12–13 s with Sol-Attn2, 17.6 s with sol_bsa, 19.7 s with Sol-Attn 1.0 and about 46 s dense. Supporting this length needed one change to the tail compression kernel (64 lanes per slot, inference only); its output is bitwise unchanged up to 2,048 KV blocks. HSG jobs 7930955 and 7930958.
Multi-GPU runs use the Sol-H3 engine with the LoRA merged and its fusions on (norms, modulation, SwiGLU), with Ulysses sequence parallelism. The first table compares dense and Sol-Attn2 at each GPU count; the second shows how each scales from one GPU.
| Sol-H3, merged LoRA + fusions, 4 steps | GPUs | Video | Dense | Sol-Attn2 | Speedup |
|---|---|---|---|---|---|
| single GPU | 1 | 5 s | 10.61 s | 6.64 s | 1.60× |
| Ulysses | 4 | 5 s | 2.84 s | 1.90 s | 1.49× |
| Ulysses, 2 nodes | 8 | 5 s | 1.46 s | 1.01 s | 1.45× |
| single GPU | 1 | 12 s | 43.09 s | 19.37 s | 2.22× |
| Ulysses | 4 | 12 s | 11.16 s | 5.27 s | 2.12× |
| Ulysses, 2 nodes | 8 | 12 s | 5.78 s | 2.76 s | 2.09× |
| Scaling from one GPU | GPUs | Video | Dense | Sol-Attn2 |
|---|---|---|---|---|
| Ulysses | 4 | 5 s | 3.74× | 3.49× |
| Ulysses, 2 nodes | 8 | 5 s | 7.27× | 6.57× |
| Ulysses | 4 | 12 s | 3.86× | 3.68× |
| Ulysses, 2 nodes | 8 | 12 s | 7.46× | 7.02× |
Denoiser time, 1344×768, FastH3 4-step adapter, HSG jobs 7895280, 7895601, 7895602. Speedups in the second table divide the one-GPU denoiser time by the multi-GPU time of the same arm. Both arms use the engine's BF16 all-to-all, 15–16% of denoiser time on 4 and 8 GPUs, which is why Sol-Attn2 scales slightly below dense: its compute shrinks while the communication stays the same.
Panel (b) and the table below break down the HyperFlow runs: the full MiniMax H3 pipeline on one GB200 with the deployed Sol-Attn2 op (quantisation, routing, tail and FP8 attention), 8-step HyperFlow with all eight calls sparse, as deployed after QAD. Median of three warm requests on the same prompt and seed.
| MiniMax H3, 1× GB200 | 5 s dense | 5 s Sol-Attn2 | 12 s dense | 12 s Sol-Attn2 |
|---|---|---|---|---|
| One transformer call | 3.05 s | 2.22 s (1.38×) | 10.77 s | 6.02 s (1.79×) |
| Denoiser, 8 steps | 24.51 s | 17.83 s (1.37×) | 86.20 s | 48.33 s (1.78×) |
| Request (denoiser + VAE decode) | 30.88 s | 24.30 s (1.27×) | 101.76 s | 63.89 s (1.59×) |
The gain grows with video length because attention grows quadratically while everything else grows linearly. In one sparse call, attention in the 44 sparse blocks is 33% of the dense call at 5 s and 50% at 12 s; Sol-Attn2 cuts it from 986 to 251 ms (5 s) and from 5337 to 844 ms (12 s). The rest of the call (projections, FFN, the six dense blocks) stays the same and caps the per-call speedup.
The HyperFlow pipeline applies LoRA as separate branches with no kernel fusion. In the Sol-H3 engine the LoRA is merged and norms, modulation and SwiGLU are fused, so everything outside attention is faster and the same Sol-Attn2 op removes more of the total: per call at 12 s, attention drops from 7879 to 2194 ms and the rest from 2895 to 2643 ms (with fusions on, the 12 s denoiser speedup is 2.22×; on 4 and 8 GPUs with Ulysses it is 2.12× and 2.09×).
After Sol-Attn2, attention is no longer the largest cost. The table splits the 4-step denoiser on the Sol-H3 engine (merged LoRA) by module. At 12 s, attention falls from 62% to 31% of the time; the QKV and output projections plus the FFN are now 64%.
| Denoiser, Sol-H3 merged LoRA | Total | Attention op | QKV + out proj. | FFN | Other |
|---|---|---|---|---|---|
| 5 s, dense | 12.07 s | 5.00 s (41%) | 3.97 s (33%) | 2.55 s (21%) | 0.56 s (5%) |
| 5 s, Sol-Attn2 | 8.37 s | 1.77 s (21%) | 3.58 s (43%) | 2.46 s (29%) | 0.55 s (7%) |
| 12 s, dense | 46.39 s | 28.58 s (62%) | 9.89 s (21%) | 6.59 s (14%) | 1.34 s (3%) |
| 12 s, Sol-Attn2 | 23.79 s | 7.36 s (31%) | 9.26 s (39%) | 5.91 s (25%) | 1.26 s (5%) |
CUDA events around each block's attention module and FFN in one extra request per arm (HSG job 7919812, one GB200, fusions off). Attention op = the attention kernel call (for Sol-Attn2: quantisation, routing, tail and FP8 core). QKV + out proj. = the attention module minus the op (projections, qk-norm, RoPE). FFN = up projection, SwiGLU and down projection. Other = norms, modulation, residuals, embeddings, refiner and output head. The FFN and projection rows differ by 5–10% between arms on the same GPU; treat that as run-to-run variation.
VDN-H3 (Video DeltaNet hybrid attention) and FastH3 (VSA) timed on the same GPU, video length (294 frames) and resolution (1344×768) as Sol-Attn2. These are different models and runtimes, so this compares system speed, not attention alone. The comparable unit is one transformer forward; FastH3 and VDN-H3 were timed over 8 forwards.
| 12 s video, 1× GB200 | Attention | Linear layers | One forward | vs dense |
|---|---|---|---|---|
| Dense, Sol-H3 engine | BF16 dense | BF16 | 10.77 s | 1.00× |
| FastH3 (FastVideo runtime) | BF16 VSA sparse | BF16 | 5.99 s | 1.80× |
| VDN-H3 | DeltaNet hybrid | FP8 | 4.96 s | 2.17× |
| Sol-Attn2, Sol-H3 engine | FP8 sparse | BF16 | 4.84 s | 2.23× |
| Sol-Attn2, Sol-H3 engine | FP8 sparse | MXFP8 | 4.02 s | 2.68× |
“vs dense” divides by the dense forward on the Sol-H3 engine. FastH3 and VDN-H3 use their released launchers (FastH3 47.9 s and VDN-H3 39.9 s for 8 forwards, HSG job 7894197). Sol-Attn2 rows are per-call medians from the Sol-H3 engine runs above. MXFP8 linear layers are lossy; the BF16 row is the lossless comparison.
| Part of call 4 | 5 s dense | 5 s Sol-Attn2 | 12 s dense | 12 s Sol-Attn2 |
|---|---|---|---|---|
| Whole transformer call | 3000 | 2164 | 10763 | 5878 |
| Attention, 44 sparse blocks | 986 | 251 | 5337 | 844 |
| of which quant + routing + tail | – | 100 | – | 307 |
| of which FP8 attention core | – | 151 | – | 538 |
| Attention, 6 dense blocks | 132 | 124 | 711 | 712 |
| QKV / output projections, norms, RoPE, layout | 1040 | 974 | 2580 | 2396 |
| FFN, modulation and the rest | 842 | 815 | 2135 | 1926 |
Breakdown from HSG jobs 7892562 (5 s, h3s5_010051) and 7893011 (12 s, h3_000070), call 4; realised density 11.3% and 8.8%. The timing table above is from HSG job 7894980 (all eight calls sparse; density 11.5% and 9.0%). Request time excludes text encoding (cached) and video writing.
Released HyperFlow adapter, no training. 64 held-out prompts, 8-step sampling with the first two calls dense, PSNR against the dense teacher's video, paired over the same prompts and seeds.
| Method (density ≈ 0.10) | PSNR (dB) | Δ vs. top-k |
|---|---|---|
| Sol-Attn2 (threshold router + tail) | 17.23 | +0.19 [+0.04, +0.34] |
| Sol-Attn1 | 17.11 | +0.07 (means) |
| Top-k (block means) | 17.04 | – |
Recipe in Training.
Validation loss on 32 fixed samples:
| At density ≈ 0.10 (steps 250–400 pooled) | Val-loss ratio |
|---|---|
| Sol-Attn2 / top-k FP8 | 0.963, 0.974 |
| SLA (BF16) / Sol-Attn2 | 1.046–1.055 |
| VSA (BF16) / Sol-Attn2 | 1.058–1.067 |
| VSA2 (BF16) / Sol-Attn2 | 1.016–1.024 (tie) |
| Top-k BF16 exact, no tail / Sol-Attn2 | 1.014–1.023 (tie) |
"Tie" means the 95% interval contains 1. After QAD we judge by validation loss and samples, not PSNR.
Tail. An equal-cost tail with 8 anchors × 8 surrogates in the same single extra tile (each anchor serves its 8 query rows) gains +0.13 to +0.16 dB training-free PSNR over the deployed 64-slot form at the same density; it is now in QAD. Grouping surrogates by key content instead of token order makes the tail independent of token order at no quality cost.
Training signal for the tail. QAD trains the model only through its final output, so the tail never gets a direct signal. We are testing a local loss that pulls each layer's Sol-Attn2 output toward its own dense attention, and a SAS-style learnable selector whose normalised gate also weights the tail, so every skipped block gets its own gradient.
One fused routing kernel. Routing and tail construction are 5.1 of the 19.4 ms of one 12 s call. Fusing them into one scan, and the tail tile into the new FP8 attention kernel, attacks exactly that remainder.
We thank the teams and open projects that Sol-Attn2 builds on.
If Sol-Attn2 helps your work, please cite this project page together with Sol-Engine and Sol-Attn.
@misc{solattn2_2026,
title = {Sol-Attn2: Sparse Attention with Complementary Approximation},
year = {2026},
howpublished = {\url{https://hp-l33-sol-attn2.static.hf.space/}},
note = {Project page}
}
@misc{li2026solvideoinferenceengine,
title = {Sol Video Inference Engine: Agent-Native Full-Stack Acceleration Framework for Efficient Video Generation},
author = {Yitong Li and Junsong Chen and Haopeng Li and Haozhe Liu and Jincheng Yu and Ligeng Zhu and Ping Luo and Song Han and Enze Xie},
year = {2026},
eprint = {2606.23743},
archivePrefix = {arXiv},
primaryClass = {cs.CV},
url = {https://arxiv.org/abs/2606.23743}
}
@misc{li2026solattn,
title = {Sol-Attn: Accelerating Video Generation Inference via On-the-Fly Attention Sparsification},
author = {Haopeng Li and Yitong Li and Junsong Chen and Tian Ye and Haozhe Liu and Jincheng Yu and Duomin Wang and Ruihua Zhang and Zeke Xie and Enze Xie and Song Han},
year = {2026},
eprint = {2607.24027},
archivePrefix = {arXiv},
primaryClass = {cs.CV},
url = {https://arxiv.org/abs/2607.24027}
}