# FastH3 Preview v1: four calls, one-tenth the attention, and what the 14x actually measures

> Satyajit Ghana — Head of Engineering @ Inkers Technology
> canonical: https://ai.satyajit.si/articles/fastvideo-fasth3
> date: 2026-08-29
> tags: video-generation, diffusion, sparse-attention, distillation, inference

[FastH3 Preview v1](https://huggingface.co/FastVideo/FastVideo-FastH3-4-step-Preview-v1-VSA-DataFree) is
[FastVideo](https://github.com/hao-ai-lab/FastVideo)'s distilled version of MiniMax's H3 audio-video
diffusion transformer, and the [announcement post](https://haoailab.com/blogs/fasth3-preview/) leads with
two numbers: "up to 14x speedup on NVIDIA Blackwell GPU," and "generate 15s 768p video in less than 13s with
sub-realtime generation on 8xB200 GPUs." Both are real — they're read straight off FastVideo's own published
table, and this piece rebuilds that table from the numbers to check them. But both numbers are also
specific in ways the headline doesn't spell out: 14x is one clip length on one GPU count, and "sub-realtime"
turns out to describe one row of a three-row table, not the whole table.

That's the shape of this piece. FastH3's own components are unusually well-documented for an open-weight
release — the checkpoint ships a machine-readable `checkpoint_metadata.json` with its exact training config,
a `provenance.json` with commit hashes and a Weights & Biases run URL, and safetensors headers you can read
without downloading 148GB. So rather than repeat the announcement, this walks through what's actually
verifiable: the two mechanisms that make FastH3 fast, a parameter count reconstructed from the checkpoint's
own tensor shapes, and a decomposition of "14x" into the piece that comes from calling the transformer fewer
times and the piece that comes from making each call cheaper — because they turn out to be different sizes,
and the source lets you tell them apart.

That verification runs one level deeper than the checkpoint, too. FastVideo publishes the full
training-and-inference framework FastH3 comes from, and reading it directly — the hand-written CUDA kernels
behind "on Blackwell," the DMD2 training step, the model registry, the Apple Silicon runtime — either confirms
specific claims the announcement makes about hardware and the roadmap, or complicates them in ways the
checkpoint's own metadata can't show on its own.

<Figure
  src="https://media.thesatyajit.com/ai/articles/fastvideo-fasth3/fig1.png?v=75defbde8bb6465b"
  alt="A validation sample generated by FastH3: an emerald-green dragon with red-veined wings banks over a misty pine forest at sunset, mountains silhouetted against a purple-and-orange sky."
  caption="A frame from one of FastH3's published validation samples — video and its own synchronized wind-and-wingbeat audio, generated end to end in four transformer calls at 90% attention sparsity (FastVideo, FastH3 Preview v1 validation gallery)."
/>

<ModelCard repo="FastVideo/FastVideo-FastH3-4-step-Preview-v1-VSA-DataFree" />

## The base model: MiniMax H3, undistilled

FastH3 isn't a new architecture — it's the same weights MiniMax shipped, pushed through a training run that
changes how the checkpoint is *used*, not what it fundamentally *is*. [MiniMax H3](/articles/minimax-h3) is a
33B-parameter dense, single-stream Omni-Transformer (MiniMax's own description, on its own model card) that
takes text, image, video, and audio in and produces synchronized audio-video out, at up to 2K resolution
(768p by default), 4-15 second clips at 24 FPS, with 32kHz stereo audio. Text and vision conditioning come
from a separate encoder — [the minimax-h3 piece](/articles/minimax-h3) identifies it as a 32B-parameter
Qwen3-VL model — and attention across the whole packed sequence is, in MiniMax's own words, "full attention
in the initial release," with sparse attention only "planned for future publication." FastVideo built that
sparse attention first, and applied it as a distillation target rather than waiting for MiniMax to ship one.

Two things are worth separating cleanly before going further, because the announcement's headline collapses
them into one number: FastH3 lowers Base H3's cost in exactly two ways, and they're independent mechanisms
that happen to compound.

## Lever one: 49 calls become 4

A diffusion transformer's inference cost is, to a first approximation, `(cost per call) x (number of calls)`.
FastVideo's own accounting of Base H3's default schedule is 49 calls to its 33B transformer per generation —
stated directly in the announcement, not inferred. FastH3 replaces that with exactly four, and this number
isn't a rounded average: `checkpoint_metadata.json`, published alongside the weights, lists
`dmd_denoising_steps: [999, 749, 500, 250]` — four fixed timesteps, no more, no fewer, for every generation
this checkpoint produces.

<CallCountBreakdown />

Forty-nine to four is a fixed 12.25x reduction in transformer forward passes, and it would be tempting to
stop there and call that the whole story. It isn't, for the reason the chart above makes visible: end-to-end
wall clock also includes text/vision encoding, VAE decode, audio decode, muxing, and file output, and none
of that shrinks when the diffusion loop gets four times shorter. At four fixed calls, that fixed overhead is
a *larger* share of a shorter clip's total time than of a longer one's — which is why the observed speedup
sits below the 12.25x line at 5 and 10 seconds, and only climbs past it at 15 seconds, where there's enough
diffusion work left for the second lever to act on.

## What actually trains those four calls: Data-Free DMD2

The method that gets Base H3 down to four calls is [Distribution Matching Distillation
(DMD2)](https://arxiv.org/abs/2405.14867), and the "Data-Free" name in FastH3's checkpoint filename describes
something specific about *how* it's trained, not a claim that training was free of supervision. Reading the
recommended checkpoint's own `checkpoint_metadata.json` training config end to end:

<DatafreePipeline />

Three networks, all initialized from the same MiniMax-H3 weights: a frozen **teacher** (dense attention,
never updated), a trainable **critic** — DMD2's own name for it is `fake_score` — that keeps dense attention
and is continuously updated to track the student's current output distribution, and a trainable **student**
that runs the sparse `VIDEO_SPARSE_ATTN_H3` backend and is the thing being distilled into a four-step
generator. `generator_update_interval: 5` in the real config means the student takes one gradient step for
every five the critic takes — the critic has to keep up with a moving target, so it trains harder.

What makes the recommended checkpoint "Data-Free" is `preprocessed_data_type: "text_only"` in that same
config — every one of its five listed training-data paths is reduced to prompts alone before training
starts. Combined with `rollout_mode: "simulate"` and `rollout_sample_type: "ode"` (DMD2's "backward
simulation"), the student generates its *own* four-step rollout starting from pure noise, and the teacher and
critic score that self-generated sample — never a video anyone recorded or rendered. FastVideo names the
alternative directly in the announcement: "the synthetic-video runs instead start from forward-noised
Base-H3 video-and-audio latents," a separate, non-default ablation covered below. Neither path ever touches
H3-Base's own training corpus; the difference is whether the rollout starts from noise or from a real
model's output.

## Inside the training step: what checkpoint_metadata.json doesn't show

The metadata gives the shape of the recipe; FastVideo's actual training-step code
(`fastvideo/train/methods/distribution_matching/dmd2.py`) shows the mechanism is more involved than "the
student takes four steps, the teacher and critic score it." Two things the config alone can't tell you:

`dmd_denoising_steps: [999, 749, 500, 250]` is the fixed schedule the student walks *forward* through to
build a simulated trajectory (`_student_rollout`, when `rollout_mode == "simulate"`) — but the teacher and
critic don't score the student's prediction at one of those four points. They score it at a separately,
uniformly sampled timestep (`_sample_score_timestep`, bounded by the config's own `min_timestep_ratio` and
`max_timestep_ratio`) that has nothing to do with the four-point schedule. That gap between "the schedule the
student denoises through" and "the noise level the loss is actually computed at" is DMD2's real
distribution-matching mechanic — matching the student's output distribution to the teacher's across a broad,
randomly sampled range of noise levels, not just at the four points that ship in the released checkpoint.

It also means one training iteration touches the student transformer far more than four times. In
`"simulate"` mode, `_student_rollout` always walks the *entire* fixed schedule under `torch.no_grad()` —
`for step_idx in range(max_target_idx)` runs all three transitions between the checkpoint's four denoising
steps unconditionally, regardless of which target index gets randomly sampled — and only then takes one more
call, graded or not, at the sampled target. That's exactly four student forward passes per `_student_rollout`
call, every time. `_critic_flow_matching_loss` calls `_student_rollout` again on *every* iteration (with
`with_grad=False`) purely to generate the sample the critic's loss trains against — four more student calls
that happen whether or not the generator itself updates that step. On the iterations where
`generator_update_interval` also fires the generator loss, `_student_rollout` runs a second time with
`with_grad=True` for another four. So a training iteration touches the student transformer four times just to
train the critic, and eight times on the one iteration in five where the generator updates too — "four calls"
describes what ships at generation time, not what training costs to compute.

The code also confirms, from the loss functions themselves rather than from metadata, which network runs
which attention: the student's rollout calls `predict_x0(..., attn_kind="vsa")`, while both the critic's
flow-matching loss and the teacher/critic scoring in `_dmd_loss` call `predict_x0`/`predict_noise` with
`attn_kind="dense"` throughout — exactly the split the earlier diagram describes, now verified against the
training loop rather than just the checkpoint's config.

One thing worth flagging plainly: the generic `DMD2Method` expects a student role model whose
`predict_x0(..., attn_kind="vsa")` actually executes sparse attention, but the one open MiniMax H3 training
wrapper in this codebase, `fastvideo/train/models/minimax_h3/minimax_h3.py`, raises `ValueError("MiniMaxH3Model
supports dense attention for training")` for any `attn_kind` other than `"dense"` — and its only wired-up
training config in the repository (`examples/train/configs/overfit_minimax_h3_t2va.yaml`) pairs it with plain
`FineTuneMethod`, not `DMD2Method`. No example or config anywhere in this checkout actually combines MiniMax
H3 with DMD2. The checkpoint's own metadata is unambiguous that VSA-sparse DMD2 distillation is what produced
FastH3, so that part isn't in question — but the exact glue code that made `attn_kind="vsa"` work for an H3
student isn't in FastVideo's public tree as cloned here. Either it lives outside this snapshot, or the public
`MiniMaxH3Model` class was written for plain finetuning and doesn't (yet) cover the distillation path the
released checkpoint actually went through. Source alone can't settle which, and it's the kind of gap that
lines up with the checkpoint's own self-reported `"known_recipe_deviation"` — training internals that have
moved on from what's merged upstream.

## Lever two: VSA-H3 makes each of the four calls cheaper

The second lever is [Video Sparse Attention (VSA)](https://arxiv.org/abs/2505.13389), adapted to H3's
particular attention pattern in `fastvideo/attention/backends/video_sparse_attn_h3.py`. H3 runs one joint
bidirectional attention over a packed sequence of `[text | condition keyframes | audio | generated video]`,
so VSA-H3 partitions only the video portion into 3D tiles over its own (t, h, w) latent grid. FastH3 is
trained on the 64-token tile shape — `(4, 4, 4)` — rather than the library's other supported shape, 256
tokens at `(4, 8, 8)`.

<VsaMechanism />

A coarse pooling stage scores every tile cheaply against the query first — nothing is skipped blind. Then
`compute_topk` (source: `max(1, min(ceil((1 - sparsity) x num_blocks), num_blocks))`) decides how many tiles
survive to expensive, exact fine-grained attention. FastH3's trained default is 90% sparsity, so roughly one
tile in ten does. Two details matter for what actually gets compressed: non-video *queries* (text, audio
tokens attending outward) are always dense, and non-video *keys* default to "exempt" — always included for
every video query, never competing for a top-k slot, with a separate "compete" mode existing in the code but
not used by FastH3. So a text or audio token never loses information to sparsity in either direction; only
video-to-video attention gets thinned.

The other detail is a learned gate the base checkpoint doesn't have. `to_gate_compress` blends a pooled
signal from the 90% of tiles that lose the top-k competition back into the output, so they aren't discarded
outright — just compressed. Reading the checkpoint's own safetensors headers directly confirms this is real,
trained weight, not a documentation claim: a `[7168, 5376]` `to_gate_compress.weight` tensor exists in all 50
transformer blocks (`num_attention_heads: 56` at `attention_head_dim: 128`, so `56 x 128 = 7168`, against
`hidden_size: 5376`). Base H3's loader zero-initializes this tensor, so untrained inference from the base
weights is exactly plain sparse attention with the compression branch contributing nothing; FastH3's
distillation run has actually trained it.

<Figure
  src="https://media.thesatyajit.com/ai/articles/fastvideo-fasth3/fig2.png?v=6d26ff63dbc22802"
  alt="A validation sample generated by FastH3: a performer in an embroidered traditional Kazakh shapan and pointed hat dances with arms outstretched on a studio floor, in front of a large LED backdrop showing steppe grassland, rolling hills, and a blue sky with clouds."
  caption="A second FastH3 validation sample — a traditional Kazakh dance performance shot against an LED-wall backdrop, at the checkpoint's default 1344x768 resolution, generated with synchronized footfall and fabric audio (FastVideo, FastH3 Preview v1 validation gallery)."
/>

## The parameter count, reconstructed

FastVideo's own model card states 35B parameters for the released checkpoint. That number is checkable, and
it decomposes cleanly into the two pieces already described. MiniMax's own card puts the base H3 transformer
at 33B, and the trained `to_gate_compress` tensors are new weight the base checkpoint never had: `7168 x
5376 = 38,535,168` parameters per layer, and with a real value in all 50 transformer blocks —
`38,535,168 x 50 = 1,926,758,400`, about **1.93B** parameters. `33B + 1.93B ~ 34.93B`, which rounds to the
card's stated 35B almost exactly. The distillation run didn't just re-weight an existing network; it grew
the checkpoint by nearly two billion trained parameters to make the compression branch worth having.

The rest of what ships in the 148GB repository is worth sizing too, because "35B model" undersells the full
pipeline: the transformer shards total 70.1GB (that 35B figure, at bf16), but the `text_encoder` directory —
14 shards, a real tokenizer and chat template — comes to 66.7GB, which at bf16 is just over 33B parameters.
That's consistent with (if a couple billion larger than, presumably from a vision tower and projector on top
of the language backbone) the 32B Qwen3-VL encoder [the minimax-h3 piece](/articles/minimax-h3) identifies as
H3's text/vision conditioner. The video VAE adds another 10.4GB and the audio VAE 0.6GB. Run the full FastH3
pipeline and you're loading two frontier-scale transformers — a ~35B generator and a ~33B encoder — not one.

The checkpoint's `provenance.json` is also worth a mention on its own, separate from what it says: it ships a
base-model commit hash, a training-run ID, a Weights & Biases URL, and sha256 checksums for every file — more
supply-chain transparency than most open-weight drops include. It also self-reports a limitation nobody would
ask for: `"known_recipe_deviation": "Predates later continuous score-clock and FastGen-alignment
corrections."` This specific checkpoint (step 1300) is flagged, by its own metadata, as coming from before
FastVideo's training recipe was refined further — worth knowing if a later checkpoint in the same LoRA
collection supersedes it.

## What's actually on the GPU: three kernels behind one switch

"Up to 14x speedup on NVIDIA Blackwell GPU" implies something architecture-specific is happening, and it is —
but it's gated behind an opt-in switch most of the code path doesn't take by default, and it's a genuinely
separate, hand-written kernel from the one that runs on Hopper, not one kernel recompiled per architecture.
`fastvideo-kernel/csrc/attention/` ships `block_sparse_h100.cu` (ThunderKittens, Hopper `wgmma` and TMA,
compiled only under the `sm_90a` device pass) alongside `block_sparse_sm100a.cu` plus
`block_sparse_kernel_sm100a.cuh` (a warp-specialized kernel built on `tcgen05.mma`, TMA tensor maps, and
cluster-launch-control scheduling — Blackwell's fifth-generation tensor-core instructions, which don't exist
on Hopper at all). The kernel's own `CMakeLists.txt` is explicit about why a plain `sm_100` target won't do:
"`-arch=sm_100a` is NOT enough — it emits a plain `sm_100` target and `ptxas` rejects every `tcgen05` /
`setmaxnreg` instruction." Both are built only when the arch list says so: Hopper kernels compile only when
`TORCH_CUDA_ARCH_LIST` matches `9.0a`/`90a`/`sm_90a`, and the build prints its own fallback plan when it
doesn't — "ThunderKittens kernels: DISABLED (will use Triton fallbacks at runtime)." The Blackwell kernel
compiles only when the list matches `10.0a`/`100a`/`sm_100a` explicitly, for 64- and 128-token blocks.

Getting to that Blackwell kernel at runtime takes more than owning a Blackwell GPU, though.
`fastvideo/attention/backends/video_sparse_attn_h3.py` reaches it only through an explicit opt-in,
`FASTVIDEO_VSA_SM100A=1`, and only for the no-grad inference forward at FastH3's trained tile size (64
tokens) — "Grad-tracking forwards and every backward stay on Triton unchanged," in the module's own words,
because the Blackwell kernel returns no gradient at all. The generic dispatcher one layer down
(`fastvideo_kernel/block_sparse_attn.py`'s `block_sparse_attn_from_indices`) has no equivalent automatic
branch for Blackwell either: with no environment variables set, its rule is "use the compiled Hopper kernel if
the device reports `sm_90` capability, otherwise Triton" — so on Blackwell hardware, by default, even
inference falls back to Triton.

<KernelRouting />

FastVideo's own benchmark reproduction script sets the switch itself:
`examples/inference/basic/basic_fasth3.py`'s `--vsa-kernel` flag defaults to `"sm100a"`, and its
`profile_environment()` sets `FASTVIDEO_VSA_SM100A="1"` accordingly as part of the `all` profile the repo's own
docs describe as "the fastest measured four-GPU Preview recipe." The switch that makes the announced Blackwell
numbers reachable is that script's default, not something a Blackwell GPU triggers on its own — and the same
docs note the honest fallback: "use `--vsa-kernel triton --no-fa4` if the Blackwell kernels are unavailable."

Two more details worth being precise about. First, the H3 backend's own module docstring states that at tile
64 "both forward and backward run the Triton block-sparse kernels directly" — read literally, that's the
correct description of a Blackwell-only build, where the Hopper kernel is compiled out entirely and Triton is
the dispatcher's only option; a build that also targets Hopper would prefer the Hopper kernel whenever the
device matches, comment notwithstanding. Second, FastVideo's own reproduction script and docs describe the
measured recipe as running on "four GB200 GPUs," while the announcement's table headers every column "B200" —
GB200 is Nvidia's Grace-Blackwell superchip (Blackwell GPU dies paired with a Grace CPU), not the standalone
B200 card the table's columns name. Both are Blackwell-generation silicon, so the architecture-level "on
Blackwell" claim holds either way, but the two documents don't agree on the exact SKU, and nothing in the
source resolves which one actually produced the published numbers.

It's also worth restating why this piece has used the 64-token tile throughout: it's FastH3's trained and
shipped default, not the library's own default. `VSA_H3_TILE_SIZE = (4, 8, 8)` — 256 tokens — is what
`video_sparse_attn_h3.py` falls back to when nothing overrides it, routed through an entirely different pair
of kernels (`block_sparse_attn_256.py`: a Triton "route A" expansion to 64-token tiles by default, or an
opt-in FA4 CuTe DSL fastpath via `FASTVIDEO_VSA_CUTEDSL=1` operating on 128-token physical blocks). Neither
hand-written CUDA kernel in this codebase ever sees a 256-token tile directly; FastH3 trains and ships at the
smaller, non-default geometry that's also the only one either hardware-specific kernel targets.

## What FastVideo actually measured

Every number below comes from one table in the announcement: warm end-to-end latency on B200 GPUs, median of
three timed requests after one full warmup (model loading and compilation excluded), and — in FastVideo's own
words — "end-to-end time includes encoding, denoising, decoding, audio, muxing, and file output." These are
full-pipeline numbers, not isolated diffusion-loop or attention-kernel benchmarks. Tests run at 1344x768 and
24 FPS with audio; the 5s/10s/15s clip lengths correspond to fixed shapes of 124/243/345 frames.

| Configuration | 5s (s) | 10s (s) | 15s (s) | Speedup vs Base H3 (1x / 4x) |
|---|---|---|---|---|
| Base H3 - Dense FA4 | 132.5 | 377.4 | 678.7 | 1.0x / 1.0x |
| Preview v1 Dense/DataFree - Dense FA4 | 18.3 | 50.2 | 91.3 | 7.24x&ndash;7.52x / 5.97x&ndash;7.54x |
| Preview v1 VSA/DataFree - 90% sparse | 16.2 | 31.1 | 47.2 | 8.16x&ndash;14.38x / 6.65x&ndash;12.48x |

*(1x/4x = 1 or 4 B200 GPUs; all timings and ratios FastVideo's own, quoted to the table's published
precision.)*

Two methodology notes the announcement states outright and that hold up: "no 8x speedup is claimed without a
matched Base H3 run" — Base H3 was never benchmarked at 8x GPUs, so the 8xB200 column exists only for the VSA
row, with no baseline to divide against. And the ratios are computed from FastVideo's internal unrounded
timings, not the two-decimal numbers printed in the table — which is why recomputing a ratio from the
published seconds sometimes lands a couple of hundredths off the printed one. That's expected rounding, not
an error in either direction.

## Decomposing 14x: two multipliers, not one

The middle row of that table — Dense/DataFree, the same four-step DMD2 distillation but *without* VSA, still
running dense FlashAttention-4 — is the isolation point that lets the two levers be pulled apart cleanly,
because it's the only configuration in the table that has one lever (distillation) but not the other
(sparsity). Dividing straight through:

| Duration | Distillation alone (Base / Dense, 1x) | VSA on top (Dense / VSA, 1x) | Combined |
|---|---|---|---|
| 5s | 132.5 / 18.3 = 7.24x | 18.3 / 16.2 = 1.13x | 8.18x (table: 8.16x) |
| 10s | 377.4 / 50.2 = 7.52x | 50.2 / 31.1 = 1.61x | 12.11x (table: 12.13x) |
| 15s | 678.7 / 91.3 = 7.43x | 91.3 / 47.2 = 1.93x | 14.34x (table: 14.38x) |

The distillation-alone multiplier is flat across clip length — about 7.2x to 7.5x, nowhere near
the naive 12.25x that "49 calls to 4" predicts on its own, for the fixed-overhead reason above. VSA's
multiplier *on top* of that, by contrast, is the one that actually grows with clip length: 1.13x at 5
seconds, rising to 1.93x at 15 seconds, because a longer clip has proportionally more diffusion compute for
90% sparsity to remove and proportionally less fixed encode/decode/mux overhead diluting the win. The 14.38x
headline is the product of both — a distillation multiplier that barely moves, times a sparsity multiplier
that does — and it's the 15-second row specifically where both are large enough, and fixed overhead small
enough, for the combined number to say "14x" instead of "8x."

One more thing worth stating because it's easy to assume otherwise: there's no hardware-generation multiplier
hiding in this number. Base H3 and both FastH3 variants are benchmarked on the same B200 GPUs — "14x speedup
on NVIDIA Blackwell GPU" means a Blackwell GPU compared against that same Blackwell GPU, not a new chip
compared against an old one. Whatever is driving 14.38x, it's the two algorithmic levers above and their
interaction with fixed pipeline overhead — not different silicon.

## Is it actually real-time?

"Sub-realtime generation on 8xB200 GPUs" is the other headline claim, and it means something specific:
generation wall-clock time faster than the clip's own duration — watching it would take longer than making
it. Checked against each of the three durations FastVideo tested, rather than just the one the announcement
leads with:

<RealtimeCheck />

At 5 seconds, the fastest configuration shown (VSA/DataFree on 8xB200) takes 6.84 seconds — 37% *slower*
than real time. At 10 seconds it's 11.66 seconds, 17% slower. Only at 15 seconds does it cross the line, at
12.88 seconds, matching the announcement's "less than 13s" almost exactly. "Sub-realtime generation on
8xB200 GPUs" is accurate for precisely the duration FastVideo chose to lead with, and not for the other two
rows of their own table. Base H3 and the Dense/DataFree variant never approach real time at any duration or
GPU count shown — sub-realtime is a VSA-plus-8-GPU result specifically, not a general property of the
distilled model.

## The other checkpoints FastVideo shipped

The recommended VSA/DataFree checkpoint isn't the only thing in the release. FastVideo also publishes three
comparison LoRAs, all distilled to the same four DiT calls, grouped in one collection so the training-source
and attention axes can be tested independently of each other:

| Checkpoint | Training source | Attention | Step |
|---|---|---|---|
| VSA / Synthetic | forward-noised Base-H3-generated video | VSA, 90% sparse, tile 64 | 1300 |
| VSA / Synthetic (longer) | forward-noised Base-H3-generated video | VSA, 90% sparse, tile 64 | 1900 |
| Dense / Data-Free | prompts only | Dense FA4 | 1000 |

"Data-Free" and "Synthetic" describe the training-source axis (prompts-only vs. Base-H3-rendered video as a
starting point); "VSA" vs. "Dense" describes the attention axis. The recommended release sits at the
Data-Free x VSA corner; the ablations let you check what changes if you swap either axis independently — at
the cost of researching them yourself, since FastVideo doesn't publish latency numbers for the two synthetic
variants (they share VSA/DataFree's runtime characteristics, so the announcement doesn't repeat the table for
them).

One correction to that framing: the recommended VSA/Data-Free configuration isn't published only as the
~148GB full checkpoint this piece analyzes. `examples/inference/basic/README.md`'s "FastH3 Preview LoRAs"
section lists four launcher scripts, not three — `run_fasth3_lora_preview_vsa_datafree.sh` alongside the two
synthetic ablations and the dense one — all pulling adapters from the same
`FastVideo/FastVideo-FastH3-4-step-Preview-v1-LoRA` collection. So the recommended configuration ships in two
forms: the full weights analyzed above, and a much smaller adapter over base MiniMax H3. Per
`examples/serving/README.md`, that adapter isn't a pure low-rank delta either: "FastH3 adapters are hybrid
startup patches: alongside low-rank factors they may contain dense deltas and a VSA compression-gate
replacement" — which makes sense once you know `to_gate_compress` doesn't exist as a real tensor in base H3 at
all (the loader zero-initializes it), so a rank-64 factor has nothing to correct there; the adapter has to
ship the whole `[7168, 5376]` gate as a dense replacement. And per the same README, strength 1 "approximates
the full student" rather than reproducing it exactly — the LoRA form is a compressed stand-in, not a
bit-identical alternative to the checkpoint this piece is built on.

## FastVideo is bigger than one checkpoint

Reading only the announcement, FastVideo could pass for a lab that ships one distilled checkpoint at a time.
The repository it's built from is a full training-and-inference framework: `fastvideo/models/dits/` alone
carries on the order of thirty diffusion-transformer architectures — Wan, Hunyuan, Cosmos, Flux, LTX2,
Kandinsky5, MatrixGame2/3, GLM-Image, and MiniMax H3 among them — and `fastvideo/attention/backends/` carries
eleven other attention implementations beside VSA-H3 and its own base-VSA sibling (dense FlashAttention, SDPA,
Sage Attention and its v3, Nabla, sliding-window attention, VMoba, and separate quantized-attention
training/inference paths). FastH3 is one entry in a
model registry (`fastvideo/registry.py`) that already lists on the order of ninety model identifiers.

The framework extends well past the DiT zoo, too: `apps/dreamverse/` is a realtime "vibe-directing" streaming
product with its own server and web UI, deployable on Modal, Docker, or a self-hosted server over SSH;
`comfyui/` ships a ComfyUI integration with its own examples and web assets; `docker/` and FastVideo's
OpenAI-compatible serving entrypoints back the exact REST surface `examples/serving/openai_fasth3.yaml` uses
to serve FastH3 itself; and `fastvideo/performance_dashboard/` is a small service (`api.py`, `metrics.py`,
`service.py`) for tracking benchmark results over time. This piece has already noted that FastVideo hasn't
published a VBench score or any other quality metric for FastH3 — worth adding that the gap isn't a tooling
one. `fastvideo/eval/` is a real, generic, multi-GPU evaluation harness (`Evaluator`/`EvalWorker`, with a
`"vbench"` metric group resolvable by name) built to score any model in the registry. The framework can
compute these numbers; nobody has published any for this checkpoint.

Apple Silicon is the clearest place where the announcement undersells its own codebase. `fastvideo/mlx_runtime/`
is not a stub: dedicated modules `minimax_h3.py` (1,286 lines), `minimax_h3_pipeline.py`,
`minimax_h3_video_vae.py`, `minimax_h3_audio_vae.py`, and `minimax_h3_conditioner.py` reimplement H3's DiT,
scheduler, VAEs, and text/vision conditioner natively in MLX, checked against the torch reference by a real
parity test suite (`fastvideo/tests/mlx/test_mlx_minimax_h3_parity.py`), with INT8/INT6/INT4 quantization of
the attention and FFN matrices and a working example entrypoint (`examples/inference/basic/mlx_fasth3.py`)
that already runs text-to-audio-video end to end on an M4 Max. FastVideo's own support matrix says as much,
plainly: "MLX FastH3 Preview T2VA... Apple M4 Max, 36 GB unified memory... Source runtime; T2VA only" — flagged
less mature than the packaged FastMetal-QAD releases sitting next to it in the same table, but real, tested
code, not aspiration. One thing doesn't carry over, though: H3's MLX attention is plain dense
`mx.fast.scaled_dot_product_attention` (`fastvideo/mlx_runtime/minimax_h3.py`); the sliding-window sparse
module the MLX runtime does have (`windowed_attention.py`) is wired only into the Wan/FastMetal path
(`fastwan.py`), not into H3, so none of VSA-H3's sparsity savings apply on Apple Silicon yet.

RTX and DGX Spark sit in a different place. The framework broadly documents both — the README's own feature
list states support for "H100, A100, 4090" across Linux, Windows, and macOS, and there's a dedicated DGX Spark
install guide (`docs/getting_started/installation/spark.md`) for Nvidia's GB10 ARM64 platform, complete with
its own from-source kernel build since no prebuilt ARM wheel exists. But neither document, nor anything else
found in this checkout, ties FastH3 specifically to either platform the way the MLX runtime does for Apple
Silicon. For RTX and DGX Spark, "explicit interest in testing" — the announcement's own phrase, addressed
again below — is a fair description of where things stand today. Apple Silicon is the one platform where that
interest has already turned into a shipped, if self-flagged-as-preliminary, runtime.

(That was true when this was written in August. Five weeks later FastVideo shipped RTX and DGX Spark builds of
an eight-step successor; see [the October update](#update-consumer-gpus-and-trim) at the end.)

## What FastH3 openly says it isn't yet

Two limitations are worth naming because FastVideo states them directly rather than leaving them for someone
else to discover. The model card is explicit that this preview "supports text-to-audio-video generation"
only — FL2VA (first-frame-and-last-frame-to-video-audio) and Ref2VA (reference-conditioned) were not
distilled, despite Base H3 supporting both as a general omni-modal model. And on quality: "difficult motion,
fine detail, and some audio may remain below the base MiniMax H3 model" — a four-step, 90%-sparse student is
not claimed to match its dense, 49-call teacher on everything, and there is no VBench score, human-preference
study, or other quantitative quality metric published anywhere in the release to check that claim against.
Every number in this piece is a speed number; none of them are evidence about output quality, because
FastVideo hasn't published any.

The roadmap section of the announcement names what's next rather cautiously: an 8-step option (framed as
possibly *higher* quality than the 4-step model, not just slower), FL2VA and Ref2VA distillation, a
collaboration with NVIDIA's FastGen team on Parallel Decoding Distillation, and FP8/NVFP4 variants — plus
explicit interest in testing on RTX, DGX Spark, and Apple Silicon, since the checkpoint itself is hardware-
independent and B200 is only FastVideo's own controlled benchmark platform, not a requirement. That's an
accurate way to describe RTX and DGX Spark today, per the source dug into above — but it undersells Apple
Silicon specifically, where a real (if self-flagged "Source runtime") MLX port of H3 already exists and runs
end to end on an M4 Max, dense attention and all.

## Checked, in one table

| Claim | Status |
|---|---|
| Base H3 calls its transformer 49 times; FastH3 uses exactly 4 | Holds — confirmed independently via `checkpoint_metadata.json`'s `dmd_denoising_steps: [999, 749, 500, 250]` |
| "Data-Free" means no video is loaded, real or synthetic | Holds — `preprocessed_data_type: "text_only"` plus noise-start backward simulation, read from the checkpoint's own training config |
| Trained `to_gate_compress` gate adds ~1.93B parameters over base H3 | Holds — computed from the safetensors header shapes (`[7168, 5376] x 50 layers`), independent of the card's rounded 35B figure |
| "Up to 14x speedup on NVIDIA Blackwell GPU" | Holds for the specific cell it describes: 15s clip, 1xB200, VSA/DataFree vs. Base H3 Dense FA4. Not the speedup at 5s or 10s, and not a hardware-generation comparison |
| "Generate 15s 768p video in less than 13s...sub-realtime on 8xB200" | Holds only at 15s (12.88s). Worth qualifying at 5s (6.84s, 37% slower than real time) and 10s (11.66s, 17% slower) |
| Base model is a MiniMax H3 finetune | Holds — all three training networks (teacher, critic, student) initialize `from` the same MiniMax-H3 checkpoint per the training config, and the base model card confirms a 33B dense architecture |
| "On Blackwell" means a separate, hand-written CUDA kernel is running | Holds, but it's opt-in — `FASTVIDEO_VSA_SM100A=1` gates it (`video_sparse_attn_h3.py`); unset, even Blackwell hardware falls back to Triton by the kernel's own default dispatch, and FastVideo's benchmark script sets the switch itself |
| DMD2 training runs the exact code merged into FastVideo's public tree | Unresolved — `dmd2.py` implements the algorithm generically and matches the metadata's field names, but the only open MiniMax H3 training wrapper currently rejects `attn_kind="vsa"`, and no example config in this checkout pairs MiniMax H3 with `DMD2Method` |
| "Interest in testing on... Apple Silicon" | Complicates — a real, tested MLX runtime for FastH3 already ships in-tree (`fastvideo/mlx_runtime/minimax_h3.py`), flagged "Source runtime; T2VA only" in FastVideo's own support matrix; it runs dense attention, not VSA-H3's sparse mechanism |

## The take

FastH3 is a genuinely well-instrumented release: a checkpoint whose training recipe, tensor shapes, and
provenance are all readable without trusting the announcement's prose, which is rarer than it should be for
a "state of the art" claim. The two mechanisms are legitimately different kinds of savings — fewer transformer
calls from DMD2 distillation, cheaper attention within each call from a trained sparse-attention gate — and
having the Dense/DataFree ablation in the published table means you don't have to take FastVideo's word for
how much each one contributes; you can divide the table yourself and get 7.2x-7.5x from distillation and
1.1x-1.9x from sparsity on top, growing with clip length in exactly the direction the mechanism predicts. The
headline numbers are real numbers pulled from real cells in that table — they're just specific cells,
describing the longest clip length and the most GPUs FastVideo tested, and the announcement is honest enough
to publish the shorter, less flattering rows right next to them.

Reading the framework this checkpoint comes from adds the same texture, one level down. "On Blackwell" is a
real, hand-written, architecture-specific kernel — genuinely different tensor-core instructions from the
Hopper path, not a recompile — sitting behind an opt-in switch that FastVideo's own benchmark script happens
to flip by default, rather than something a Blackwell GPU does automatically. The training step that produced
the checkpoint runs more forward passes than the four the metadata advertises, and the specific glue code that
let an H3 student train with sparse attention doesn't appear to be in FastVideo's public tree as cloned here.
And "interest" in new hardware is further along for Apple Silicon than the announcement's cautious phrasing
suggests — a real MLX port already runs FastH3 end to end, dense attention and all. None of this contradicts
the checkpoint-level accounting above; it's the same honesty check applied one layer further down, into code
the announcement doesn't quote from at all.

For readers coming from the sparse-attention side, [VSA-H3's tile-and-gate design](/articles/minimax-sparse-attention)
sits alongside a growing family of ways to cut attention's quadratic cost in video and long-context models —
compare it with [Sol-Attn's training-free block routing](/articles/sol-attn) for video diffusion, or [a field
guide to the wider design space](/articles/attention-mechanisms). For the distillation side, [MrFlow's
training-free resolution reshuffle](/articles/mrflow-diffusion-acceleration) tackles the same
"fewer/cheaper diffusion steps" problem from a completely different angle. And for what a from-scratch
efficient video architecture looks like instead of a distilled one, [SANA-Video 2.0](/articles/sana-video2)
and [Chimera](/articles/chimera-diffusion) are the two most direct comparisons on this site.


## Update — 2 October 2026

FastVideo's data-free 4-step distillation is not the only few-step H3 in circulation. A community turbo LoRA, [`larryvrh/MiniMax-H3-Turbo-Lora`](https://huggingface.co/larryvrh/MiniMax-H3-Turbo-Lora) (Apache-2.0, base `Comfy-Org/MiniMax-H3` — verified), reaches the same four calls a different way: it is a LoRA on the stock H3 weights, run through ComfyUI, and its card describes "joint video + synchronized stereo audio in as few as 4 sampling steps instead of the usual ~20 — a ~5× sampling speedup" (reported), one that "keeps getting better as you add steps." It is not FastH3 — no VSA sparsity, no Data-Free training claim; it is step-count distillation applied to the base MiniMax checkpoint rather than the 90%-sparse student this article dissects.

The honest caveat is the LoRA author's own. The checkpoint is "still a preview," and at the full 4 steps with large, fast motion the recommended `v4` build can "produce motion-smear / trailing ghosting," which the card says is "largely" removed by running 6–8 steps instead — so the real-world speedup is nearer 3× than 5× for anything that moves quickly. Same lesson as the 14.38× dissected above: the step count the headline quotes and the step count you actually run are not always the same number.

A second community release, [`Wuli-art/MiniMax-H3-Turbo`](https://huggingface.co/Wuli-art/MiniMax-H3-Turbo), ships three tiers: its 4-step tier is a 2.78 GB (2.59 GiB) adapter, a rank-128 backbone LoRA plus fused video and audio output projections, one pair per step, that only loads on top of the official FL2VA transformer through the repository's own `run_fl2va.py` (the card warns against a generic LoRA loader) and so saves steps but not VRAM, since the full transformer still has to be resident. The 6- and 8-step tiers are complete Diffusers transformers that replace the official one, about 20.1B parameters each in their safetensors headers rather than 33B, because the per-block AdaLN projections are baked into fixed per-step tables (*added 12 October 2026*).

## Update: consumer GPUs and Trim

*Added 7 October 2026.*

On 6 October FastVideo [posted](https://x.com/haoailab/status/2107591980591227227) that FastH3 "now runs on a
single consumer machine," with a [blog post](https://haoailab.com/blogs/fasth3-rtx/) and five new
checkpoint families. Two things changed since the preview this article takes apart. The model is now FastH3 V2,
an eight-step DMD2 student at 80% attention sparsity (the preview was four steps at 90%). And there is a second,
smaller model, FastH3 Trim, with 8 of the 50 transformer blocks cut out. I wanted to know how a 35B-parameter
generator plus a 33B text encoder ends up in 8 GB, so I read the new checkpoints' headers and the code that
produced them. Most of it holds up, and the files let me check more than the post asks you to take on trust.

### The timings

FastVideo's table, end to end from prompt to MP4 for a 5-second clip with audio, warm server, median of two runs
on each of two prompts:

| Machine | V2, 832x480 | Trim, 832x480 | V2, 1344x768 | Trim, 1344x768 |
|---|---|---|---|---|
| RTX PRO 6000 (96 GB) | 13.5 s | 12.0 s | 36.5 s | 32.5 s |
| RTX 5090 (32 GB) | 14.8 s | 13.4 s | 38.6 s | 35.4 s |
| RTX 4090 (24 GB) | 54.6 s | 43.9 s | 154.6 s | 132.8 s |
| RTX 4090 capped at 8 GB | — | 82.0 s | — | — |
| DGX Spark | 141.4 s | 125.8 s | — | 340.1 s |
| 2× DGX Spark | 87.2 s | 78.3 s | — | — |
| Mac, M4 Max (36 GB) | — | 925.2 s | — | — |

Read these with the same care as the B200 table above. They are 480p, not the 768p of the preview's headline,
so a 5-second clip in 13.4 s on a 5090 is about 2.7 times slower than real time, not faster. The 16, 12 and 8 GB
rows are one 4090 with its memory capped, and the post says a real card that small will be slower. The Mac number
exists for Trim only. And Trim's advantage is modest where the GPU is not the bottleneck: 10% on the 5090, 20% on
the 4090, roughly what you'd expect from running 42 blocks instead of 50 (16% less transformer compute) once
offloading is added on the smaller card. The Spark result is the one I'd point at: the four-step preview took
243 s on one Spark in FastVideo's earlier post, and the eight-step models do twice the denoising and still finish
in 141 s.

<Figure
  src="https://media.thesatyajit.com/ai/articles/fastvideo-fasth3/fig6.png?v=5e8fe8be83bceda2"
  alt="Five 100%-stacked bars, one per machine, for a 5 s 480p FastH3 Trim clip. RTX PRO 6000, 12.0 s: denoise 78%, decode 17%, rest 5%. RTX 5090, 13.4 s: denoise 68%, decode 16%, rest 16%. RTX 4090, 43.9 s: denoise 75%, decode 17%, rest 7%. DGX Spark, 125.8 s: denoise 65%, decode 34%, rest 1%. Mac M4 Max, 925.2 s: denoise 91%, decode 8%, rest 2%."
  caption="Where the time goes for one Trim clip on each machine. The Spark spends a third of its time decoding video; the Mac spends 91% denoising because its attention still runs on a reference path (FastVideo, FastH3 on Consumer Hardware, Figure 5)."
/>

### Fitting 137.7 GiB into one machine

The BF16 pipeline is 137.7 GiB: a 62.1 GiB Qwen3-VL text encoder, a 65.3 GiB transformer, and 10.3 GiB of VAEs.
A 32 GB card can't hold the transformer alone. FastVideo shrank each piece on its own, and each trick is checkable.

<Figure
  src="https://media.thesatyajit.com/ai/articles/fastvideo-fasth3/fig3.png?v=a11be1cfb6af71e2"
  alt="Two stacked horizontal bars. BF16 H3: text encoder 62.1 GiB, DiT 65.3 GiB, VAEs 10.3 GiB, 137.7 GiB in total. FastH3 Trim with NVFP4: text encoder 15.3, DiT 11.1, VAEs 6.5, 33.0 GiB in total."
  caption="Checkpoint size by component, base H3 in BF16 against the Trim NVFP4 release (FastVideo, FastH3 on Consumer Hardware, Figure 2)."
/>

I summed the file sizes in the Hub listing to check the total. The Trim NVFP4 repository is 32.96 GiB: 15.33 for the
text encoder, 11.10 for the transformer, 6.49 for the two video VAEs and the audio VAE. 137.7 / 32.96 is 4.18,
so "4.2x smaller" is honest. The V2 BF16 text encoder's shards sum to 62.13 GiB, which matches too.

Start with the text encoder, which loses its last 14 layers. H3 reads hidden state 50 of a 64-layer Qwen3-VL and never asks it
to generate, so layers 50 to 63 and the language-model head compute nothing H3 uses. The shipped index has weight
entries for `language_model.layers.0` through `.49` and no `lm_head` at all, while its `config.json` still says 64
layers; the loader evidently trusts the weights over the config. The 50 survivors are stored as NVFP4
(`weight_packed`, `weight_scale`, `weight_global_scale` per projection). Dropping the layers is exact: the features H3
consumes are computed below them. Only the 4-bit storage approximates anything.

The AdaLN projections are my favourite find in the release, because nobody would guess how big they are. Every H3 block maps a
2,688-dimensional time embedding to its modulation vectors through one linear layer, and in the V2 checkpoint that
layer is `[96768, 2688]` per block. I counted it from the header: 13,010,457,600 parameters across 50 blocks, 37%
of the whole 35.05B transformer, 24.2 GiB in BF16. (96,768 is 18 x 5,376: six modulation vectors for each of the
three modalities, which is how the code indexes them, `timestep_indices * 3 + token_tags`.) All of that to
transform one number, the timestep.

FastVideo attacks it twice. For V2, a few-step model only ever sees eight timesteps, so the modulation each block
needs is a constant per step. The `FASTVIDEO_H3_ADALN_TABLE` switch in the quickstart loads a 0.14 GiB
`adaln_tables.pt` of precomputed outputs and never moves the 24.2 GiB of weights to the GPU. The DiT code says so
plainly: "the projection weights are not needed at all," and it raises an error if you ask for a timestep off the
ladder. That's why the V2 "consumer" repo can be 58.9 GiB on disk and still run on a 32 GB card.

Trim makes it permanent with a low-rank factorization. The input to every AdaLN projection is a smooth function of
a scalar, so sampled over the whole timestep range it spans very few directions.
`scripts/checkpoint_conversion/convert_minimax_h3_adaln_rank.py` samples 4,096 timesteps, takes the SVD of the
resulting embeddings, keeps 16 directions, and pre-multiplies every block's projection by that basis. Its docstring
says this removes "~39% of the model's parameters," and my count agrees: 13.01B of the 33.12B parameters that are
not the trained sparse-attention gate. The Trim header has exactly the shapes that predicts, a shared
`adaln_basis.weight [16, 2688]` and a `[96768, 16]` projection per block, about 1.6M parameters per block instead of
260M. One small mismatch with the blog: it says the factors are stored in FP16 (BF16 doubled the reconstruction
error, by its account), and the released Trim stores them in F32, which is at least as accurate.

Then eight blocks go. Trim's `transformer/config.json` carries `source_num_layers: 50` and the list of kept blocks,
so the removed ones can be read straight off it: blocks 6, 7, 9, 13, 15, 16, 22 and 23 of H3, all in the first
half, matching the blog's figure. FastVideo chose them by skipping one block at a time and measuring how much the
video and audio predictions moved, on four examples (motion, speech, music, sound events) at three noise levels:
4 x 3 x 50 = 600 measurements, which matches the blog's count. Ranking each block by its worst case under any
condition means a block that matters only for audio still survives. The first and last blocks (0, 1, 5, 47, 48, 49)
mattered most. The ranking script itself isn't in the public repository, so I couldn't reproduce the selection; I
could only confirm the result.

<Figure
  src="https://media.thesatyajit.com/ai/articles/fastvideo-fasth3/fig4.png?v=dc434fae08e82133"
  alt="Squares drawn to scale, area equal to transformer checkpoint size. H3 BF16, 65.3 GiB, tiled with blocks 0 to 49; blocks 6, 7, 9, 13, 15, 16, 22 and 23 red as removed, blocks 0, 1, 5, 47, 48 and 49 outlined as most sensitive. Arrows lead to smaller squares: Trim BF16 34.8 GiB (1.9x smaller), FP8 19.9 GiB (3.3x), INT6 14.3 GiB (4.6x), NVFP4 11.1 GiB (5.9x)."
  caption="The Trim transformer in each released format, area proportional to size. Dropping 8 blocks and the full-rank AdaLN halves it; storing 4 bits does the rest (FastVideo, FastH3 on Consumer Hardware, Figure 4)."
/>

Trim is 18,688,516,864 parameters by my count of its header, against 35,049,751,296 for V2: 1.88 times fewer. The
rest of the 5.9x comes from the number format. Its training metadata (`metadata.json`) shows the recipe: eight-step
DMD2, a frozen teacher and a trainable critic both initialised from base H3, the pruned student trained on 32 GPUs,
released at step 300 of a planned 1,500. One difference from the preview matters for this article's earlier
reading: the preview was "Data-Free" (`preprocessed_data_type: "text_only"`), and Trim's config says `"t2va"` and
points at preprocessed text-audio-video sets. Rollouts are still simulated from noise, and there is a new
`audio_anchor` term with weight 0.1, which I'd guess is where real audio latents come in; the code for that term
isn't in the public tree, so I couldn't confirm it.

### Four-bit activations that don't clip

The most technical post in the thread is the one about clipping, and I could check it end to end.

NVFP4 stores each group of 16 values as 4-bit floats (largest magnitude 6) with a shared FP8 scale (largest 448),
plus one global scale per tensor. For weights, you compute that global scale from the weights. For activations it
has to be fixed before the data arrives, and the lazy choice, a global scale of 1, caps inputs at 6 x 448 = 2,688.
Anything larger is clamped.

H3's activations are much larger. FastVideo ran 1,000 prompts through the full eight-step sampler, recorded the
largest input to every quantized linear, and stored one static scale per layer. The conversion script documents the
encoding: `_nvfp4_input_global_sf = 448 * 6 / amax`. So the calibration is in the checkpoint, and it can be read
back. I range-read all 294 of those scalars from Trim's `nvfp4_weights.safetensors` and inverted them.

<Fp4Clipping />

The result reproduces the post exactly. 294 calibrated layers (7 linears in each of 42 blocks). The MLP output
projection exceeds 2,688 in 40 of the 42 blocks; only Trim blocks 9 and 10 fit. Block 37 (H3's original block 45)
peaks at 368,640, which is 137.1 times the limit. What the post doesn't say is where the problem lives: all of it is
in that one projection, `ff.fc_out`. The other 252 calibrated layers (query, key, value, attention output, the
sparse-attention gate and the MLP input) peak between 6 and 840, under the limit. For those, calibration buys finer
resolution rather than preventing a clip. The heavy tail is the input to the second MLP matrix, after the
activation function, which is where large-activation outliers usually show up in transformers. A unit scale would
have flattened exactly the values the model leans on most, on every forward pass. For the format itself, see
[the NVFP4 Nemotron piece](/articles/nemotron-nvfp4).

<Figure
  src="https://media.thesatyajit.com/ai/articles/fastvideo-fasth3/fig5.png?v=d5d611d4217a2774"
  alt="Log-scale bar chart of the largest input to each FastH3 Trim block's MLP output projection across 42 blocks, against a dashed line at 2,688. 40 of the 42 bars exceed it; block 37 reaches 368,640."
  caption="FastVideo's own chart of the same quantity. The values I recovered from the checkpoint's stored scales match it bar for bar (FastVideo, FastH3 on Consumer Hardware, Figure 3)."
/>

V2 had calibrated only its MLPs. Its consumer checkpoint stores `_nvfp4_input_global_sf` on `fc_in` and `fc_out`
only, while Trim stores one on all seven linears, consistent with the post's "extends the FastH3 V2 NVFP4 recipe
from the MLPs to every quantized layer."

### Per device

On the RTX 5090, the first NVFP4 export quantized only the MLPs, leaving a 20 GB DiT that couldn't share the
card with the text encoder, so every request shuttled the DiT to host memory and back: 26.4 s at 480p, and 768p did
not fit. With attention and gate weights in NVFP4 too, the DiT stays resident and the text encoder streams in one
layer at a time. There's a nice systems detail in the host side. PyTorch's pinned allocator rounds each allocation
up to a power of two, so 2.87 GiB of FP4 weights cost 5.06 GiB of host RAM, enough to get a 60 GB container killed.
`fastvideo/hooks/pinned_memory.py` replaces it with a `PinnedTensorArena`: one ordinary host allocation, every tensor
packed at 256-byte offsets, page-aligned, and registered with `cudaHostRegister`. It falls back to the normal pinned
allocator with a warning if registration fails.

The RTX 4090 has no FP4 tensor cores, so it runs FP8: per-output-channel weight scales and per-token activation
scales. The trouble is that PyTorch's FP8 matmul with those row-wise scales runs at about 70 TFLOPS on Ada, below
BF16's 160, while the per-tensor kernel reaches 220 to 305. `fastvideo/layers/quantization/fp8_kernels.py` calls
the fast per-tensor kernel with unit scales and multiplies the output by `sx[i] * sw[j]` in one Triton pass. That's
algebraically the same thing, because a per-row and a per-column scale factor straight out of the dot product; the
only cost is one extra BF16 rounding on the output and 5 to 10% of the GEMM's time. The 4090 also quantizes queries
and keys to INT8 for the attention scores, which FastVideo measures at 1.6x faster with about 0.6% relative error,
and it streams part of the transformer from host memory each step. The Trim FP8 header shows the layout: every
block's q, k, v, out and both MLP matrices in `F8_E4M3` with a `[out, 1]` F32 scale, and the gate left in BF16.

A DGX Spark keeps everything in its 128 GB of unified memory, and two Sparks split a request with sequence
parallelism. On Apple Silicon both models run in MLX with INT6 weights. One caveat there: the post and the thread
link `FastVideo-FastH3-8-Step-V2-MLX-INT6` and `FastVideo-FastH3-Trim-8-Step-MLX-INT6`, and on 7 October both
returned 401 from the Hub API, which is what Hugging Face returns for a repository that doesn't exist or isn't
public. FastVideo's MLX guide gives the conversion command from the BF16 checkpoint, so you can build them yourself,
but the preconverted Mac weights aren't downloadable yet.

### What I'd use, and what I couldn't check

If you have a 5090 or a PRO 6000, V2 in NVFP4 is the one to run; Trim saves 10% there, and the post itself says busy
scenes lose detail. On a 4090, Trim's 20% matters more, and it is the only one that fits in 8 GB. The headline quality
claim, that V2 "beats base H3" at eight steps, has no metric behind it in this post, and as with the preview there is
no VBench or preference study anywhere in the release for me to check. I ran nothing on a GPU. The timings are
FastVideo's; what I verified is the arithmetic of the sizes, the shapes and dtypes in the headers, the removed blocks,
and the 294 calibration scales.

FastVideo added [Kandinsky 6](/articles/kandinsky-6-video) the same day, and [FreeVideo](/articles/freevideo-minimax-h3) gets the same H3
into 8 GB by a different route, a planner that decides where every block lives.

## Update: TaoMate-H3, three steps and a stream

*Added 15 October 2026.*

On 15 October ModelScope [posted](https://x.com/ModelScope2022/status/2110641830140559398) that Alibaba's TaoLive
AIGC team had released [TaoMate-H3-FL2VA](https://huggingface.co/TaoLiveAIGC/TaoMate-H3-FL2VA), "3-step streaming
audio-video generation" for H3, with "11.45× faster DiT inference and 10.6× faster time to first playable video."
It is a third few-step H3, and it gets there differently from FastH3: it splits the clip into short chunks and
generates them one after another, each in three denoising steps, against a bounded cache of the chunks before it.
The weights are on Hugging Face as well as [ModelScope](https://modelscope.ai/models/TaoLiveAIGC/TaoMate-H3-FL2VA).

<ModelCard repo="TaoLiveAIGC/TaoMate-H3-FL2VA" />

### What the paper describes, and what the adapter holds

The [TaoMate paper](https://arxiv.org/abs/2607.24359) (27 July) is not about H3. Its generator is "initialized from
a distilled LTX-2.3 checkpoint," 22.1B parameters, and the recipe is causal distillation: the student generates
its own chunks, its earlier chunks are re-noised before they are reused as context so it learns not to trust
them, and distribution-matching distillation (the DMD family FastH3 uses) runs over those rollouts at three steps
per block, plus a PCM consistency term between neighbouring steps. The paper's real contribution is a learned
memory: a fixed visual anchor and running audio and video states, read through extra attention layers and a FiLM
modulation that together add about 97.8M trainable parameters.

The H3 adapter doesn't contain that memory. I read its safetensors header: 416 tensors, all `F32`, 620,232,704
parameters, and every one is a rank-128 LoRA factor on `qkv_proj`, `out_proj`, `fc1` or `fc2` in H3's 50 blocks
and two token-refiner blocks. That is 11,927,552 parameters per block, times 52, exactly. No memory attention, no
FiLM. Its `config.json` instead declares a `full_prefix` context that is `parameter_free`, video-only, with a
60-second half-life, and `optimizer_step: 300`. So the H3 release carries the three-step chunked generator and the
runtime around it, not the paper's anchor memory. The paper's long-form quality tables are LTX-2.3 numbers and
tell you nothing about this adapter.

### The numbers

The 11.45x is on the model card, and it is a T2AV benchmark (text to audio and video), not FL2VA: one 8× H20 node,
TP2 × Ulysses4, a `480x864` canvas, a 10-second clip, one seed.

| Metric (reported) | TaoMate-H3 | MiniMax H3 | Ratio |
|---|---|---|---|
| Pure DiT time | 14.810 s | 169.572 s | 11.45x |
| First final chunk latent | 6.148 s | 170.052 s | 27.66x |
| First playable video | 17.287 s | 183.313 s | 10.60x |
| Peak DiT memory | 31.37 GiB | 32.03 GiB | — |

All three ratios check from the card's three-decimal times (169.572 / 14.810 = 11.45). Dividing the tweet's
rounded 169.6 s by 14.8 s gives 11.46 instead, which is only rounding. The baseline behind the 10.6x is 183.313 s.
Memory doesn't move.

Two things I'd read into the table (reasoned). First, step count explains little of it. A 10-second run is "24
generation forwards and eight clean-KV updates," so 32 passes against the 49 FastVideo counted for H3's default
schedule, about 1.5x. The rest comes from each forward covering one short chunk against a bounded cache rather
than the whole clip. Second, the first playable video lands 11.1 s after the first chunk's latent is final, and
2.5 s after the whole clip's DiT time would have finished. The card doesn't break down the 11.1 s, but in this
benchmark the stream isn't yet what you wait on.

### Against FastH3

| | FastH3 Preview v1, VSA | TaoMate-H3 T2AV |
|---|---|---|
| Steps | 4 for the whole clip | 3 per chunk |
| Attention | 90% VSA sparse | not stated |
| Weights shipped | full checkpoint (or hybrid adapter) | rank-128 LoRA, 2.48 GB |
| Resolution | 1344x768 | 480x864 |
| Hardware | 1× B200 | 8× H20 |
| What is timed | end to end, with audio and muxing | DiT only |
| 10 s clip, base to distilled | 377.4 s to 31.1 s, 12.13x | 169.572 s to 14.810 s, 11.45x |

The speedups look alike and are not comparable. FastH3's is the whole pipeline on one Blackwell GPU at 2.5 times
the pixels; TaoMate's excludes text encoding, VAE decode and media encoding and runs on eight H20s, a Hopper part
with a fraction of an H100's compute. The closer like-for-like is FastH3's distillation alone, 7.52x end to end
at 10 seconds, and even that mixes in fixed overhead TaoMate's number leaves out. Neither release publishes a
quality metric for H3.

### Licence

The adapter ships MiniMax's own licence file, byte-identical to the base repository's. It is a Model Derivative
under that agreement, so the territorial exclusion [the MiniMax H3 piece](/articles/minimax-h3) covers applies:
no use in the EU, the UK, South Korea or the US. I ran nothing; the timings are TaoLive's.

---

*Sources: the [FastH3 Preview v1 announcement](https://haoailab.com/blogs/fasth3-preview/); the
[FastVideo-FastH3-4-step-Preview-v1-VSA-DataFree model card and files](https://huggingface.co/FastVideo/FastVideo-FastH3-4-step-Preview-v1-VSA-DataFree)
on Hugging Face, including its `checkpoint_metadata.json`, `provenance.json`, and safetensors headers, read
directly via the Hugging Face API; the [MiniMax H3 base model card](https://huggingface.co/MiniMaxAI/MiniMax-H3);
the [FastVideo repository](https://github.com/hao-ai-lab/FastVideo), specifically
`fastvideo/attention/backends/video_sparse_attn_h3.py`, `video_sparse_attn.py`, and
`video_sparse_attn_h3_probe.py`; the DMD2 training method at
`fastvideo/train/methods/distribution_matching/dmd2.py` and the MiniMax H3 training model at
`fastvideo/train/models/minimax_h3/minimax_h3.py`; the hand-written CUDA kernels and their build gating in
`fastvideo-kernel/csrc/attention/` and `fastvideo-kernel/CMakeLists.txt`, and the kernel dispatch logic in
`fastvideo-kernel/python/fastvideo_kernel/block_sparse_attn.py` and `block_sparse_attn_256.py`; the FastH3
benchmark reproduction script `examples/inference/basic/basic_fasth3.py` and its accompanying
`examples/inference/basic/README.md` and `examples/serving/README.md`; the Apple Silicon MLX runtime at
`fastvideo/mlx_runtime/minimax_h3.py` and `windowed_attention.py`, and FastVideo's own
`docs/inference/support_matrix.md`; the [DMD2
paper](https://arxiv.org/abs/2405.14867) (Yin et al.) and the [VSA
paper](https://arxiv.org/abs/2505.13389) (Zhang et al.). For the October update: the [FastH3 on Consumer Hardware post](https://haoailab.com/blogs/fasth3-rtx/) and [thread](https://x.com/haoailab/status/2107591980591227227); the safetensors headers, `config.json`, `fastvideo_inference.json` and `metadata.json` of `FastVideo-FastH3-Trim-8-Step`, `-Trim-8-Step-NVFP4`, `-Trim-8-Step-FP8`, `-8-Step-V2` and `-8-Step-V2-NVFP4-Consumer`, plus the 294 stored activation scales of the Trim NVFP4 file, read by HTTP range request; and, in FastVideo at commit `33d8173`, `scripts/checkpoint_conversion/convert_minimax_h3_adaln_rank.py`, `convert_minimax_h3_modelopt_nvfp4_dit.py`, `fastvideo/models/dits/minimax_h3.py`, `fastvideo/hooks/pinned_memory.py`, `fastvideo/layers/quantization/fp8_kernels.py`, `scripts/benchmarks/minimax_h3_4090/README.md` and `docs/getting_started/installation/mlx.md`. For the 15 October update: the [ModelScope post](https://x.com/ModelScope2022/status/2110641830140559398), the `TaoLiveAIGC/TaoMate-H3-FL2VA` model card, `config.json`, `LICENSE` and safetensors header (read by HTTP range request), and the [TaoMate paper](https://arxiv.org/abs/2607.24359) (Gan et al.). Figures 3 to 6 are the post's own charts, rendered from its SVGs. The validation-sample stills are FastVideo's,
shown for commentary. The tile-selection, pipeline, call-count, real-time, and kernel-routing diagrams are
original, built from the sources above.*
