Skip to content

[diffusion] MiniMax-H3: tiered AdaLN plan cache (pinned-host tier + per-plan LRU) - #37266

Merged
BBuf merged 13 commits into
sgl-project:mainfrom
triple-mu:feat/minimax-h3-adaln-tiered-cache
Sep 3, 2026
Merged

BBuf merged 13 commits into
sgl-project:mainfrom
triple-mu:feat/minimax-h3-adaln-tiered-cache

Conversation

@triple-mu

@triple-mu triple-mu commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Motivation

Under --minimax-h3-adaln-online, any plan miss re-reads all 24.2 GiB of adaln_proj weights from the checkpoint (nsys-measured 5.8-6.7 s of GPU idle per request), and slab overflow triggers a full reset, so two alternating 50-step schedules re-read the checkpoint on every request. This PR adds per-plan LRU eviction and a pinned-host tier so previously built plans swap back in over PCIe instead. Repeated-schedule requests drop 94.8 -> 88.4 s on 1x H200 with bit-identical outputs.

The schedule space (task shape, num_inference_steps, flow_shift, audio_flow_shift) is request-controlled in serving, so the combination count is unbounded; the cache keys stay "the exact fp32 bit patterns of one step's deduped timesteps", which every combination collapses into.

Modifications

  • GPU slab: eviction becomes per-plan LRU with in-flight protection instead of a full reset; geometry and pointers are unchanged (breakable-CUDA-graph contract). Requests that cannot fit are rejected at admission, before the encode stages.
  • New pinned-host tier, --minimax-h3-adaln-host-cache-gb (default 8 GB per rank, 0 disables): one pinned slab in 9.25 MiB pages, LRU at schedule granularity because a rebuild pass streams every layer regardless of how few plans it misses; over-capacity schedules recompute instead of raising. Capacity is MIN-reduced across ranks and state transitions commit synchronously inside prepare, keeping multi-rank collectives in lockstep.
  • Plan slots are resolved on the host in prepare_adaln_plans and passed to forward as a device tensor, removing the per-step device-side lookup and its capture-breaking host sync; block_all() replaces 50 per-block gathers with one.
  • Fail closed on four pre-existing traps: adaln LoRA deltas were silently dropped in cache modes (disk adapters and LoRA IPC alike), Diffusers-layout checkpoints only failed on the first request, and weight updates left every tier stale. BaseDiT.validate_weight_update_source and validate_lora_layers run before a single weight is written, so an update the cache cannot follow is refused with the served model untouched instead of pairing new weights with the old checkpoint's conditioning.
  • MiniMaxH3AdalnCache moves into its own module (pure relocation). Expert knobs are env vars (SGLANG_DIFFUSION_MINIMAX_H3_ADALN_GPU_PLANS, SGLANG_DIFFUSION_MINIMAX_H3_ADALN_FP32); the host-cache size is the only new CLI flag.

Behavior changes: none in the default numerics path (the rebuild stays bit-exact with resident adaln_proj weights: per-plan-M GEMM, TP-sharded N + all-gather). The env-gated fp32 rebuild changes bits by construction and is off by default. LoRA adapters touching adaln_proj now raise in cache modes instead of silently using base weights. Runtime weight updates are constrained in cache modes: online mode accepts a disk update whose target carries native adaln_proj safetensors and rejects everything else (tensor RPC, and directories without those tensors); a sidecar deployment rejects weight updates outright, since the sidecar is an offline artifact the server cannot regenerate.

Accuracy Tests

A/B (host tier 8 GB vs disabled), 1x H200, t2va, --minimax-h3-adaln-online, 50 steps, seed 1101, two alternating flow_shift values (12.0 / 10.0), 4 requests per arm in one server process: all 8 MP4s are sha256-identical across arms, and repeated requests are sha256-identical to their first occurrence, i.e. both the rebuild and the pinned-host round-trip are bit-faithful. Unit tests cover LRU order, alternating-schedule residency, host-cap accounting and pinned-allocation degradation, recompute fallback, bit-exact swap-in, the fp32 projection, the LoRA/Diffusers/weight-update guards, and admission-time rejection; the full multimodal_gen unit suite passes (the one remaining failure reproduces on main).

Speed Tests and Profiling

Same A/B setup as above (sglang generate-equivalent requests through DiffGenerator, warmup excluded):

request host tier disabled host tier 8 GB
shift 12.0, first seen 94.83 s 94.68 s (full rebuild)
shift 10.0, first seen 94.76 s 94.76 s (full rebuild)
shift 12.0, repeated 94.77 s 88.42 s (33 plans from host cache, zero checkpoint reads)
shift 10.0, repeated 94.73 s 88.34 s

The 6.4 s saved per repeated request matches the nsys-measured rebuild cost (5.8-6.7 s). An 8-step run with a deliberately small slab (SGLANG_DIFFUSION_MINIMAX_H3_ADALN_GPU_PLANS=8) shows the same behavior for distilled schedules. Multi-rank (4x H200, ulysses=4, tp=1, same t2va schedule, 50 steps) reproduces the single-rank result: 31.95 / 31.88 s for the two first-seen schedules, 25.16 / 25.13 s when each repeats, every output bit-identical across the host-tier-on and host-tier-off arms and across repeats, no rank divergence or hang. The env-gated fp32 rebuild was measured against the default path on the same requests: 29.10 dB / 24.08 dB video PSNR (mean abs diff 3.42 / 6.09 on u8), i.e. it is a different sampling trajectory rather than a refinement of the same one -- it stays off by default and end-to-end validation remains required before using it.

Conclusion

Mixed-schedule serving no longer pays a 24.2 GiB checkpoint read for any schedule it has seen before, at the cost of one pinned-host slab per rank, with the default path bit-exact and one new CLI knob.

Checklist


CI States

Latest PR Test (Base): ✅ Run #33694613256
Latest PR Test (Extra): ❌ Run #33694612785
Latest PR Test (AMD ROCm 7.2): ❌ Run #33694613236

@github-actions github-actions Bot added documentation Improvements or additions to documentation diffusion SGLang Diffusion labels Aug 31, 2026

@BBuf BBuf left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change summary

This PR replaces MiniMax-H3's repeated 24.2-GiB AdaLN checkpoint scans with a tiered plan cache: fixed GPU plan slots with per-plan LRU, a pinned-host group cache, streamed native-checkpoint projection/all-gather, device-resident resolved slots for the denoise loop, and admission/configuration guards for online, sidecar, LoRA, and Diffusers-layout modes.

flowchart LR
    A["Request timestep plans"] --> B["prepare_adaln_plans"]:::changed
    B --> C{"GPU plan hit?"}:::changed
    C -->|yes| D["Fixed GPU slab / per-plan LRU"]:::changed
    C -->|no| E{"Pinned-host group hit?"}:::changed
    E -->|yes| D
    E -->|no| F["Stream checkpoint + TP projection"]:::changed
    F --> D
    D --> G["Denoise reads device plan slots"]:::changed
    H["Weight update"]:::changed --> I["Retarget / invalidate derived cache"]:::changed
    I --> B
    classDef changed stroke-dasharray: 5 5,stroke-width: 2px;
Loading

At admission time, the full timestep plan is resolved into GPU slots. Misses can be refilled from pinned host pages or rebuilt by streaming native AdaLN tensors and applying the TP-sharded projection. The denoise loop then uses only device-side slot indices. Weight updates are intended to invalidate this derived state, but the two update sources below do not preserve that invariant. Dashed nodes are changed by this PR.

Findings

  • [P1] A sidecar deployment keeps serving stale AdaLN conditioning after a weight update (python/sglang/multimodal_gen/runtime/models/dits/minimax_h3.py:1538-1544). The transformer update has already succeeded when this hook runs, but the sidecar branch only warns and returns without invalidating or rejecting service. Subsequent requests combine the new transformer weights with a sidecar generated from the old checkpoint. This needs to fail before applying the update, atomically switch to a matching sidecar, or invalidate the cache and make requests fail until a compatible sidecar is installed.
  • [P1] Tensor-RPC updates invalidate the cache and then rebuild it from the startup checkpoint (python/sglang/multimodal_gen/runtime/post_training/weights_updater.py:575). weights_path=None leaves cache.weight_files pointing at the original checkpoint; the next miss rereads old AdaLN weights. Worse, AdaLN modules are pruned in cache mode, so incoming adaln_proj tensors are logged as unknown and skipped while the API still returns success. Reject tensor updates in online-cache mode or retain a coherent updated AdaLN rebuild source/payload before publishing success.

The same source-version rule should be applied to disk updates whose target lacks native adaln_proj safetensors: warning and rebuilding from the original path is not fail-closed.

Review evidence

  • Reviewed all 14 changed files, including GPU-slot ownership, host-tier refcounts/LRU, copy-stream barriers, TP capacity agreement, plan-key construction, admission, LoRA, and both weight-update APIs.
  • Exhaustively swept 32,639 historical human-review threads for every touched path and broader cache/weight-update/LoRA/pinned-memory/concurrency terms. Exact MiniMax-H3 paths had no prior episodes; broader weight-update discussions consistently require a single coherent model version across an in-flight update.
  • Consulted the MiniMax model history card. It covers M2/M2.5/M2.7 autoregressive serving and does not cover H3 diffusion or AdaLN-derived caches, so this review followed the changed H3 source paths directly.
  • git diff --check and Python byte-compilation pass. The local checkout has no torch/pytest, so the new CPU-oriented tests could not be executed here. CI lint/check-change steps passed, but GPU/test lanes did not run because the PR lacks the run-ci label. The PR also currently conflicts with main.

Residual validation risk after the fixes: the author-listed multi-rank end-to-end test and fp32 trajectory comparison are still needed, plus explicit disk/sidecar/tensor update tests that prove the cache never serves a mixed weight version.

"built against the previous weights; requests keep using its "
"stale conditioning until the sidecar is rebuilt"
)
return

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] This warning does not fail closed: the transformer weight update has already succeeded, then this branch leaves the old sidecar active. Every later request mixes the new transformer weights with AdaLN conditioning generated from the previous checkpoint. Please reject the update before mutation, atomically install a matching sidecar, or invalidate the cache and make requests fail until a compatible sidecar is available. A regression test should update weights under sidecar mode and prove stale plans cannot be served.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed by moving the decision ahead of the mutation.

BaseDiT.validate_weight_update_source(weights_path=...) is a new hook that runs before a single weight is written — in update_weights_from_disk right after _validate_weight_files, and in update_weights_from_tensor before the first _load_weights_into_module. A rejection returns (False, msg) with the served model untouched, so the mixed-version window this warning left open no longer exists.

The H3 override rejects a sidecar deployment outright: the sidecar is generated offline from the startup checkpoint and the server cannot regenerate it, so the error names the two ways out (rebuild the sidecar and restart, or serve with --minimax-h3-adaln-online). refresh_weight_derived_caches keeps only the retarget, and re-asserts the same predicate so a broken call order raises instead of degrading silently.

Regression test: test_weights_updater_rejects_sidecar_update_before_writing_weights drives the real WeightsUpdater against a sidecar-mode DiT and asserts the update is refused, the module parameter still holds its pre-update value, and pipeline.model_path is unchanged — i.e. no request can observe new weights against the old sidecar.

if isinstance(module, BaseDiT):
# Same invariant as the disk path; there is no on-disk source
# to retarget the rebuild at, so only the caches drop.
module.refresh_weight_derived_caches(weights_path=None)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] For tensor-RPC updates, weights_path=None leaves cache.weight_files pointing at the startup checkpoint and only invalidates the plans, so the next request rebuilds AdaLN from the old weights. In cache mode the resident adaln_proj modules are also pruned, meaning incoming AdaLN tensors are logged as unknown/skipped while this API still returns success. Please reject tensor updates in online-cache mode or retain a coherent updated AdaLN payload/source before publishing success, and test that a post-update rebuild cannot read the original checkpoint.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tensor-RPC updates are now rejected in both cache modes, before any tensor is loaded.

validate_weight_update_source(weights_path=None) has no directory the rebuild could stream adaln_proj from, so online mode refuses the update and points at update_weights_from_disk; sidecar mode refuses it for the reason in the other thread. That also removes the second half of this finding — no adaln_proj tensor can arrive at a pruned module and be logged as unknown while the API reports success, because the request never gets that far.

The same source-version rule now covers the disk path you flagged in the review body: a target directory without native adaln_proj safetensors is rejected instead of warning and rebuilding from the original checkpoint. For a target that does carry them, the rebuild source is retargeted at the new directory, so the pruned resident modules are not a coherence gap on that path — the next miss reads the new checkpoint by construction.

Regression tests: test_weights_updater_rejects_tensor_update_in_online_cache_mode (real WeightsUpdater, asserts weights untouched), test_online_cache_rejects_update_source_without_native_adaln, and test_disk_update_retargets_rebuild_source_and_drops_plans, which asserts cache.weight_files points at the new directory and every previously built plan is gone.

Pure relocation out of the 2.6k-line minimax_h3.py ahead of the
tiered-cache work; no behavior change.
…h the block gather

prepare_adaln_plans returns each step's slab slot as a device tensor that
forward consumes directly, replacing the per-step device-side lookup and
its capture-breaking host sync. block_all() fetches all 50 blocks' params
in a single gather; the derived slab buffers leave state_dict.
…ng the slab

LRU over plan slots with in-flight protection: two alternating 50-step
schedules both stay resident instead of triggering a full slab reset and
a 24.2 GiB checkpoint re-read per request. Requests that cannot fit are
rejected at admission, before the encode stages spend GPU time.
--minimax-h3-adaln-host-cache-gb (default 8/rank, 0 disables) keeps built
plans in one pinned slab; a plan set evicted from the GPU slab swaps back
in over PCIe instead of re-reading the checkpoint (repeated-schedule
requests 94.8 -> 88.4 s on 1xH200, outputs bit-identical). Schedule-level
LRU with recompute fallback; capacity is MIN-reduced across ranks and
every state transition commits synchronously so ranks stay in lockstep.
Opt-in: compute the one-time projections in fp32 (TF32 pinned off)
before the bf16 store. Off by default -- more accurate params, but not
bit-comparable to resident adaln_proj weights, so it stays gated until
an e2e trajectory check clears it.
…ight updates in cache modes

adaln_proj LoRA deltas now raise instead of being silently dropped; the
Diffusers-layout checkpoint is rejected at startup instead of a
first-request KeyError; update_weights_from_disk invalidates every cache
tier and retargets the rebuild source at the new shards.
…ache

--minimax-h3-adaln-host-cache-gb is the only new flag; the GPU slot
count and the fp32 rebuild are SGLANG_DIFFUSION_MINIMAX_H3_ADALN_* env
escape hatches. Document the online mode and the host tier in cli.mdx
and the cookbook.
Correctness: touch the GPU slab LRU on pure cache hits (hot schedules
were evicted first), invalidate the cache on tensor-RPC weight updates
via a BaseDiT hook (not just disk updates, and without importing the
model zoo in the shared updater), check the native layout before
retargeting the rebuild source, roll back reserved slots when a host
swap-in fails, name the env var instead of a deleted CLI flag in the
overflow error, raise the coverage error instead of a shape mismatch on
over-width lookups, and downgrade the flag-misuse check to a warning
(config-file construction marks every key explicit).

Cleanup: drop the dead per-plan host timesteps copy (~50 stream syncs
per stored group), key each plan once per request instead of twice
(~98 D2H syncs), reuse the world-group MIN reduce and the shared host
reserve constants, and deduplicate the unpin bookkeeping.
@triple-mu
triple-mu force-pushed the feat/minimax-h3-adaln-tiered-cache branch from 0d0d492 to 808c96d Compare September 1, 2026 15:12
…follow

The cache holds values derived from adaln_proj, so an update it cannot
follow leaves new transformer weights paired with the old checkpoint's
conditioning. The previous hook ran after the weights were already
written and only warned, so both the sidecar deployment and the tensor
RPC path kept serving that mix.

BaseDiT.validate_weight_update_source now runs before any weight is
written and rejects a sidecar deployment, a tensor update, and a disk
target without native adaln_proj safetensors; the refresh hook keeps
only the retarget. BaseDiT.validate_lora_layers closes the same hole in
the LoRA IPC path, where adaln_proj layers were logged as unknown,
skipped, and reported as success.
@triple-mu
triple-mu force-pushed the feat/minimax-h3-adaln-tiered-cache branch from 808c96d to fdb9cb1 Compare September 1, 2026 15:27
@triple-mu

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Both P1s and the source-version rule from the review body are fixed, the branch is rebased on main (the conflict was two import blocks against #35703), and the two validation gaps you listed are now measured rather than pending.

What changed

The coherence decision moved ahead of the mutation. BaseDiT gained two pre-checks, both no-ops by default:

  • validate_weight_update_source(*, weights_path) — called in update_weights_from_disk right after _validate_weight_files, and in update_weights_from_tensor before the first _load_weights_into_module. A rejection returns (False, msg) with the served model untouched. The H3 override rejects a sidecar deployment (built offline, cannot be regenerated in the server), a tensor update (no directory to stream adaln_proj from), and a disk target without native adaln_proj safetensors. refresh_weight_derived_caches keeps only the retarget and re-asserts the same predicate, so a broken call order raises instead of degrading silently.
  • validate_lora_layers(layer_names) — called in _update_lora_from_tensor before convert_to_lora_layers() wraps anything. This closes the same hole at an entry point the review did not name: in cache mode the LoRA IPC path resolved adaln_proj layers to nothing, logged them as unknown, skipped them, and still returned success. The disk LoRA path already failed closed; both now share one guard.

Seven CPU tests cover each rejection plus the accepted disk retarget, and two of them drive the real WeightsUpdater and assert the module parameter still holds its pre-update value — a rejected update cannot have written anything.

Multi-rank e2e

4x H200, ulysses=4, tp=1, t2va, 50 steps, 512 short edge, 5 s, seed 1101, gpu-plans=64; four requests per arm in one process, alternating flow_shift 12/10.

request flow_shift host tier 8 GB host tier off sha256 (8 GB) sha256 (off) equal
0 12.0 31.95 s 32.01 s 9a2abc30ca30 9a2abc30ca30 yes
1 10.0 31.88 s 31.95 s 00cfefe24f2e 00cfefe24f2e yes
2 12.0 25.16 s 31.93 s 9a2abc30ca30 9a2abc30ca30 yes
3 10.0 25.13 s 31.87 s 00cfefe24f2e 00cfefe24f2e yes

Every output is bit-identical across arms and across repeats, and the host tier saves 6.8 s per repeated schedule at four ranks (single-rank was 6.4 s). The rank-0 AdaLN decisions were rebuilt 48 plan(s) → pass #2, rebuilt 48 plan(s) → pass #3, then 33 plan(s) from the host cache twice, with no hang and no rank divergence.

fp32 rebuild trajectory

SGLANG_DIFFUSION_MINIMAX_H3_ADALN_FP32=1 against the default path, same requests:

request flow_shift video PSNR video mean abs diff (u8) audio mean abs diff (i16)
0 12.0 29.10 dB 3.42 447
1 10.0 24.08 dB 6.09 267

Worth stating plainly: the fp32 projection changes bits by construction, and 50 sampling steps amplify that into a visibly different trajectory, not a "more accurate version of the same output". It stays off by default and the docs keep the experimental / validate-end-to-end wording, which these numbers now back with a measurement instead of an assertion.

Test status

On the rebased head: test_minimax_h3_adaln_cache.py + test_minimax_h3_admission.py + test_minimax_h3_dit_contract.py → 64 passed (this includes the block-FP8 tests #35703 added, so the rebase is clean). unit/ -k "weight or lora or updater" → 250 passed, 2 failed; both failures are test_lora_commit_as_base.py's 1e-5 tolerance asserts and reproduce on this commit's parent and on main.

One thing I could not cover end to end: an actual weight-update e2e needs a second full checkpoint, so the "never serves a mixed weight version" property is covered by the WeightsUpdater-level tests above rather than a live update.

The PR still needs the run-ci label for the GPU/test lanes to run.

@mickqian

mickqian commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

@github-actions github-actions Bot added the run-ci label Sep 2, 2026
# Conflicts:
#	python/sglang/multimodal_gen/test/unit/test_minimax_h3_admission.py
@mickqian

mickqian commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

Conflict: prepare_lora_adapter gained _reject_non_lora_delta_tensors on main
while this branch added the AdaLN cache-mode guard; both run, main's format
check first.
prepare_lora_adapter reads _adaln_precomputed to decide whether adaln_proj
deltas are servable, so the SimpleNamespace standing in for the model needs
that attribute; without it the guard raises AttributeError before reaching
the rejection the test asserts.
@triple-mu

Copy link
Copy Markdown
Contributor Author

CI triage on 826f9d3 — the unit-test failure is fixed, the rest is infrastructure.

multimodal-gen-unit-test — fixed, now green. The failure on the previous head was test_minimax_h3_dit_contract.py::test_model_lazy_resolver_keeps_transformer_scoped_backend, which asserts selected_attention_backend=CUBE_SPARSE_ATTN while the resolver passed None. It does not come from this PR: #34893 added that test together with MiniMaxH3Attention._selected_attention_backend, but the model-level resolver only reads _component_attention_backend_override, so the assertion could not hold until #37480 added the per-module fallback in _resolve_attention_backend_once. This branch had been merged with main just before #37480 landed. Merging current main fixes it — multimodal-gen-unit-test is green, and every multimodal-gen-test-1-gpu / -5090 / -b200 failure on the earlier run was a fast-fail cascade off it, which is also what starved diffusion-coverage-check of the 9 cases it reported missing.

That merge needed one follow-up. prepare_lora_adapter reads self._adaln_precomputed before the AdaLN LoRA guard, and #37480's new test_fasth3_lora_bundle_is_rejected_loudly drives it with a SimpleNamespace that lacks the attribute, so it raised AttributeError instead of the ValueError the test asserts. Fixed by giving that stub _adaln_precomputed=False, the same thing test_minimax_h3_dit_contract.py already does. Locally on the merged head the whole multimodal_gen/test/unit suite is 2498 passed / 3 failed, and all three failures (test_lora_commit_as_base.py x2, test_server_args.py::TestOffloadDefaults::test_auto_ltx_original_replaces_component_cpu_offload) reproduce on current main in the same container.

The remaining failures are Install dependencies, not the PR. Five jobs on the latest run die at

git clone --branch v0.5 --depth 1 https://github.com/EvolvingLMMs-Lab/lmms-eval.git
fatal: could not read Username for 'https://github.com': No such device or address
##[error]Process completed with exit code 128

The v0.5 tag exists and the repo is public, so this is GitHub throttling an anonymous clone rather than a missing ref. The other four failures are check-pr-test-health cascading off those. I do not have rerun rights here — could a maintainer re-run the failed jobs?

Separate from this PR, worth a look: scripts/ci/cuda/ci_install_dependency.sh:765 clones bare, while the AMD path at scripts/ci/amd/amd_ci_install_dependency.sh:197 already goes through git_clone_with_retry. Routing the CUDA clone through the same helper would make this class of flake self-healing.

The AMD lanes are still running; I have not seen their logs yet and will follow up if they fail for a reason of their own.

@mickqian

mickqian commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

@triple-mu

Copy link
Copy Markdown
Contributor Author

Following up on the AMD lanes, as promised. Both failures reproduce on main, so nothing here comes from this PR. Current state of the 13 red checks on 826f9d3:

check failing step cause
multimodal-gen-test-2-gpu-amd (0, 1) Run diffusion server tests (2-GPU) minimax_h3_ref2va_video_audio_2gpu_h100 raises MiniMax H3 full-loop denoise requires CUDA, MPS, or Ascend NPU — the platform guard from #33569; the case carries no ROCm exclusion, so the AMD lane always runs a configuration H3 does not support
multimodal-gen-test-1-gpu-amd (0) Run diffusion unit tests test_modelopt_fp8_layerwise_offload_load / test_transformer_quant: torch.float8_e4m3fnuz != torch.float8_e4m3fn, i.e. the ROCm fp8 variant against a CUDA-hardcoded dtype
multimodal-gen-component-accuracy, multimodal-gen-test-2-gpu (1, 2) Install dependencies the anonymous lmms-eval clone, still throttled
diffusion-coverage-check Verify coverage starved of the cases the jobs above never ran
multimodal-gen-test-1-5090 check-pr-test-health fast-fail cascade
pr-test-finish, pr-test-extra-finish, pr-test-amd-extra-finish Check all dependent job statuses aggregation of the above
call-gate / pr-gate (x2) Require run-ci-extra label (optional) no run-ci-extra label

Evidence for the AMD claim: multimodal-gen-test-2-gpu-amd (rocm700, ..., 0) on the 2026-09-01 scheduled main run fails on the same case with the same RuntimeError, and the last five pr-test-amd.yml runs on main are all red.

So the only thing standing between this PR and a green CUDA lane is the lmms-eval clone. It has now thrown on three separate runs, and I still cannot re-run jobs here — a maintainer re-run would help, and adding retry to scripts/ci/cuda/ci_install_dependency.sh:765 (the AMD path already uses git_clone_with_retry) would stop it recurring for everyone. Happy to send that as its own PR if it is wanted.

@triple-mu

Copy link
Copy Markdown
Contributor Author

Update: merged current main into the branch (head 2365c14), which brings in #37647 — that PR moved all three CI clones behind scripts/ci/utils/git_clone_with_retry.sh with authentication and retry, so the lmms-eval throttling that failed Install dependencies on the last three runs should stop recurring. No need for the CI-side change I offered earlier, and no manual re-run needed: the new head starts a fresh run with the fix in place.

The merge was conflict-free, and MiniMax/VSA/FastH3 unit tests are 161 passed on the merged head.

The AMD lane failures stand as described above — they reproduce on main and are not related to this PR.

@triple-mu

Copy link
Copy Markdown
Contributor Author

Full CI has now settled on 2365c14 — the CUDA lane is green end to end: pr-test-finish, lint, multimodal-gen-unit-test, diffusion-coverage-check, multimodal-gen-component-accuracy and every 1-GPU/2-GPU shard pass. #37647's clone retry did fix the Install dependencies flake that failed the previous three runs.

The 10 remaining reds are all outside this PR:

  • AMD (3 jobs) — unchanged from my earlier comment: the ROCm fp8 dtype assert (torch.float8_e4m3fnuz != torch.float8_e4m3fn) and minimax_h3_ref2va_video_audio_2gpu_h100 hitting the requires CUDA, MPS, or Ascend NPU platform guard. Both reproduce on main.
  • NPU (multimodal-gen-test-2-npu-a3 (0))minimax_h3_t2va_2npu fails one check with GT image not found, but the artifact is actually there: that exact pinned URL returns 200. _load_remote_gt_image breaks immediately on a 4xx and only retries on network errors, 403/429 and 5xx — the log shows two "retrying" warnings, so the runner could not reach raw.githubusercontent.com, and the message is reported as "not found" regardless of cause. A re-run of that job should clear it.
  • call-gate / pr-gate (x2) — no run-ci-extra label; the step is marked optional.
  • Four *-finish jobs — aggregation of the above.

So the only actionable item left on my side is none; a re-run of multimodal-gen-test-2-npu-a3 (0) would settle the NPU lane, and the AMD lane needs whatever fix main needs.

@BBuf

BBuf commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

@BBuf
BBuf merged commit bf71035 into sgl-project:main Sep 3, 2026
135 of 145 checks passed
@triple-mu
triple-mu deleted the feat/minimax-h3-adaln-tiered-cache branch September 3, 2026 14:13
StevenChenSE pushed a commit to StevenChenSE/sglang that referenced this pull request Sep 6, 2026
…er-plan LRU) (sgl-project#37266)

Co-authored-by: mickqian <mickqian@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

diffusion SGLang Diffusion documentation Improvements or additions to documentation run-ci

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants