Repository navigation
[Perf] [AMD] diffusion: VDN-H3 and MiniMax-H3 ROCm MI355X compile path, AITER kernels, MXFP8 fixes - #3
Open
jackyhkust wants to merge 10 commits into
Open
[Perf] [AMD] diffusion: VDN-H3 and MiniMax-H3 ROCm MI355X compile path, AITER kernels, MXFP8 fixes#3jackyhkust wants to merge 10 commits into
jackyhkust wants to merge 10 commits into
Conversation
…ample. The gfx950 run needs the AITER window path. The linear branch stays on eager Cholesky, and the breakable CUDA graph stays off.
The VDN attention module's Ulysses all-to-all and frame-sum all-reduce used raw async_op=True collectives and Work.wait(). Dynamo cannot trace a Work handle, so every call forced a hard graph break under torch.compile. Switch the three call sites (_vdn_a2a_rows_to_heads, _vdn_a2a_heads_to_rows, and the frame_work all-reduce in _vdn_ulysses_hybrid_core) to torch.distributed._functional_collectives and resolve results with the existing _maybe_wait() helper from usp.py at the point of use, keeping the launch-early/wait-late overlap. Extend the exchange round-trip test with a 4-rank case (heads=8 so local heads divide evenly). MI355X, compiled, 1344x768x124f, 9 steps (last-clip stage sum): u2 t2va: 108.66 s -> 65.10 s u4 t2va: 32.12 s, u4 fl2va: 32.84 s
…n on gfx950 The window passes, the dense leg, the full-cover dense call and the token refiner ran through AITER Triton varlen on every ROCm arch, because the grouped-varlen CK/ASM kernel hangs on MiniMax-H3 packed lengths on gfx942. On gfx950 it does not hang and is faster. Register aiter.flash_attn_varlen_func (how_v3_bf16_cvt=2 when supported) at import as the opaque custom op sglang::vdn_aiter_ck_varlen, so torch.compile treats it as one node, and dispatch _fa_varlen to it. The default is aiter_ck when is_gfx95_supported(), else triton; SGLANG_VDN_WINDOW_BACKEND overrides. The text-encoder dense path stays on Triton. If aiter cannot be imported, the backend logs a warning and keeps Triton. Kernel check (1 GPU): rel L2 vs Triton 6-8e-5, compiled == eager bit-exact under fullgraph=True; 1.36-1.63x faster on large segments. MI355X x8, compiled u8, t2va 768x1344, 9 steps, fp8, total_duration_ms: fox 124f: 4.564 s -> 4.227 s (-7.4%) ex2 345f: 13.071 s -> 11.450 s (-12.4%) piano 345f: 13.028 s -> 11.455 s (-12.1%)
…on gfx950 On gfx950 the video VAE ViT attention was pinned to math SDPA. Fused ROCm SDPA (AOTriton flash and efficient) returns intermittently wrong outputs at the ViT shapes (head dim 64, large B x S) with HIP 7.16/7.17 and torch 2.13: 12-31% of trials, rel L2 up to 1e-1. Math is exact but upcasts to fp32 and runs unfused. Add SGLANG_MINIMAX_H3_VAE_ROCM_ATTN = aiter | math | sdpa (gfx95 only; default aiter). aiter calls aiter.flash_attn_func on the [B, S, H, D] tensors the decoder already holds; fp32 inputs and a missing aiter fall back to math. sdpa keeps the fused path as an opt-in. AITER stays at the fp64 reference and is run-to-run deterministic. MI355X x8, decode vs math: -626 ms (124f), -1792 ms (345f). End to end, total_duration_ms, math -> aiter: fox 124f: 4.842 s -> 4.139 s ex2 345f: 13.157 s -> 11.337 s piano 345f: 13.125 s -> 11.323 s
… matmul on ROCm MIOpen runs the BigVGAN resblock dilated fp32 Conv1d with naive_conv on gfx950: 3-9 ms per conv, about 50x the existing _conv1d_as_matmul path. Route groups=1, dilation>1, fp32 Conv1d to unfold + matmul first on ROCm. SGLANG_MINIMAX_H3_AUDIO_DILATED_CONV_MATMUL=0 restores the conv path. MI355X: -248 ms audio decode per 124-frame clip.
…RS=1 With SGLANG_LOG_FP8_LAYERS=1, Fp8Config.get_quant_method logs whether each linear leaf name is quantized or skipped by --quantization-ignored-layers, once per (name, decision). This verifies the FP8 scope at runtime, e.g. that an ignore list leaves exactly qkv_proj, out_proj, to_out_linear, fc1 and fc2 in FP8 for VDN-H3. No effect when the variable is unset.
VDN-H3 remaps --quantization fp8 to mxfp8 on Blackwell (sm100) and sm120. The loader only forwarded quantization_ignored_layers for fp8/mxfp4/kitchen_int8, and MXFP8Config.get_quant_method had no skip check, so every linear layer was quantized. Forward the ignore list for mxfp8, skip ignored prefixes with is_layer_skipped, and log decisions under SGLANG_LOG_FP8_LAYERS like Fp8Config.
can_use_mxfp8_swizzled() is False under torch.compile, so apply() hit the Triton quantizer guard (k % 32 ValueError), and Inductor cannot lower _scaled_mm_v2 with swizzled scales. Register the activation quantizer and the block-scaled GEMM as opaque custom ops (sglang::mxfp8_quantize_act, sglang::mxfp8_gemm) with fake impls. Eager kernels and numerics are unchanged.
sgl-project#38671 changed MiniMax-H3 num_inference_steps from sigma grid points to denoise transitions (DiT forwards), and set the VDN-H3 default to 8. The VDN-H3 sampling params on this branch kept the old count (default 9, accepts 9 and 50). With the new stages, a request for 9 runs 9 forwards on a 10-point grid, which is off the distilled 8-NFE schedule and about 9% slower. Use the upstream count again: the default is 8 (the distilled schedule, nine sigma grid points), and 8 and the 50-step comparison sample are accepted.
jackyhkust
marked this pull request as ready for review
October 22, 2026 23:48
This comment has been minimized.
This comment has been minimized.
jackyhkust
force-pushed
the
feat/vdn-h3-rocm-mi355x
branch
from
October 23, 2026 03:50
04967d1 to
80f81b0
Compare
This comment has been minimized.
This comment has been minimized.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
VDN-H3 (
OpenVDN/vdn-minimax-h3) and MiniMax-H3 changes from thesgld-vdn-compilebranch, rebased onto currentmainas a linear series. Most changes are ROCm (MI355X, gfx950); the two MXFP8 commits fix Blackwell.usp._maybe_waithybrid_window_attn_h3window on AITER CK on gfx950SGLANG_MINIMAX_H3_VAE_ROCM_ATTN=mathis the exact controlnaive_conv(about 50x slower)SGLANG_LOG_FP8_LAYERS=1--quantization-ignored-layersfp8is remapped tomxfp8, and the ignore list was dropped, so every linear was quantized--enable-torch-compilewith MXFP8 failsTwo benchmark-only commits from the branch are not in this PR: the
SGLANG_VDN_SPD_INVERSE=invworkaround for old rocSOLVER, and the opt-in per-tensor FP8 cuDNN path.Rebase notes
test_minimax_h3_vae_parallel_modes.py: kept the branch version; it already drops the mocks ofh3_vae_qk_rmsnorm_ropethat [Refactor] kernels/diffusion/tests: Prune dead code and fix tests that never ran sgl-project/sglang#44690 removed.denoising.py:is_hip()replaced withis_rocm(); the VSA and PDD changes frommainare kept.attention.pychange merges cleanly with [Refactor] kernels/diffusion/tests: Prune dead code and fix tests that never ran sgl-project/sglang#44690 (fused QK path removed,envs.*flags).configs/sample/minimax_h3_vdn.py: the branch version used the count from before [Fix] MiniMax H3: honor requested inference step count sgl-project/sglang#38671 (default 9, sigma grid points). With the new stages, 9 ran 9 forwards. The last commit uses the [Fix] MiniMax H3: honor requested inference step count sgl-project/sglang#38671 count. Requests for the distilled schedule now usenum_inference_steps=8.Testing
On 8x MI355X, at the pre-rebase branch (
5400d640e5plus the MXFP8 commits), patched against unpatched: fox (124 frames) +0.0%, ex2 (345 frames) −0.3%, piano (345 frames) −0.2%. Video is bit-identical, and the FP8 layer plan and recompiles are unchanged.B200: the MXFP8 commits were validated on 8x B200 (matched FP8 layer coverage, compile on, no recompiles in the timed request).
All 22 changed files parse in the run image.
MI355X rerun on this branch (
80f81b089f): passed. 8x MI355X, compiled Ulysses 8,num_inference_steps=8. Canonical value is the last of 3 requests:5400d640e5+ MXFP8)maingive a different sampling path.CI States
Latest PR Test (Base): ❌ Run #39897757357
Latest PR Test (Extra): ❌ Run #39897757298
Latest PR Test (AMD ROCm 10): ❌ Run #39897757369