The previous commit (93730cfd) replaced the blanket module.to() in
_process_weights_after_loading with an unconditional per-parameter move.
That broke the FSDP/HSDP path: after apply_hsdp_to_model the params are
FSDP-sharded DTensors whose storage cannot be cross-device reassigned via
`param.data = param.data.to(cpu)`, raising at load time:
RuntimeError: Attempted to set the storage of a tensor on device
"cuda:0" to a storage on different device "cpu". This is no longer
allowed; the devices must match.
Regressed nightly test_zimage[layerwise_hsdp] (Diffusion X2I Function
Test with L4), which passed pre-fix. The FP8 online-quant variants it was
meant to fix (qwen/bagel fp8, parallel_*_fp8_*) all passed.
Meta-device params only ever arise from online quant (uses_meta_device),
so gate the meta-safe per-parameter move to that case and keep the
original FSDP/HSDP-aware whole-module module.to() for everything else.
Online quant initializes on the accelerator, so its params are normally
already on the target device (the per-param loop is a no-op move) — the
only behavioral change vs. the original is skipping meta stragglers.
Co-Authored-By: Claude <noreply@anthropic.com>