Repository navigation
Conversation
TorchFSDPPlugin.configure() passed torch.cuda.current_device() as the FSDP device_id, so on a non-CUDA accelerator booster.boost() raised "AssertionError: Torch not compiled with CUDA enabled" before FSDP was even built. Use get_accelerator().get_current_device() instead, which is what LowLevelZeroPlugin already does. This was the only torch.cuda call under colossalai/booster/plugin. Add a pre-commit hook, no-hardcoded-device, that fails when a guarded directory references torch.cuda, .cuda() or a hardcoded nccl backend, so the same mistake does not come back. Only colossalai/booster/plugin is guarded: the rest of the tree still has around 130 such references outside colossalai/legacy and colossalai/accelerator, and directories can be added to GUARDED as they are cleaned up. A line that is genuinely device-specific can opt out with '# allow-hardcoded-device: <reason>'. Checked on an Ascend 910B2: the hook reports the call on main and passes with this change, and TorchFSDPPlugin now gets past device selection.
JazyJiang
marked this pull request as ready for review
October 26, 2026 10:37
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.
Fixes #6480
Related to #6455, which replaces hardcoded device selection with the accelerator API in
colossalai/fxandcolossalai/inference. No file overlap with this PR.1. Background and problem
Current behaviour.
TorchFSDPPlugin.configure()passestorch.cuda.current_device()as the FSDPdevice_id.Problem. On any accelerator other than CUDA,
booster.boost()raisesAssertionError: Torch not compiled with CUDA enabledbefore FSDP is built, so the plugin cannot be used at all. This is the onlytorch.cudacall left undercolossalai/booster/plugin;LowLevelZeroPluginalready goes throughcolossalai.accelerator.Reproduce. Construct any model, wrap it with
TorchFSDPPluginand callbooster.boost()on a non-CUDA build. Full snippet in the linked issue. Reproduced on an Ascend 910B2.Expected behaviour. The device comes from the accelerator the framework has already detected.
Why now. The failure is invisible on CUDA, so it survives review and CI. The NPU port hit it on the first run of the plugin.
2. What changed
colossalai/booster/plugin/torch_fsdp_plugin.py: useget_accelerator().get_current_device()for the FSDPdevice_id, and importget_accelerator..github/scripts/ci/check_no_hardcoded_device.py(new): fails when a guarded directory referencestorch.cuda,.cuda()or a hardcodedncclbackend. Reports file, line, the offending source and the suggested replacement..pre-commit-config.yaml: register it as theno-hardcoded-devicehook, so it runs in the existing Layer 1pre-commitjob. No GPU and no new workflow.Not included in this PR:
colossalai/legacyandcolossalai/acceleratorthere are still ~130; onlycolossalai/booster/pluginis added toGUARDED. Locking everything now would turnmainred. Directories go in one at a time as they are cleaned.3. User and compatibility impact
CudaAccelerator.get_current_device()returnstorch.device(f"cuda:{torch.cuda.current_device()}"), i.e. the same device, as atorch.devicerather than anint. FSDP'sdevice_idaccepts both.New contributor-facing behaviour:
pre-commitnow fails if someone adds a hardcoded device undercolossalai/booster/plugin. The message names the file, line and replacement, and# allow-hardcoded-device: <reason>is the opt-out.4. Test environment
Verified on Ascend NPU only so far. The template's NVIDIA fields do not apply; the Ascend equivalents are given instead.
NVIDIA Driver / torch.version.cuda / nvcc: not applicable on this host.
5. Test commands and results
5.1 The hook
main: exit code 1, reportscolossalai/booster/plugin/torch_fsdp_plugin.py:540: torch.cuda.*no hardcoded device found in 1 guarded directoryNo GPU/NPU needed; runs on any machine.
5.2 Repository plugin tests on NPU
tests/test_booster/test_plugin/test_torch_fsdp_plugin.pypasses on an Ascend 910B2 with this change:Reverting only the one line in this PR makes that same test fail at
torch_fsdp_plugin.py, atdevice_id=torch.cuda.current_device(). That is the evidence for this change.Three things outside this PR were needed to get the repository's tests running on that machine at all, and are not proposed here: installing
torchvision/torchaudiofrom the CPU wheel index (the aarch64 wheels on PyPI linklibcudart.so.13), replacing seven hardcoded.to("cuda")/torch.cuda.empty_cache()calls in the four plugin test files, and dropping a@torch.jit.scriptdecorator in the ChatGLM modeling code that fails the TorchScript fuser on a non-CUDA device. The other three plugin tests also pass once those are in place (TorchDDP, LowLevelZero, Gemini).5.3 Standalone plugin smoke on NPU
A small script building a tiny Llama (2 layers, hidden 128) and running fwd/bwd/step twice per plugin, one plugin per process:
torch.cuda.current_device()1 and 2 NPUs, bf16. A separate check confirmed 2-card DDP gradients match a single process on the same global batch (relative 5.2e-7 over 590k elements), so the collective path is exercised.
5.4 GPU regression
Run on CUDA through the repository's layered CI (Layer 2) on
gpu-h20-5, inside the qualified dependency imagesha256:ae8ff34bf340a692803edca6e0f38a576fc1a2b206c01b4ef6f7c2a40dfd8c10, torch 2.13.0+cu130 / CUDA 13.0, on NVIDIA H20 (sm 9.0):02-single-gpu-core, 1 GPU)05-booster-lora-2gpu, 2 GPUs)test_dp_plugin_base.py,test_torch_ddp_plugin.py,test_torch_fsdp_plugin.py,test_low_level_zero_plugin.py,test_lora.pyBatch 5 is the batch that covers this change:
test_torch_fsdp_plugin.py::test_torch_fsdp_pluginpassed in 118.40s on 2 GPUs.Run: https://github.com/hpcaitech/ColossalAI/actions/runs/40308859635
That is attempt 3. The two earlier attempts executed no tests at all: they stopped at the runner's idle-GPU check with
Need N idle GPU(s), found 0, which reports host capacity rather than anything about the code.What CI tested is GitHub's merge commit
7e9551dec40fa57003be73de761950fc736aad9c, that is this PR's head3fa26fe5merged into basecb3b2234(the base recorded in section 4).mainhas moved on since, and this has not been re-run against the newer base.Still unverified on CUDA: the FSDP + AdamW path described in section 6.1, since batch 5's FSDP test constructs
SGD; gradient checkpointing, lazy init and checkpoint save/load, which live in other batches; and fp16.6. Known issues
6.1 TorchFSDP + AdamW is broken on torch 2.13, on every device
Symptom:
configure()rebuilds the optimizer withoptimizer.__init__(fsdp_model.parameters(), **optimizer.defaults). Under torch 2.13AdamW.defaultscarriesdecoupled_weight_decay, whichAdamW.__init__does not accept, so this raisesTypeError.Scope: specific to optimizers whose
defaultsdo not match their__init__signature.test_torch_fsdp_plugin.pyusesSGDand is unaffected, which is why it passes above.Introduced by this PR: no, and not accelerator-specific.
Also affects CUDA: yes. In
wangzhijian/colossalai-ci:torch2.13-cu130-tf5.17.0-exp-20261019:Handling: out of scope here, to keep this PR to one change.
Issue: to be filed
Owner / timing: to be assigned
6.2 The repository's tests assume a CUDA environment
Getting them to run on a non-CUDA accelerator needed the three changes listed in 5.2. Two of those are device assumptions in the repository itself: seven hardcoded CUDA calls in the four plugin test files, and a
@torch.jit.scriptdecorator whose fuser rejects the device.tests/still contains roughly 900 hardcoded CUDA references across 206 files.colossalai/booster/pluginonly;tests/is a much larger cleanup that deserves its own discussion rather than riding along.7. Risk and rollback
Risk. Low. One line, and the replacement resolves to the same CUDA device. The hook could annoy contributors if a legitimate device-specific line lands in a guarded directory; the
# allow-hardcoded-device:opt-out covers that.The hook runs on whole directories rather than changed files, so an unrelated PR that adds a hardcoded device under
colossalai/booster/pluginwill failpre-commitrather than the author's own files. That is the intent, but it does mean the failure can appear in a PR that did not expect it.Rollback. Revert the commit. The two parts are independent: dropping the hook (the
.pre-commit-config.yamlentry plus the script) leaves the one-line fix in place, and vice versa.8. Documentation and release impact
The hook's own usage and the opt-out marker are documented in the script docstring.