Repository navigation
fix(rocm): make AMD device families explicit and enforce kernel support contracts - #3550
Conversation
HIP reuses torch's cuda namespace, so HAS_CUDA is true on ROCm and both
normalize_device() and auto_select_device() returned DEVICE.CUDA. Kernel
selection then treated CUDA-only kernels (TritonV2Linear, W4A-FP8/NVFP4,
...) as supported and dispatched to NVIDIA-only MMA paths.
Map "cuda", "cuda:N", integer ordinals, and torch.device("cuda:N") to
DEVICE.ROCM when IS_ROCM, and use normalize_device() in the quantize
paths so a raw device value cannot bypass the mapping. Explicit
DEVICE.CUDA remains a caller-declared NVIDIA family.
Add ROCm regression coverage asserting the normalized device is
DEVICE.ROCM and select_quant_linear(device=DEVICE.ROCM) never returns
TritonV2Linear. Make two CUDA-specific tests host-deterministic.
…ROCm family `DEVICE.ROCM` is a kernel support family, not a torch device: its value `"rocm"` is rejected by `torch.device()`. Storing it in `quantize_config.device` (via `auto_select_device`/`normalize_device`) broke the default ROCm quantize path with `ValueError: Unknown device for pool: DEVICE.ROCM` raised from `stage_inputs_capture.cache_inputs` -> `DEVICE_THREAD_POOL.read_lock`. Keep the stored value in HIP's `cuda` spelling (`torch_compatible_device`) and resolve the family at kernel selection: `normalize_device()` and `importer._device_family()` now map `DEVICE.CUDA` to `DEVICE.ROCM` on a ROCm host, so `auto_select_device()` can keep returning the torch-compatible default. This also fixes the pre-existing `device="rocm"` crash (same error). Verified on ROCm with HIP_VISIBLE_DEVICES=2,3: - GPTQModel.load + quantize (Qwen2.5-0.5B, GPTQ 4bit) passes for device=None / "cuda" / "rocm"; the previous head crashed for all three. - pre-quantized checkpoint load + generate passes (TorchLinear). - select_quant_linear(device=DEVICE.CUDA) -> TorchLinear (TritonV2Linear on main). - test_selection.py + kernel device/ROCm tests: 131 passed, 77 skipped.
…ries
Revert the ROCm-to-CUDA conversion introduced by the previous revision.
PyTorch already exposes ROCm through the `cuda` namespace, so storing
`DEVICE.CUDA` for an AMD host turns ROCm handling back into CUDA checks and
lets CUDA-only kernels pass the support-family gate.
Keep `DEVICE.ROCM` in `quantize_config.device` and kernel selection, and
resolve it to a concrete `torch.device` only where torch, the device thread
pool, or a module move requires one.
- Remove `torch_compatible_device()`; `auto_select_device()` and the loader
retain `DEVICE.ROCM` on a ROCm host.
- Add `as_torch_device()` and use it at module-move / p2p / structure /
prewarm / rotation / model-definition boundaries.
- `DeviceThreadPool` accepts `DEVICE` enums and maps them to the runtime
family, fixing `Unknown device for pool: DEVICE.ROCM`.
- Kernel `_device_family()` normalizes `torch.device("cuda:N")` and
`DEVICE.CUDA` to `DEVICE.ROCM` on HIP, so CUDA-only kernels are gated.
- Tests assert `DEVICE.ROCM` is preserved and resolved at the boundary.
|
Updated this PR in The previous revision added Changes in
Verification:
The PR description's |
Keep support-family conversions indexless at torch boundaries so CUDA and ROCm enum moves honor the current accelerator instead of forcing device zero. Normalize string selectors in direct kernel validation to prevent CUDA-only kernels from accepting HIP's cuda spelling. Correct selector smoke-test device discovery on ROCm and add mocked and live multi-GPU regressions.
|
Pushed review fixes in
Added regression coverage for these cases, including live two-GPU tensor/module moves, explicit-ordinal overrides, and preserved values/outputs. Three regression cases failed before the fixes and pass afterward. Validation:
Live tests used NVIDIA GPUs with Torch 2.15.0+cu132; ROCm dispatch was tested with simulated HIP flags. This revision has not been run end-to-end on AMD hardware. The PR description has also been updated to reflect the current implementation and validation. |
…rdware Declare bitsandbytes ROCm support, validate AllSpark targets and warm up on their device, reject native EXL3 on HIP, and expose specialized-loader device contracts. Add an exhaustive registry audit and live bitsandbytes numerical/storage regressions. Avoid NVIDIA capability probes for AMD and make NVIDIA-specific tests host-independent.
Distinguish static hardware support declarations from PyTorch runtime aliases. Document centralized normalization, ordinal preservation, current-device boundaries, mixed-vendor hosts, per-target architecture validation, and numerical acceptance requirements.
|
Completed the ROCm kernel-contract audit and pushed Scope: all 57 registered quant-linears, Fixes:
The remaining contracts stay unchanged: portable Torch kernels admit ROCm through Policy: AGENTS.md now requires the device-family skill. It distinguishes static NVIDIA/AMD hardware declarations from Torch's shared Validation:
Live numerical evidence is RDNA4-specific. The full inventory's family gates and mixed-architecture refusal cases are simulated; this audit does not claim execution validation on every AMD family. |
|
Resolved the overlap with main's EXL3 sign-buffer dtype fix and pushed merge commit Post-merge validation: 505 passed, 49 skipped on ROCm (contracts/selection/EXL3 gating/imports), 401 passed on CUDA (including upstream sign-buffer regressions), and 14 passed on ROCm for portable EXL3 FP16/BF16 forward/oracle and lazy materialization/shard-layout checks. Ruff and diff checks pass. The explicit-device-family agent policy and skill are included in this head. |
|
c4489283211 — Already fixed on current head |
|
c4489306623 — Confirmed fixed at HEAD e292951: |
Summary
PyTorch exposes AMD GPUs through its
cudanamespace on HIP builds. Treating that spelling as the NVIDIA hardware family allowed unsupported kernels through validation and hid ROCm support in other kernels.DEVICE.ROCMin GPTQModel family-valued configuration and kernel selection. Normalize runtime aliases centrally; resolve enums to Torch devices only at execution boundaries, preserving explicit ordinals and current-device behavior. Family-wide thread-pool locks cover every device.EXL3_TORCHalternative.AGENTS.mdand.agents/skills/gptqmodel-device-families/SKILL.md, covering self-declared kernel support, Torch runtime aliases, mixed-vendor hosts, ordinals, and per-target architecture validation.Validation
2.16.0.dev20261025+rocm10.1: audit/selection/gating/AllSpark/bitsandbytes run 615 passed, 54 skipped.2.15.0+cu132: audit/gating/bitsandbytes/EXL3 import/FP4 CPU run 577 passed, 42 skipped. Final selector/contract rerun after the explicit-AMD capability guard: 508 passed, 29 skipped.rtol=atol=2e-3. Maximum observed absolute error:6.14e-4; repeated forwards retain no additional weight storage. FP32 uses the vendor path.The full hardware declaration matrix is tested with simulated HIP; live numerical coverage here is on RDNA4, not every declared AMD architecture.