1. Quick start
Install withuv pip install "sglang[diffusion]" --prerelease=allow, then choose
a verified recipe below. Setup changes the deployment; Server and Request expose
orthogonal startup and sampling choices.
The generated Server command already includes the recommended encoder policy.
Change a Server option only for a deliberate trade-off; Request options do not
reload the model.
/data/minimax-h3.
AMD and Grace Blackwell currently offer the Python form; the other NVIDIA
recipes also offer Docker.
To use ModelScope through the same normal sglang serve path, prefix the copied
command with SGLANG_USE_MODELSCOPE=true and replace the model path with
MiniMax/MiniMax-H3. Keep the selected variant and topology flags unchanged.
For platform-specific installation details, see the
SGLang Diffusion installation guide.
2. Model capabilities
MiniMax-H3 is a native joint video-and-audio model for text-to-video-and-audio, first/last-frame control, and multimodal reference conditioning. Its main strength is producing the picture and stereo soundtrack together, so speech, music, ambient sound, and visible events can stay aligned without a separate audio-generation pass. Choose H3 when synchronized audiovisual output or reference-driven generation matters more than a lightweight deployment. The released recipe targets a 768-pixel short edge at 24 fps for 4–15 seconds, and its capabilities are split across two checkpoint partitions; serving every mode therefore requires separate FL2VA and Ref2VA deployments.
Video-to-video (V2V) is a supported
ref2va use case, not a fourth task
value. Run the Ref2VA partition and provide a video reference in
conditions. A hybrid ref2va request may also include the same ordered
first/last keyframes accepted by fl2va, but it must still contain at least one
reference condition.
Use the selected Hub’s root model ID: MiniMaxAI/MiniMax-H3 on Hugging Face
or MiniMax/MiniMax-H3 on ModelScope. Select the checkpoint variant with
--model-variant: fl2va serves both t2va and fl2va, while ref2va
serves reference-conditioned requests. SGLang owns the checkpoint-directory
mapping; do not point --model-path at a manually downloaded subdirectory.
3. Deployment details
The builder accepts legal custom GPU counts and topologies, marking them Unverified until the exact recipe has completed end-to-end validation. Static H3 head or partition violations disable Copy before they reachsglang serve.
Grace Blackwell
Select GB300 or GB200 in the builder. The default is one Linux ARM64 host with four GPUs, Ulysses4, and resident weights. This follows the four-GPU compute-tray layout; an NVL72 rack is not a single 72-GPU process host. For two four-GPU hosts, set Nodes = 2 and GPUs / node = 4. The builder emits Ulysses4 inside each host, Ring2 across hosts, and replicated encoders. Set the same reachable Head address on both hosts and use node ranks 0 and- Run the generated command once per host, with the same SGLang revision and
dependencies. Let
sglang serveresolve and download the selected weights.
quality="lossless".
Ref2VA and multi-host commands remain Unverified. See the
GB300 measurements for the tested workload.
Checkpoint and adapter formats
Start with the command emitted by the builder. Every row below is an overlay on the same native SGLang pipeline; component repositories contribute their own config and weights, while weight files retain the base component config. Storage layout and inference behavior are separate contracts: for example, a PEFT file may be either a normal style adapter or a timestep-distilled Turbo adapter.
The rows compose rather than enumerate every cross-product. A Turbo-merged INT8
ConvRot checkpoint, for example, must satisfy both the Turbo sampling contract
and the ConvRot storage/backend contract.
H3’s Qwen3-VL text encoder also handles image understanding; there is no separate
image_encoder component. Select the conditioning checkpoint, not an optional
generation-tail file for prompt rewriting. The uncensored or Heretic label
describes a weight modification, not a separate loader or a guarantee of output quality.
For H3, the registered component names are transformer, text_encoder,
video_vae, and audio_vae. The shorter --transformer-weights-path and
--text-encoder-path aliases remain supported. conditioning_projection is an
H3 text-encoder sidecar key, not a standalone model component. Plain
video/audio VAE safetensors can use --component-weights-paths.video_vae or
--component-weights-paths.audio_vae, but SGLang does not currently advertise
a native quantized H3 VAE format.
Pre-quantized files are self-describing: do not combine those rows with
--quantization or --component-quantizations.*. Only byte-identical official
full weights—whether loaded from the original model, Diffusers component, or a
weight-only layout—belong to the consistency GT. Pruned, quantized,
compact-encoder, and LoRA routes are outside that baseline and the audited
quality="high" contract. Packed and per-layer mixed formats reject FSDP unless
their row says otherwise; see
Quantization for backend-wide constraints.
LoRA tensors alone do not make an execution-coupled release portable. Sparse-
attention/SLA adapters and causal-streaming adapters such as RAVEN also require
their matching attention or streaming pipeline; they are not standard H3 LoRA
overlays in SGLang. Likewise, a remixed checkpoint that prescribes a custom
sampler is only covered when that sampler contract can be reproduced—the fact
that its safetensors layout loads is not sufficient.
For a four-card H200 host, keep the full BF16/FP32 model resident by default.
The model fits without FSDP, so this path avoids the per-block parameter
all-gathers of the memory-oriented FSDP profile:
4×H200 resident
4×H100 fastest
--tp-size 4 --ulysses-degree 1 when lower resident memory matters more than
the last few percent of latency. FSDP remains a verified capacity option, but
its per-block weight all-gathers do not make it the H100 speed default:
4×H100 FSDP capacity
2×RTX 5090 fastest lossless
kitchen_int8. Keep vae out of
--layerwise-offload-components: putting the VAE decoder in layerwise
offload re-streams about 9 GiB on each of 167 decode tiles. Default
attention stays fa (exact). Approximate backends are opt-in; see
Attention Backends.
Install comfy-kitchen first (pip install comfy-kitchen).
1×RTX 4090 24GB
sglang serve. Drop --quantization for the BF16
baseline; everything else stays identical. GPU peak stays about 18 GB
either way because streaming offload is set by the offload buffers and VAE
decode, not the weight dtype.
The first launch resolves every selected source through the normal Hub path. If
a repository requires authentication, export a Hugging Face token in the
server environment; no manual pre-download is required.
For MiniMax-H3, --performance-mode speed deliberately keeps the DiT eager.
The current torch.compile path changes the model’s numerical output, so no
recommended lossless preset enables it implicitly. An explicit
--enable-torch-compile true remains available for controlled experiments, but
do not use it to generate consistency ground truth.
Singularity hybrid weights
Singularity is an FL/Ref fusion fine-tune, not a complete pipeline repository. Keep the official model ID for the encoders and VAEs, and select one exact transformer file:2×B300 hybrid checkpoint
Minimax-h3_Singularity_ref2va_v1.3_int8.safetensors. SGLang downloads the
selected file automatically. Do not add an online quantization override.
hybrid requires an explicit weight override; it does not convert the official
Ref2VA weights into a multimode model. Request task and conditions retain
their usual meanings, including conditions: []
for t2va and keyframes for fl2va.
Start with quality: "lossless" and the standard 50-point schedule. Here
lossless disables additional request-time approximations; it does not undo
INT8 quantization, pruning, or fine-tuning. The author’s recommended Ref2V
Turbo LoRA is a separate optional adapter, not an automatically inferred
4-step schedule. Reference fidelity can differ from the official model; see
the author’s guidance
before applying the LoRA sampling contract.
Advanced: precomputed AdaLN cache
The model card notes that about 13B H3 parameters are AdaLN branches whose outputs can be precomputed for inference. The public base checkpoint contains the original branches, not a ready-to-use cache. SGLang therefore keeps the standard path as the default. When an inference-only deployment has a fixed sampling schedule, build a cache from the already materialized transformer directory on CUDA, then pass it to the usualsglang serve command. This does not alter the denoising formula:
the cache stores the BF16 outputs of the original AdaLN linears.
Command
$TRANSFORMER_PATH is the FL2VA/transformer or Ref2VA/transformer
directory in the normal SGLang/Hugging Face snapshot; the builder never
downloads a second copy. A cache only covers the scheduler settings used to
create it, including its mode, step count, flow shifts, and condition noise
values. SGLang rejects a request outside that coverage instead of silently
changing conditioning. Cache mode supports the matching unquantized checkpoint
only.
Advanced: online AdaLN rebuild with a host cache
--minimax-h3-adaln-online true needs no prebuilt artifact: the server drops
the 24.2 GiB of adaln_proj weights from the GPU and computes each request’s
AdaLN outputs from the checkpoint on demand, bit-exact with the resident-weight
path. Because a rebuild pass streams the whole 24.2 GiB, the first request of
every new (task shape, num_inference_steps, flow_shift, audio_flow_shift)
combination pays several seconds; after that the plans are served from a
64-slot GPU slab (LRU per plan) backed by a pinned host cache
(--minimax-h3-adaln-host-cache-gb, LRU per schedule, default 8 GB per
rank), so mixed-schedule serving does not re-read the checkpoint. Plan sets
that exceed the host budget are simply recomputed on their next occurrence.
Expert escape hatches live in environment variables:
SGLANG_DIFFUSION_MINIMAX_H3_ADALN_GPU_PLANS resizes the GPU slab (needed
only beyond 65 inference steps) and SGLANG_DIFFUSION_MINIMAX_H3_ADALN_FP32
computes the one-time projections in fp32 (experimental; not bit-comparable
to resident weights, validate end-to-end before production). LoRA adapters
that modify adaln_proj are rejected in both cache modes rather than
silently ignored.
Both cache modes hold values derived from adaln_proj, so a runtime weight
update is only accepted when the cache can follow it: online mode takes a disk
update whose target directory carries native adaln_proj safetensors, and
rejects everything else (tensor updates, and directories without those
tensors) before a single weight is written. A sidecar is built offline and
cannot be regenerated in the server, so weight updates are rejected outright;
rebuild the sidecar against the new weights and restart.
Serve MiniMax-H3 on Ascend NPUs
For Ascend NPU, follow the NPU installation guide before starting the server. The Ascend commands below explicitly enable the Cache-DiT configuration used for the reported performance measurements. Remove theseSGLANG_CACHE_DIT_*
variables to use lossless denoising. See the Ascend NPU topology comparison
in the Benchmarks section for the measured eight- and four-NPU latency.
The measured latency configuration also passes --dit-cpu-offload false to
keep the transformer resident on the NPUs. Omit this flag when lower device
memory usage is more important than avoiding CPU-to-NPU transfer latency.
For an eight-NPU host, the validated topology is TP2 + SP4 with Laser
Attention. Use Ascend Flash Attention by replacing laser_attn with fa.
8-NPU
4-NPU
4. Generate video and audio
MiniMax-H3 uses the asynchronous OpenAI-compatible video endpoint. Choose a generation mode below, submit a job, poll its status, and then download the completed MP4.- T2VA
- FL2VA
- V2V
- Multimodal Ref2VA
MiniMax-H3 supports output durations from 4 through 15 seconds, inclusive. The
following request keeps the verified 5-second profile at a 768-pixel short
edge. MiniMax-H3 resolves the aligned output canvas and frame count from
The output contract is an MP4 containing H.264 video at 24 fps and one AAC stereo audio stream at 32 kHz.
target.Command
file:// URIs must
refer to files visible inside the SGLang server environment.
5. LoRA recipes
H3 accepts both native fused adapters and standard Diffusers/PEFT adapters. Native adapters target modules such asblocks.*.attn.qkv_proj; PEFT adapters
may instead provide separate to_q, to_k, and to_v projections and the
default adapter namespace. SGLang normalizes both layouts.
The following pinned FL2VA adapters have distinct purposes:
The H3 request field controls the number of sigma grid points, including the
terminal zero; the denoising loop therefore runs one fewer model evaluation.
This is why an adapter described as 8-step uses
9, and a 4-step adapter uses
5, in the request.
All three use the same launch shape. Pinning the filename is required for
repositories that publish multiple revisions, and is also recommended for a
reproducible single-file recipe:
Command
auto merges an adapter into ordinary resident weights to avoid per-step LoRA
matmuls, but keeps the dynamic path for FSDP-sharded weights where a full
gather can increase peak memory. Use dynamic when one resident server must
switch repeatedly between base and LoRA output.
Use the filename, scale, and request schedule from the table together. The
4-evaluation LightX2V recipe is the more aggressive latency/quality tradeoff.
Its checkpoint has rank 128 but omits the training alpha from both the file and
repository metadata, so --lora-alpha 8 is required to reproduce the author’s
reference implementation. Start with the Larry 8-evaluation recipe when
preserving fine visual detail is more important than minimum latency.
The pinned files above were trained for the FL2VA partition and apply to
t2va or fl2va requests. Some repositories, including LightX2V, publish
separate files for Ref2VA/Ref2V; select one explicitly for a ref2va server
rather than reusing an FL2VA file. Those Ref2VA files are not yet a pinned,
validated recipe on this page. Also avoid stacking a distilled adapter with
quality: "high": both alter denoising, and that combination has not been
quality-validated.
AdaLN-pruned Diffusers components that publish adaln_basis and adaln_mean
can also consume a LoRA trained against the released full-width AdaLN modules:
SGLang projects those adapter factors onto the pruned coordinates at load time.
A structurally modified checkpoint without that metadata still fails closed,
and packed GGUF weights remain incompatible with LoRA.
6. FastH3: 4-step distilled preview
FastVideo/FastVideo-FastH3-4-step-Preview-v1-VSA-DataFree is a 4-step DMD2 distillation of MiniMax-H3, trained data-free with Video Sparse Attention (VSA) at 0.9 sparsity and 64-token tiles. Only the T2VA capability was distilled: requests must usetask: "t2va", and fl2va /
ref2va requests are rejected. The checkpoint inherits the MiniMax-H3
Community License.
Pass the repository directly to --model-path. The flat native-Diffusers
upload is materialized into the base-H3 layout through a registered model
overlay; the only non-symlink step is a one-time re-serialization of the
roughly 10 GB video VAE on first launch.
4×B300 VSA-H3
task: "t2va", conditions: [], and a target such as
{"short_edge": 768, "aspect_ratio": "16:9", "duration_seconds": 5.0}. The
request default is num_inference_steps: 5: five points on the standard
shift-12/shift-3 sigma grid, i.e. the four distilled DiT evaluations. Any
other step count is rejected.
video_sparse_attn_h3 (VSA-H3) is the trained sparse policy: an in-tree
Triton block-sparse kernel (SM90 / SM100 / SM103) over segment-pure prefix
tiles and (4, 4, 4) video tiles, driven by the checkpoint’s trained
to_gate_compress compression branch. Only the DiT runs sparse; the token
refiner, text encoder, and VAEs keep their dense defaults. Ulysses sequence
parallelism is supported. See
Attention Backends for
VSA_sparsity, vsa_mode, vsa_dense_first_n_steps, and
vsa_dense_layers. Every dense backend that runs on base H3 (fa,
torch_sdpa, …) also runs on the FastH3 weights without VSA flags, and
sglang generate takes the same flags as sglang serve.
Measured latencies for the 4× B300 recipe are in
FastH3 on B300.
FastH3 rejects deployment options that do not apply to the distilled preview
instead of silently ignoring them: --model-variant, quality: "high",
fl2va / ref2va requests, and, with VSA-H3, --ring-degree greater than 1,
torch.compile, and breakable CUDA graph execution.
Upstream labels this checkpoint a preview. Quality gaps versus base H3 on hard
motion and fine detail are properties of the released distillation, not of the
SGLang port. Use base MiniMax-H3 when output quality matters more than
latency.
7. VDN-H3: hybrid attention, 8-step distill
Video DeltaNet (VDN) is a hybrid attention architecture that approaches the speed of linear attention while maintaining near-lossless quality. It splits the video-video attention into two complementary branches: a sliding-window softmax branch for local frame pairs (five consecutive latent frames form a chunk, and each chunk attends to itself, the previous chunk, and the following chunk; the first and last frames, text and audio stay dense) and a bidirectional linear branch, Video Delta Attention, for long-range context. OpenVDN/vdn-minimax-h3 applies it to MiniMax-H3: the releasedstage-dmd-step-250 checkpoint adds a
4.3 GB linear branch and OpenVDN’s own 8-step DMD2 LoRA on the unchanged H3
backbone. It is the FL2VA partition, so it serves t2va and fl2va (first,
last, or both keyframes); ref2va is rejected. The weights inherit the
MiniMax-H3 Community License.
Pass the repository directly to --model-path. On first launch a registered
overlay prefuses both adapters into the transformer weights (a 62 GB write)
and attaches the linear branch; the Qwen3-VL conditioner and the VAEs are
hard-linked from MiniMaxAI/MiniMax-H3. Keep SGLANG_DIFFUSION_CACHE_ROOT on
the same filesystem as the Hugging Face cache with at least 90 GB free.
8×B200
--num-gpus 4, 2 or 1 gives the smaller Ulysses recipes in the benchmark
table; sglang generate takes the same flags. --warmup-num-frames /
--warmup-resolutions warm up at the clip length and canvas you will serve;
without them the first long request pays 2 to 3 s of allocator growth and
kernel setup.
Requests use the same video endpoint as the base model with task: "t2va"
and conditions: [], or task: "fl2va" with the
keyframe conditions, and a target such as
{"short_edge": 768, "aspect_ratio": "16:9", "duration_seconds": 14.375} (the
345-frame paper workload). The default num_inference_steps: 9 is the only
accepted value: nine sigma grid points, eight DiT forwards. Each keyframe adds
about 2,000 dense rows, so an fl2va forward costs a little more than t2va.
hybrid_window_attn_h3 is required: a dense backend would silently skip the
linear branch and the gates and produce the wrong model. On Blackwell
(SM100 / SM103 / SM120) the transformer defaults to online MXFP8;
--quantization bf16 opts out. Before SM100, --quantization fp8 is base
H3’s per-channel fp8 path, and SM80 runs the bf16 DiT (62 GB; budget for
--layerwise-offload-components). Ampere and Ada are enabled but not
benchmarked. Ulysses sequence parallelism is supported; --model-variant,
quality: "high", --ring-degree greater than 1, torch.compile, and
breakable CUDA graph execution are rejected. The backend’s
--attention-backend-config keys are listed in
Attention Backends.
Measured latencies for 1, 2, 4 and 8 B200s are in
VDN-H3 on B200; single-card and PCIe multi-card numbers
for the RTX PRO 6000 are in VDN-H3 on RTX PRO 6000.
8. Sampling and output controls
MiniMax-H3 supports more than one output per prompt. The video API acceptsnum_outputs_per_prompt (or OpenAI-compatible n) from 1 through 10. Offline
generation accepts --num-outputs-per-prompt N; --num-outputs N is the short
alias. A scalar seed is expanded deterministically as seed + output_index, so
the outputs do not reuse the same noise.
Same-prompt fan-out reuses text conditioning. On the verified 2× RTX 5090
recipe, a 5-step two-output request completed in 155.39 seconds versus 78.11
seconds for one output, while producing two distinct valid MP4 files. The
independent denoise and decode passes remain sequential on this 32 GB profile
to keep peak memory bounded; the grouped path adds essentially no orchestration
overhead. Use server replicas when lower wall-clock latency for many variants
matters more than per-server memory efficiency.
For example, set "num_outputs_per_prompt": 2 in any request above. After the
job completes, download both outputs by selecting each zero-based variant:
Command
Choose the quality level
quality is a cumulative request-scoped optimization parameter with three
levels:
"lossless"(default): the exact reference path. Output is bit-exact against the reference implementation and the CI ground truth."extra-high": includes the global fusion-only tier but does not enable Cache-DiT or another approximate optimization. MiniMax-H3 currently has no request-gated fusion site, so its denoise path is the same aslossless."high": the audited accelerated path. Quality is guaranteed (the audited Cache-DiT configuration measures SSIM 0.931 / PSNR 28.16 dB againstlossless), but output is no longer bit-identical to the reference.
quality: "high" request
mounts its audited Cache-DiT policy at the batch boundary, and a later
quality: "lossless" or quality: "extra-high" request removes the hooks
before denoising.
Start the validated server once:
Command
- lossless (default)
- extra-high
- high
Native denoising with no feature-cache approximation. This is the default;
omitting the field is equivalent.
Request field
These numbers use 1344×768, 124-frame, 24 fps T2VA with 50 inference steps,
video flow shift 12, audio flow shift 3, and three fixed prompt/seed pairs on
4×H200. The prompts cover a quiet detailed scene, fast multi-subject action,
and a moving close-up portrait.
inference_time_s is averaged across the three
prompts; the quiet-scene point is itself the mean of two repeats.
SSIM and PSNR compare decoded, frame-aligned output with the lossless
result for the same prompt and seed. They measure trajectory deviation, not
absolute perceptual quality: the high path can produce a different but
still plausible realization. It also changes the joint audio-video denoise
trajectory, while these two metrics cover video only.
quality: "high" currently accepts only the exact workload and 4×H200
deployment above; other hardware, task modes, request shapes, step counts, or
flow shifts fail before denoising. Offline generation uses the same level
name, for example sglang generate --quality high.
quality selects a model sampling level and can change generated content.
output_quality controls only output-file compression; it is a separate field.quality field and set --enable-cache-dit or the
process-wide SGLANG_CACHE_DIT_* defaults. Any explicit quality, including
"lossless" and "extra-high", takes H3 off the generic Cache-DiT path. The
24 GB layerwise recipe above can use the same switch; skipped blocks are
not streamed.
Command
9. Feature contracts and advanced recipes
The generated command already contains the recommended topology and encoder setting. Use the detailed reference below only when applying an optional override or checking its installation, topology limits, and validation evidence.- Lossless runtime
- Attention backends
- Online quantization
- Cube sparse attention
- SubBlock sparse attention
- Encoder scheduling
The recommended BCG is lossless for a matching captured signature, but capture reserves extra
GPU memory. Re-measure the live H3 text length before reusing this bucket for a
different task profile, reference set, resolution, or prompt template.
speed launch already combines resident components with
Ulysses sequence parallelism. Validation status below applies only to the
listed hardware and topology; it is not inherited by a similar GPU family.The verified parallel, placement, and matching-signature BCG paths keep the
BF16/FP32 weights and denoising math.
torch.compile is the exception called
out above. Always use the eager BF16/FP32 launch when producing CI consistency
ground truth.For the validated 1344×768 Ref2VA profile, use a 5504-row text bucket so both
the server warmup and reference-conditioned requests share the captured
signature:Command
10. Configuration notes
- MiniMax-H3 produces the canonical 24 fps output; request duration is expressed through
target.duration_seconds. target.duration_secondsmust be between 4 and 15 seconds, inclusive. The command picker defaults to the verified 5-second profile.- Use a 768-pixel short edge for the released quality recipe. The aligned output dimensions are derived from
target.aspect_ratio. flow_shiftcontrols video diffusion andaudio_flow_shiftcontrols audio diffusion.- V2V uses
task: "ref2va"with avideoorvideo_audioreference; it is served by theRef2VApartition and is not a separate public task value. conditions[].start_time_secondsselects a non-negative offset for a video reference. Its visual and audio streams are always sought together.- Ref2VA condition order is semantic and must match the one-based material tags in the prompt. For Ref2VA,
target.aspect_ratio: "auto"resolves to the model’s 16:9 fallback rather than inheriting a reference asset’s geometry. - The distilled pipeline uses a single denoising branch, so CFG parallelism does not apply. Do not enable it:
--enable-cfg-parallel trueor--cfg-parallel-sizegreater than 1 is rejected instead of duplicating the positive branch. Explicitly disabling CFG, or setting its size to 1, remains a valid no-op. - The released visual VAE quality recipe uses overlapping tiled decode. SGLang keeps that recipe by default and distributes complete tiles across the decode group; this changes scheduling, not the computation inside each tile.
- H3 rejects
--vae-config.parallel-decode-mode spatialandspatial_shard: validation found output mismatches. Use the default released tiled recipe. - Keep the default
--encoder-parallel auto. With the server’s defaultbatching_max_sizeof 1, single-node H100/H200/B200/B300 recipes with peer-to-peer access fold the Qwen text encoder over otherwise idle Ulysses ranks. This is separate from DiT tensor parallelism. A pure-TP recipe already shards the encoder over its TP group and does not add a world fold. - For throughput-oriented serving, select DP (batched throughput). The picker pairs
--encoder-parallel dpwith an editable--batching-max-sizegreater than 1. Encoder DP stays inside each DiT replica and composes with encoder TP: the H100 TP2 + Ulysses2 recipe has two TP-sharded encoder copies that can split a batch, while the RTX 5090 pure-TP2 recipe has one encoder copy and therefore no additional batch-DP degree. It provides no benefit for a batch of one and is not bitwise-identical to the unsplit deployment. - Use explicit Fold to prioritize single-request latency and encoder memory on a measured high-bandwidth single-node topology. Use Replicate as the compatibility path when folding or encoder DP is unsuitable.
--use-fsdp-inference trueshards only the DiT. MiniMax-H3 preserves the original FP32 dtype of its patch, time, and output projections during FSDP all-gather, so this path does not trade numerical correctness for memory. On 4×H100, prefer TP2 + Ulysses2 for speed; use FSDP as an explicit capacity policy rather than assuming it is faster.speedkeeps model components resident, whileautoapplies the model-aware 120 GiB residency threshold.memoryprioritizes avoiding OOM and includes the executable VAE decoder in its default layerwise set. A measured recipe with sufficient headroom can opt into--component-residency vae=resident; the 2×H100 CI recipe does this because the VAE’s 4.8 GiB/GPU cost avoids repeated decoder transfers during tiled decode. DiT residency and prefetch knobs remain scoped to the DiT. Usespeedonly after confirming that the complete target workload fits.- Breakable CUDA graph execution is an explicit opt-in, not part of the recommended
speedpreset. It requires--enable-breakable-cuda-graph, every served size in--warmup-resolutions, and--bcg-text-bucketsthat cover the live H3 condition sequence. The validated 1344×768 Ref2VA recipe uses 5504; other task profiles and reference sets may need a different value. It preserves eager output for matching captured signatures, but graph capture consumes additional GPU memory and may provide little latency benefit when Ulysses attention and collectives dominate, so benchmark it on the target topology before enabling it.
11. Benchmarks
The picker exposes resident and FSDP profiles on NVIDIA datacenter GPUs. GPU counts are properties of the selected recipes, not a claim that every platform requires that many GPUs. The detailed tables below report performance only for the configurations with collected measurements:GB300 single-host
Four requests on 1 host × 4 NVIDIA GB300, using Linux ARM64, SGLang main15d2cbcc90fc,
PyTorch 2.13.0+cu130, and NCCL 2.29.7. The source checkout was installed with
python3 -m pip install -e "python[diffusion]" --upgrade inside
lmsysorg/sglang:latest; this is a source-validation environment, not a claim
that the image’s bundled release contains that revision.
The command matches the GB300 default in the builder: Ulysses4, resident
weights, automatic encoder folding, native BF16/FP32, platform-default
Dynamic cuDNN/FA attention, and eager execution. The model was downloaded by
sglang serve from MiniMaxAI/MiniMax-H3.
The workload uses the builder’s cat-band prompt, FL2VA T2VA, a 5-second request
at a 768-pixel short edge, 50 inference steps, quality="lossless", one output,
and seed 1101. Every MP4 contained video and audio and passed a full decode check.
These are client-observed completion times, including up to one second of
status-polling delay. Download, model loading, and server warmup are excluded.
This is a deployment smoke/latency measurement, not a cross-framework quality
audit, a minimum-GPU claim, or an extrapolation to GB200/NVL72 scaling.
Ascend NPU topology comparison
Both topologies used Laser Attention and the explicit Cache-DiT configuration from the Ascend launch commands, with--dit-cpu-offload false keeping the DiT
resident. The measured workload was one 5-second T2VA request at 1344×768,
124 frames, 24 fps, and 50 inference steps.
These are individual end-to-end measurements for each topology, not averages.
The eight-NPU topology had 46.8% lower end-to-end latency than the four-NPU
topology.
B300 precision and encoder placement
A 12-configuration sweep on a single 8× B300 host, covering both checkpoint partitions, both transformer precisions, and all three text-encoder placements. It answers one question — how long does one request take, and how much memory does it need.What was measured
Hardware. 8× NVIDIA B300 SXM6, single node. Model.MiniMaxAI/MiniMax-H3, both released weight partitions.
Serve command. Exactly the recipe the picker emits for B300, plus the one
or two overlay flags under test:
Command
--model-variant (fl2va / ref2va), --quantization
(unset for BF16 / fp8), and --encoder-parallel (auto / fold /
replicate). Nothing else differs between the 12 servers.
This is a single-request latency sweep (batching_max_size: 1), so encoder DP
is intentionally excluded: it cannot distribute a batch of one. Use the
DP for a request batch setting above for a compatible multi-request
deployment; the table below does not claim a measured H3 DP speedup.
Driver.
Command
Results
FastH3 on B300
The same 4× B300 host served FastH3 with the VSA-H3 recipe above (1344×768 at 24 fps with audio,task: "t2va",
num_inference_steps: 5, seed 1000, eager BF16, Ulysses4, VSA_sparsity 0.9).
E2E is the client wall clock of a /v1/videos request including decode,
muxing, and file output, median of three requests after one warm request;
the stage columns are the server timings of the same request. H3 aligns the
requested durations to 124, 243, and 362 frames. Client RTF is E2E divided by
the video duration:
All three requests finish faster than playback. Dense FA on the same weights
and topology takes 3.77 / 9.84 / 18.45 s (
sglang generate, stage sum): it is
competitive at 5 s, and VSA-H3 pulls ahead from 10 s on. At 5 s,
TP2 + Ulysses2 (3.42 s, 62,290 MB), FSDP + Ulysses4 (3.42 s, 50,984 MB), and
online --quantization fp8 (2.93 s, 64,204 MB) trade a little latency for
peak memory.
VDN-H3 on B200
An 8× B200 (SM100, 183 GB) host served VDN-H3 on the paper workload: 1344×768 at 24 fps with audio for 14.375 s (345 frames, 102 latent frames, about 104k packed rows),task: "t2va",
num_inference_steps: 9 (8 DiT forwards), seed 1000, hybrid_window_attn_h3,
eager, and the warmup run at the served clip shape
(--warmup-num-frames 345 --warmup-resolutions 1344x768), so every forward
of the served request is steady state; without those flags the first forward
pays 2 to 3 s of allocator growth and kernel setup. “Steady
s/NFE” is the mean of forwards 2 to 8. The OpenVDN reference rows ran the released
inference stack (8nfe_tuned_fp8.yaml, infer_ulysses.py) on the same host
and the same clip length, with its Ulysses layout (parallel.softmax_ranks)
swept at every GPU count rather than assumed. Every row below comes from one
campaign, one arm at a time on an otherwise idle node; a repeated arm moves by
about 3% across nodes, so treat smaller differences as noise:
On 8× B200 the SGLang Ulysses8 path runs the paper workload at 0.88 s/NFE
(7.0 GPU-seconds per NFE) against the published 1.40 s/NFE of OpenVDN’s 5+3
branch-parallel layout; the whole request (text encoding, 8 forwards, joint
decode) completes in about 8.7 s after warmup. At this GPU count the step is
launch- and copy-bound in the linear branch rather than FLOP-bound, and the
transformer runs online
mxfp8 by default (e4m3 with one E8M0 scale per 32
elements into cuBLASLt’s block-scaled GEMM, with the activation quant fused
into the adaLN and SwiGLU producers).
Against the published 8× B200 headline (1.40 s/NFE, 11.2
GPU-seconds per NFE), the SGLang 4× B200 run spends 6.7 GPU-seconds per
NFE, with half the GPUs and half the all-to-all fan-out. At equal GPU count
SGLang is 1.48× faster at two cards (3.30 vs 4.87 s/NFE), 1.55× at four
(1.67 vs 2.59) and 1.60× at eight (0.88 vs 1.40), while on one card the two
stacks are within 4% of each other (6.03 vs 6.25 s/NFE quantized, 7.45 vs 7.66
in BF16). The advantage is therefore parallel scaling rather than per-GPU
kernel work: SGLang holds 86-91% parallel efficiency from 2 to 8 cards against
the reference stack’s 56-64%, and sweeping the reference stack’s own layout
does not close it (its best split is 8% better than standard Ulysses at eight
cards, 1.40 against 1.52 s/NFE).
On one B200 both single-GPU rows run with the DiT resident under the auto
memory policy (128 GB peak quantized, 156 GB in BF16, of the card’s 183 GB),
so no --layerwise-offload-components flag is needed at this clip length and
the single-GPU rows are compute-bound.
VDN-H3 on RTX PRO 6000
The same paper workload (1344×768, 345 frames, 8 DiT forwards, seed 1000,hybrid_window_attn_h3, --performance-mode speed, served-shape warmup) on
RTX PRO 6000 Blackwell Server Edition cards (SM120, 96 GB, PCIe, no NVLink).
The window runs on FA4’s sm120 kernel and the transformer defaults to online
mxfp8 (a cutlass sm120 block-scaled GEMM); --quantization fp8 maps to it.
One card needs --layerwise-offload-components text_encoder: the fp8 DiT
(33 GB) and the bf16 text encoder (48 GB) do not both fit, and the whole-module
--text-encoder-cpu-offload re-homes the encoder in one piece and runs out of
memory when it is used. Multi-card Ulysses goes over PCIe; the all-to-all is
the bulk of the step there (54% of GPU time at 8 cards), so the per-card
efficiency drops with count. A 2-card run should use a pair on one PCIe
switch (nvidia-smi topo -m shows PIX): a pair across the CPU root complex
measured 15.7 to 17.0 s/NFE on a shared host.
For comparison the same code on B200 measures 6.03 / 3.30 / 1.67 / 0.88 s/NFE
at 1 / 2 / 4 / 8 cards (NVLink, 86% parallel efficiency at 8).
H200 topology comparison
The same four-card H200 host completed both lossless resident placements with the standard 1344×768, 5-second, 50-step T2VA request (fixed prompt and seed, eager BF16/FP32, back-to-back runs on an otherwise idle host). Latency is the warmed-up request; the first pair uses the default warmup request, the second pair adds--warmup-resolutions 1344x768 so warmup already covers the served
resolution:
Ulysses4 stays the H200 latency default: 5.0 % faster end-to-end than
TP2 + Ulysses2 once warmup covers the served resolution (1.6 % with the
default warmup, where first-request cold start masks the topology gap).
TP2 + Ulysses2 shards the DiT weights and holds peak memory about 30 GB per
GPU lower, which is why it remains the 80 GB H100 recipe. Matching the warmup
request to the served resolution removes the cold first-request cost on both
topologies (about 10 s end-to-end on this workload).
H200 cross-node scaling
Long references and long durations grow the packed sequence length, and Ulysses alone cannot scale sequence parallelism past the GPU count of one node without either violating head-count divisibility or exposing all-to-all traffic across the slower inter-node link. H3 combines node-local Ulysses with cross-node Ring: Ring’s point-to-point KV rotation is designed to overlap with attention compute, which fits a slower cross-node link better than an all-to-all does. Hardware. 2 nodes × 8× NVIDIA H200 SXM, same cluster, InfiniBand between nodes. Serve command. The cross-node cell the picker emits for H200, run identically on both nodes with--node-rank set to 0 and 1:
Command
The gain grows with sequence length because Ring’s per-hop communication
cost stays roughly constant while attention compute grows quadratically
with sequence length, so V2V’s longer packed sequence benefits more than
T2VA’s shorter one. With the point-to-point KV rotation pipelined against
attention compute, one V2V request’s full denoise stage completed in
68.1–68.3 seconds versus 128.6 seconds on the single-node 8-GPU baseline
(−47.0%), with byte-identical output to the unpipelined cross-node path.
Cross-node determinism was confirmed separately: the same request run
twice against the same cross-node deployment produced byte-identical
output. A cross-node run’s output is not expected to bit-match a
single-node run of the same prompt and seed — Ring’s online-softmax merge
across hops accumulates floating-point operations in a different order
than single-node attention, which is an expected source of bit-level
difference, not a correctness regression.
H100 topology comparison
The same four-card H100 host completed three lossless placements. TP2 with Ulysses2 was the fastest; TP4 used the least memory:RTX 5090 capacity run (two cards)
The single-card recipe is a different one — see RTX 5090 single card, physical desktop below; the twenty resident layers here are half a layer per GPU under TP2 and do not transfer to one card. The verified two-card RTX 5090 host used TP2 with layerwise offload. The full 50-step, 1344×768, 5-second request completed in 559.67 seconds: 525.05 seconds of denoising and 33.61 seconds of decoding, with a 26.3 GiB sampled peak per GPU.Consumer GPU tuning
On consumer hardware the binding question is not which card you have but how much host RAM sits behind it. H3’s weights are about 108 GB — 61.73 GB of DiT and 46.18 GB of text encoder — so no consumer configuration holds them all, and where the shortfall lands decides the throughput. The command — most consumer machines need exactly one flag beyond the model:consumer single GPU, lossless
--layerwise-resident-layers video_vae=36 for
the 13 s decode; with ~96 GB of host RAM and 16 GB+ of VRAM, add
--dit-layerwise-resident-layers 4 for the 6 s step. That is the whole flag
surface. The builder at the top of this page has consumer
cards and a Host RAM selector: pick your budget and it emits this command with
your tier’s measured expectations attached as comments. The table below is the
same data in one view.
Unified-memory machines are the exception: on a DGX Spark (GB10, 128 GB
shared between CPU and GPU) launch with no flags at all. The deployment
still exceeds the pool, automatic offload engages on its own, and its placement
beat the explicit recipe above by 2.1× on the denoise (12.1 vs 25.8 s/it
measured on the same box) — the VRAM/host split that justifies every flag in
this section does not exist there. Expect ~12 min of load, a ~5.5 min text
encoding stage per request (steady-state compute on this chip, not a stall),
and ~12 min per warm 480P request.
Two budgets, and what each one buys
The left column is one configuration measured twice, at 318.94 s and 356.37 s;
the 12% spread tracked host load on a shared machine, so treat smaller
differences than that as unresolved. The right column is 120.92 s at a 16 GiB
allocator cap. Four resident DiT layers is what Recipe B buys its speed with,
and it is also why 12 GiB is not enough for it.
Read the host row carefully, because the two numbers are not the same kind of
memory. Anonymous host memory — pinned buffers and pageable copies — has to fit,
and the kernel cannot reclaim it. Page cache backing a file mapping is
droppable, so it does not count against the budget even though it shows up in
VmRSS; use RssAnon from /proc/<pid>/status when checking. Likewise measure
VRAM with torch.cuda.set_per_process_memory_fraction and let the allocator fail,
rather than reading nvidia-smi, which reports the caching allocator’s reserved
pool and overstates the requirement.
Inside 32 GB the weights cannot be pinned, so each denoise step copies about
60 GiB from the checkpoint mapping, and a mapped source is synchronous however
the copy is requested: the driver stages it through its own buffer, so the
transfer neither overlaps compute nor runs at pinned bandwidth. That is where
the step goes, and giving the host room to pin the weights instead is what takes
it to 6.01 s.
Two caveats on the constrained number, both from instrumenting the run rather
than from arithmetic. The machine it was measured on has 2 TB of host memory, so
the kernel kept all 107.7 GiB of mapped checkpoint pages resident: major faults
across a whole request were 6, and read_bytes was zero. Nothing was read from
disk. A real 32 GB host cannot cache 107.7 GiB, so it will fault and re-read,
and should be expected to be slower than the figures here rather than equal to
them — an NVMe is a requirement, not a recommendation. Measure your own machine
with major faults (/proc/<pid>/stat) on the worker process, not on the
launcher, which holds no weights.
Recipe A — fits 12 GB VRAM + 32 GB host
12 GB + 32 GB, lossless
unconstrained host, lossless
video_vae=36holds every decoder block for the decode only — residency arms at the decoder’s first block and releases when it finishes, so the denoise still runs on an empty card. It fits 12 GB because decoder weights are held in their decode compute dtype (fp16) from load, which halves them to ~4.9 GiB; the rounding was already part of every output (the decode computes in fp16 autocast), so the result is bit-identical, and the decode drops from 60 s streamed (or 209 s on a busy host) to ~10 s. Theexpandable_segmentsline stays: the decode sits close enough to the cap that fragmentation otherwise tips it over.- Leave
--enable-torch-compileoff, as elsewhere on this page. Layerwise offload rebindsparam.dataon every layer, so compiled graphs do not get the benefit they would on resident weights. - Recipe A’s flags are what the automatic policy should choose on its own. Until
the model declares its own placement,
--performance-mode memoryplus the explicit component list is what makes it happen; pass them.
Layerwise offload: host memory available: N GiB— what the runtime sees after loading, not your DIMM size. On a 32 GB host expect single digits here; a much larger number means another process’s memory accounting (or a container limit) is in play.leaving N GiB of weights on the checkpoint mapping— the expected line on a 32 GB host: the DiT streams from the checkpoint file. If instead the log reports pinned weights, the runtime decided your host has room — which is faster, and means the 32 GB figures above do not apply to you.Loaded video_vae: ... host mmapvshost pageable— where the VAE landed (decoder weights are ~4.9 GiB once held in their decode dtype).Loaded <component>lines carry the same buckets for every component.
expandable_segments line, and if it persists drop to
video_vae=24 and take the partially streamed decode.
Against ComfyUI, on the same weights
Same unpruned bf16 checkpoints, same card, same sampler settings (cfg 1.0,
euler_ancestral, sigma shift 12.0/3.0, seed 1101), 864×480 / 124 frames / 20 NFE:
When host memory is free, the engines are close and sglang is ahead:
Inside 12 GB, both engines run these weights, and one measurement convention
matters on each side. ComfyUI’s memory manager reads system RAM and adapts, so
the rows below patch
psutil to a pretend host size — the same convention the
sglang rows use. Its --reserve-vram is also soft: told to keep 12 GiB free it
still peaked at 13.5 GiB, a figure a real 12 GB card cannot give it, so both
engines here run under the same hard allocator cap
(set_per_process_memory_fraction), where its peak stays at 12.1–12.3 GiB.
Under that cap, Recipe A wins the whole request at every host size:
Same GPU, same load window, unpruned bf16 checkpoints, outputs verified. All
figures are anchored at 480P — activations grow with the pixel count, so at
768P drop the resident DiT layers to 0 first, then
video_vae to 24 if the
decode still collides.
One convention behind that table is the one a home machine does not share: the
host sizes above are psutil patches on a 2 TB lab machine, so the kernel kept
the whole checkpoint in page cache and nothing was read from disk. A physical
host of that size re-reads the streamed weights every step, and what that costs
is computable — bytes per step = (50 - resident DiT layers - layers the host pin budget covered) x 1.23 GiB. The courier overlaps that read with compute, so
the drive stops being the denoise clock once its sequential rate exceeds those
bytes divided by the card’s step time. A 32 GB host covers roughly 13 layers,
which puts a 24 GB card at ~38 GiB/step and a 12/16 GB card at ~46 GiB/step: a
PCIe 4.0 NVMe (6–7 GiB/s) clears both, a PCIe 3.0 drive (~3.2 GiB/s) becomes the
clock, and a SATA SSD is not usable for this model. Resident DiT layers remove
1.23 GiB/step each, but only while the streamed set is larger than the pin
budget — once the read fits under the step’s compute time, more of them buy
nothing and only cost VRAM.
An earlier revision of this page recorded 38 s/step on a physical 4090 with a
990 Pro, reading 52.9 GB per step — about 1.4 GB/s, and faulted sequentially, so
almost none of it showed in majflt (measure read_bytes, not major faults).
That rate was the old path, not the drive: the pinned-store pool rounded every
block up to a power of two, so the pin budget over-committed and the machine had
to run with pinning off, and the layers that stayed mapped faulted in 4 KiB at a
time. Exact-size pinning and O_DIRECT reads through the courier removed both,
and the physical 5090 run below shows the drive fully hidden behind compute. A
4090 on a 32 GB host is derived to return to its compute wall (~8.5 s/step) on a
PCIe 4.0 drive; that machine has not been re-measured. The
VRAM axis holds too: capped at 16 GiB the same recipe wins ~250 vs 292–301 s,
and at 24 GiB (with --dit-layerwise-resident-layers 6 — measured at a
22 GiB cap so a desktop’s own allocations fit; a headless card can raise it
to 10 for under 1% more) ~8.5 s/step vs ComfyUI’s 249–260 s requests. Four changes carry it: the VAE staying on its checkpoint mapping (#35862, root fix
#35946), per-layer pinning with net-cost accounting (#35867), the courier
thread that ships still-mapped layers through pinned slots (#35882), and
decoder weights held in their decode dtype from load (#35967) — which is what
lets video_vae=36 fit and turns the decode from the slowest stage (54–96 s
streamed) into the fastest (~10 s, faster than ComfyUI’s own 15–25 s). Output
equivalence is bit-level: the fp16-held decode reproduced the fp32-store run’s
video byte for byte, and the audio stream is bit-identical.
Stage by stage under the cap: text encoding is even (both stream the same
48 GB Qwen3VL), the denoise leads at 32–48 GB hosts and sits within
run-to-run variance of ComfyUI at 64 GB (162 vs 159 s), and the decode leads
everywhere. Two ComfyUI notes that still matter: --fast-disk measured no
faster than its default on this lab host — though on a physical 60 GB desktop
its default is OOM-killed while loading (55.6 GB of anonymous memory) and
--fast-disk is what makes it run at all — and stacking
--novram --cache-none --disable-pinned-memory made things strictly worse
(69.1 GiB anonymous, 750 s requests) — the adaptive default is the right
configuration on a small host.
The path ComfyUI ships for 12 GB cards uses
minimax_h3_fl2va_pruned_int8_convrot and qwen3vl_32b_minimax_h3_nvfp4_awq,
i.e. an int8 DiT and an NVFP4 text encoder, and its pruned bf16 file is 40.2 GB
against the unpruned 66.3 GB. Those are different weights, so it is not a
like-for-like comparison with the recipes above.
RTX 5090 single card, physical desktop
Every consumer figure above this point was measured with at least one axis simulated: a hard allocator cap standing in for VRAM, apsutil patch standing
in for host RAM, and a lab machine whose page cache held the whole checkpoint.
This run had none of that — an RTX 5090 (32 GB) in a Ryzen 9 9950X desktop with
60 GB of RAM, an 8 GB swap file and a Samsung 9100 PRO on PCIe 5.0, on Ubuntu
24.04. The workload matches the comparison above: FL2VA T2VA, 864×480, 124
frames, 20 steps, cfg 1.0, euler_ancestral, sigma shift 12.0/3.0, same seeds and
keyframes on both engines, unpruned bf16 weights on both sides.
32 GB VRAM + 60 GB host, lossless
Three things a capped run cannot settle:
The denoise is at the card’s compute wall, not the drive’s. The two engines
are within noise of each other per step, and prefetch depth 2 and cuDNN SDPA
each measured as no change. The 51.3 GiB the DiT reads from the drive per
request is fully overlapped — across a whole request the compute thread waited
0.9 s for the courier.
Host RAM decides how much traffic there is to hide. At 60 GB the pin budget
covers 34 of the 50 DiT layers, so only about two layers per step come off the
disk. The 46 GiB text encoder is never pinned — streamed layers take the budget
first — and is read whole, once per request, at the drive’s sequential rate:
that is the 4.2 s stage, against 12.1–12.9 s when the same bytes go through the
page cache.
Neither engine’s default command survives this machine. ComfyUI’s is
OOM-killed during load (55.6 GB of anonymous memory) and needs
--fast-disk;
sglang’s was too, until pinned stores were allocated at their exact size instead
of the allocator’s next power of two. Even now the automatic placement keeps no
resident DiT layers and streams the VAE on every decode, so the flags above are
what reach the numbers in the table.
Two caveats to carry into your own machine. The run finished with its 8 GB swap
file full, because the pin budget takes 95% of the memory available after
loading and there is no smaller setting yet — on a machine that is also your
desktop, expect that pressure and give the card more resident layers, since a
resident layer is one the host no longer has to pin. And these are 480P figures:
at 768P drop the resident DiT layers first, then video_vae to 24.
RTX 4090 24 GB single-GPU run
One RTX 4090 D 24 GB completed the 1344×768, 107-frame, 20-NFE T2VA workload (euler,torch.compile and step caching disabled) with DiT and
text-encoder layerwise offload. Same process: load → warmup (seed 0) →
timed (seed 42); only the timed pass is reported. GPU peak stayed about
18 GB.
kitchen_int8 + FA changes Linear numerics only. The sol_attn /
sage_attn / hybrid rows also change the attention algorithm, so speed
and pixel fidelity rank in opposite orders there. Default remains
kitchen_int8 + fa. Cache-DiT can share this layerwise recipe; omit
quality and see the quality-level section.
AMD Instinct task and scaling runs
The AMD recipes keep the released BF16/FP32 precision policy and use AITER packed attention. The picker emits the fastest measured topology, 8 GPUs with Ulysses degree 8. All runs below completed full H.264/AAC decoding and representative-frame inspection.
The task matrix used 8 GPUs and 50 denoising steps. The scaling matrix uses
one 1344×768, 209-frame T2VA request and changes only the GPU count and
matching Ulysses degree:
For a measured lower-count AMD deployment, set both
--num-gpus and
--ulysses-degree to 4, 2, or 1. AITER packed attention matched segment-wise
BF16 SDPA at cosine similarity 0.9999991655 on MI355X and 0.9999991059 on
MI300X.