Skip to content

[diffusion] post_training: run weight update under torch.inference_mode()#31263

Open
kangwangamd wants to merge 6 commits into
sgl-project:mainfrom
kangwangamd:diffusion/weight-update-inference-mode
Open

[diffusion] post_training: run weight update under torch.inference_mode()#31263
kangwangamd wants to merge 6 commits into
sgl-project:mainfrom
kangwangamd:diffusion/weight-update-inference-mode

Conversation

@kangwangamd

@kangwangamd kangwangamd commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Motivation

multimodal-gen-test-1-gpu shard running test_update_weights_from_disk.py fails with a server-side error and the /update_weights_from_disk API returns an HTTP error instead of 200:

Inplace update to inference tensor outside InferenceMode is not allowed.
You can make a clone to get a normal tensor before doing inplace update.

_apply_weights then rolls back (Weight update failed for module 'transformer': Inplace update to inference tensor ...).

Root cause

The diffusion pipeline builds/loads model weights while running under torch.inference_mode(), so the model parameters and buffers are inference tensors. PyTorch forbids in-place mutation of an inference tensor outside an inference-mode context.

The weight-update path performs in-place copies. Some are shielded by .data (which detaches from the inference guard) and some are not:

Site Code Safe?
weights_updater.py load_weights_into_model param.data.copy_(...) safe (.data)
weights_updater.py load_weights_into_model dtensor_param._local_tensor.copy_(...) unsafe
layerwise_offload.py cpu_tensor.copy_(...), cpu_buffer[...].copy_(...) unsafe

On torch builds with strict inference-tensor enforcement, the unsafe sites raise. This is not device-specific (it reproduces identically on CPU, no accelerator involved) and not a code regression — it is torch-version-sensitive.

Note that layerwise_offload.py already wraps its own restore-path copy in torch.inference_mode(False) + torch.no_grad(), so this pattern is already established in this module.

Not ROCm-specific — verified against the NVIDIA lane

test_update_weights_from_disk.py is part of the shared run_suite.py --suite 1-gpu, which runs on both the NVIDIA lane (pr-test.yml, 1-gpu-h100) and the AMD lane (pr-test-amd.yml). It is not an AMD-only test.

On a recent diffusion PR that exercised the full H100 suite (#31029, 2026-07-14), the NVIDIA multimodal-gen-test-1-gpu job — including the shard that runs test_update_weights_from_disk — was green (11 passed), with no inference-tensor error. Same sglang code, same day.

The difference is purely the torch build each environment ships:

Lane / image torch test_update_weights_from_disk
NVIDIA 1-gpu-h100 2.11.0 ✅ pass
AMD older image 2.9.1 ✅ pass
AMD current CI image 2.9.0a0+git7bcbafe (alpha) ❌ fail

The failing torch (2.9.0a0 alpha) sits between two versions that both pass, so this is not a simple "newer torch is stricter" case — that specific alpha build enforces the inference-tensor rule where the others don't. NVIDIA isn't passing because of a fix to copy over; it just ships a torch that happens not to trip the latent bug. This change makes the code correct on all torch builds (including that NVIDIA one), which is why it belongs in the shared code path rather than in an image/torch pin.

Modifications

Wrap the body of _load_weights_into_module() (the single choke point that both the offload and non-offload branches flow through) in torch.inference_mode(), so every in-place copy site — params, DTensor _local_tensor, and the offload CPU buffers — runs inside an inference-mode context. No CUDA-path change; the wrap simply re-enters the same context the tensors were created in.

Test

  • The exact error reproduces at the PyTorch level with a one-liner (an in-place .copy_() on a tensor created under torch.inference_mode()) and goes away when the copy is wrapped in torch.inference_mode(); verified the updated bytes are correct (torch.allclose).
  • Verified the failure is environment/torch-version specific: test_update_weights_with_offload_enabled[FLUX.2-klein-base-4B] passes on torch 2.9.1 and 2.11.0 and fails on 2.9.0a0, same sglang commit. NVIDIA h100 (torch 2.11.0) is green for this suite on [Diffusion] post_training: Add LoRA IPC weight sync via lora_merge mode #31029.
  • Please run multimodal-gen-test-1-gpu (test_update_weights_from_disk.py) on CI to confirm the update-weights suite goes green with this change.

cc @mickqian @HaiShaw @BBuf @niehen6174


CI States

Latest PR Test (Base): ✅ Run #29537287202
Latest PR Test (Extra): ❌ Run #29537286809

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@github-actions github-actions Bot added amd diffusion SGLang Diffusion labels Jul 15, 2026
…de()

Model params/buffers are created under torch.inference_mode() (they are
'inference tensors'); the in-place copies in the weight-update path
(param.data.copy_, DTensor _local_tensor.copy_, and the layerwise-offload
CPU-buffer copies) must therefore run inside an inference-mode context.
On torch builds with strict inference-tensor enforcement this otherwise
raises 'Inplace update to inference tensor outside InferenceMode is not
allowed' and makes /update_weights_from_disk return an HTTP error,
failing test_update_weights_from_disk.py. Wrapping _load_weights_into_module
in torch.inference_mode() (matching layerwise_offload's own restore path)
fixes it with no CUDA-path change.
@kangwangamd
kangwangamd force-pushed the diffusion/weight-update-inference-mode branch from 21483ad to cac5a71 Compare July 15, 2026 03:09
@mickqian

Copy link
Copy Markdown
Collaborator

/tag-and-rerun-ci

@HaiShaw

HaiShaw commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

@amd-bot ci-status

@amd-bot

amd-bot commented Jul 16, 2026

Copy link
Copy Markdown

@HaiShaw

CI Status for PR #31263

Merge verdict: ⚠️ Do not merge on the strength of this CI run. No executed failure is caused by this PR — the AMD reds are an unrelated sgl-kernel/mori build break and the NPU red is an unrelated generation test — but the exact test this PR fixes (test_update_weights_from_disk.py) did not run on any lane, so CI has not verified the fix at all. The green NVIDIA multimodal-gen-test-1-gpu shards prove nothing about this change.

Caution

This PR's changed code is not exercised by any PR-CI test. weights_updater.py::_load_weights_into_module is only reached by test/single_test_file/test_update_weights_from_disk.py. On this run: (a) the NVIDIA/AMD 1-gpu suite scheduled 0 standalone filescompute-diffusion-partitions logged Standalone files: 0 and plan-1gpu has empty standalone_files for all 4 partitions; (b) AMD never reached tests (build broke); (c) NPU hard-disables this test (_UPDATE_WEIGHTS_FROM_DISK_TEST_FILE = None in testcase_configs_npu.py:200). Before merge, run the target test explicitly on a GPU, e.g. python3 python/sglang/multimodal_gen/test/run_suite.py --suite 1-gpu with the standalone file forced in (the partition-plan path currently drops it), or run pytest python/sglang/multimodal_gen/test/single_test_file/test_update_weights_from_disk.py.

Changed files: python/sglang/multimodal_gen/runtime/post_training/weights_updater.py (+31/−16)

Executed CI failure attribution: AMD: 8 failures (0 related) · NPU: 1 failure (0 related) · Others: 0 independent (2 *-finish + pr-gate are fast-fail cascades). No jobs pending.

AMD Executed Failures

All 8 AMD multimodal-gen jobs failed identically at the sgl-kernel build step (ninja: build stoppedcmake --build exit 1), before any test ran. Root cause is one compile error in the mori dependency; collapsed into one row.

Job Test File Test Function Error Related? Why
multimodal-gen-test-1-gpu-amd (0) + shards 1-3, 2-gpu-amd (0-2), unit-test-amd N/A (build) N/A mori/src/cco/cco_init.cpp:95: error: use of undeclared identifier 'hipMemAllocationTypeUncached'ninja: build stopped → exit 1 🟢 Toolchain/infra: mori doesn't compile against the ROCm HIP headers in image rocm/sgl-dev:v0.5.15.post1-rocm700-mi30x-20260715. PR is a Python-only diff; cannot affect a HIP C++ build. Tests never ran.

Other Executed Failures

Job Test File Test Function Error Related? Why
multimodal-gen-test-1-npu-a3 sglang/multimodal_gen/test/server/ascend/test_server_1_npu.py TestDiffusionServerOneNpu::test_diffusion_generation[glm_image_t2i_1npu] Failed: ... 'glm_image_t2i_1npu' failed 1 check(s): Validation failed for 'Stage DecodingStage' 🟢 Plain diffusion generation/decode test; does not touch the post-training weight-update path this PR modifies. NPU also disables the target test entirely. Likely pre-existing NPU decode-validation issue.

(Cascade-only jobs, not counted: pr-test-amd-finish, pr-test-npu-finish, pr-test-extra-finish, pr-test-amd-extra-finish, pr-gate.)

Details / what to do before merge

  • Verify the fix (highest priority). The one behavior this PR changes is untested by CI. Run pytest python/sglang/multimodal_gen/test/single_test_file/test_update_weights_from_disk.py on an H100 (or force it into the 1-gpu suite) and confirm /update_weights_from_disk returns 200 with the torch.inference_mode() wrapper. The diff itself looks correct and self-consistent with the existing layerwise_offload.py restore-path pattern, but that is a code read, not a test result.
  • Investigate the standalone-scheduling gap separately. compute-diffusion-partitions returns Standalone files: 0 for all suites (1-gpu, 2-gpu, b200) even though gpu_cases.py::STANDALONE_FILES lists files — so test_update_weights_from_disk.py, test_disagg_server.py, etc. appear to be silently dropped from PR CI. This is pre-existing (not caused by this PR) and affects far more than this change; worth a separate issue/triage against scripts/ci/utils/diffusion/diffusion_case_parser.py (collect_diffusion_suites / _extract_file_dict).
  • AMD build break (mori / hipMemAllocationTypeUncached): affects all AMD multimodal-gen jobs and is independent of this PR. In-flight fix: ❌ none found (searched open PRs for hipMemAllocationTypeUncached). Triage: check whether mori needs a bump or the ROCm dev image needs updating; the API was likely renamed/removed in the HIP headers of the current image. Ask the author to confirm AMD CI once the build is fixed, since it currently provides zero signal.
  • NPU generation failure: verify against a recent main NPU run to confirm it is pre-existing before treating it as a blocker for this PR.

Generated by amd-bot using Claude Code CLI

@bingxche

bingxche commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

The errors are in install deps, which is fixed by #31406 , should update branch and wait for new round of CI.image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants