Skip to content

Commit 6559bca

Browse files
lvyufenglvyufengclaude
authored
feat: validate AMP support on MUSA (#145)
Run the shared PrivateUse1 autocast and GradScaler contract on native MUSA builds, and document measured FP16/BF16 behavior on MTT S5000. Keep GradScaler unscale on the existing correctness-oriented CPU fallback because mudnn has no fused AMP foreach primitive. Co-authored-by: lvyufeng <lvyufeng@flagopen.baai.ac.cn> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 2e00b39 commit 6559bca

5 files changed

Lines changed: 87 additions & 18 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ Capability availability and validation status vary by platform. A feature existi
8181
| PPU | CUDA boxing against PPU's CUDA-13-compatible SDK | Eager, autograd | **Experimental** | [PPU](docs/vendors/ppu/installation.md) |
8282
| Hygon DCU | CUDA boxing over hipified DTK torch | Eager, autograd, FP16/BF16 AMP, profiler | **Beta** | [DCU](docs/vendors/dcu/installation.md) |
8383
| Enflame GCU | Native topsaten backend, CPU fallback for unrouted/int64 ops | Eager | **Experimental** | [GCU](docs/vendors/gcu/installation.md) |
84-
| Moore Threads MUSA | Native mudnn backend, CPU fallback for unrouted ops | Eager | **Experimental** | [MUSA](docs/vendors/musa/installation.md) |
84+
| Moore Threads MUSA | Native mudnn backend, CPU fallback for unrouted ops | Eager, FP16/BF16 AMP | **Experimental** | [MUSA](docs/vendors/musa/installation.md) |
8585
| D-Robotics BPU | No eager kernels; `torch.compile` graph path via hbdk4 | Graph compilation only | **Runtime only** | [BPU](docs/vendors/bpu/installation.md) |
8686
| TsingMicro | Runtime build selector exists | Setup not documented | **Runtime only** | — |
8787

‎docs/reference/compatibility.md‎

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
| PPU | `ACCELERATOR=cuda` + `PPU_SDK`/`PPU_HOME` detection | Same CUDA-boxing path as NVIDIA CUDA, against the PPU's CUDA-13-compatible SDK | Experimental (FP16/BF16 autocast and GradScaler measured on PPU hardware, not in CI) | Not validated | Experimental (NCCL fallback via vendor-adapted `libnccl.so.2`; not CI-covered) | Not validated on this vendor's tracer | Experimental (vendor-index Triton required) | Experimental |
2929
| Hygon DCU | `ACCELERATOR=dcu` | CUDA boxing over the hipified DTK torch build (HIP kernels under the CUDA dispatch key) | Beta (including FP16/BF16 autocast and GradScaler) | Experimental (FlagTree HCU validated on `gfx936`; not in CI) | Experimental (RCCL via DTK; all_reduce/DDP measured on 2 cards, not in CI) | Beta (parity suite runs in CI) | Beta (Python dispatch only) | Beta |
3030
| Enflame GCU | `ACCELERATOR=gcu` | Native `libtopsaten.so` operator backend, with CPU fallback for unrouted/int64 ops | Experimental | Not validated | Not validated | Not validated | Experimental (Python dispatch, requires vendor Triton) | Experimental |
31-
| Moore Threads MUSA | `ACCELERATOR=musa` | Native `mudnn` operator backend, with CPU fallback for unrouted ops | Experimental | Not validated | Not validated | Experimental (MUPTI device timeline measured on MTT S5000; CPU-Kineto linkage is environment-dependent) | Experimental (Python dispatch, requires vendor Triton) | Experimental |
31+
| Moore Threads MUSA | `ACCELERATOR=musa` | Native `mudnn` operator backend, with CPU fallback for unrouted ops | Experimental (including FP16/BF16 autocast and GradScaler measured on MTT S5000) | Not validated | Not validated | Experimental (MUPTI device timeline measured on MTT S5000; CPU-Kineto linkage is environment-dependent) | Experimental (Python dispatch, requires vendor Triton) | Experimental |
3232
| D-Robotics BPU | `ACCELERATOR=bpu` | No eager kernel sets are built; eager ops run on CPU | Runtime only (CPU fallback for eager) | Experimental (`torch.compile(backend="bpu")` graph path via hbdk4) | Not applicable | Not validated | Not applicable (no per-op kernel build) | Runtime only |
3333
| TsingMicro | `ACCELERATOR=tsingmicro` | Runtime/build selector present; no per-op kernel set documented | Runtime only | Not validated | Not validated | Not validated | Not applicable | Runtime only |
3434

@@ -155,11 +155,17 @@ with a documented CPU fallback for ops the vendor kernel table does not cover (s
155155
[`setup.py`](../../setup.py), lines 440-457, and
156156
`tests/integration/ops/test_musa_dispatch.py`, lines 15-24). No CUDA boxing kernels or FlagGems
157157
C++ kernels are compiled for this platform; FlagGems Python dispatch is optional and needs the
158-
vendor Triton backend. Distributed support remains unvalidated on hardware. The optional MUPTI
159-
tracer has been measured on the available MTT S5000 host and emits real positive-duration kernel,
160-
runtime, and memcpy activities with device, stream, name, and Chrome-trace metadata. CPU-to-device
161-
linkage depends on whether the installed PyTorch/Kineto build supplies the PrivateUse1 resolver;
162-
the CPU-only PyTorch 2.10 wheel used for this measurement does not justify a general parity claim.
158+
vendor Triton backend. The shared `AutocastPrivateUse1` policies and native mudnn routes were
159+
measured on an MTT S5000 with both FP16 and BF16. The 25-case AMP suite covers lower-precision
160+
matmul, linear, and convolution; float32 and promote policies; nested autocast state; finite scale
161+
growth; overflow backoff and optimizer-step skipping; and end-to-end GradScaler training. The
162+
GradScaler unscale operation currently follows the correctness-oriented CPU fallback and copies
163+
its mutated tensors and `found_inf` flag back to MUSA rather than using a native mudnn foreach
164+
kernel. Distributed support remains unvalidated on hardware. The optional MUPTI tracer has been
165+
measured on the available MTT S5000 host and emits real positive-duration kernel, runtime, and
166+
memcpy activities with device, stream, name, and Chrome-trace metadata. CPU-to-device linkage
167+
depends on whether the installed PyTorch/Kineto build supplies the PrivateUse1 resolver; the
168+
CPU-only PyTorch 2.10 wheel used for this measurement does not justify a general parity claim.
163169

164170
### D-Robotics BPU
165171

‎docs/reference/dtype-support.md‎

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,29 @@ is not an AMP target and is not accepted by its native matmul API.
2525
| Ascend | float16, bfloat16, float32, float64, integer, uint8, bool | Vendor coverage; unsupported ACLNN combinations use the CPU fallback | float16, bfloat16, float32 natively; float64 and unsupported types use the CPU fallback | float16, bfloat16 |
2626
| MetaX boxing | MACA libtorch CUDA-compatible coverage | MACA libtorch CUDA-compatible coverage | MACA libtorch CUDA-compatible coverage | float16, bfloat16 |
2727
| DCU | Vendor library coverage | Vendor library coverage | Vendor library coverage | Backend-specific |
28-
| MUSA | Vendor library coverage | Vendor library coverage | Vendor library coverage | Backend-specific |
28+
| MUSA | float16, bfloat16, float32, float64, integer, bool | mudnn coverage; unrouted operations use the CPU fallback | float16, bfloat16, and float32 measured for AMP paths; broader support is vendor-dependent | float16, bfloat16 |
2929

3030
The MetaX AMP entry is measured for the CUDA-boxing path on C550 with MACA
31-
3.8.0; it does not cover the legacy handwritten MetaX kernel mode. The DCU and
32-
MUSA entries intentionally do not claim AMP target parity without hardware
33-
measurements for the specific library release. Their native boxing or
34-
code-generated kernels determine the available operator/dtype combinations.
31+
3.8.0; it does not cover the legacy handwritten MetaX kernel mode. The DCU entry
32+
remains vendor-dependent. MUSA AMP coverage below is measured for the specific
33+
S5000 and mudnn release rather than inferred from its route configuration.
34+
35+
## MUSA Boundaries
36+
37+
MUSA AMP uses the shared `AutocastPrivateUse1` policy lists with the native
38+
mudnn operator routes. On the measured MTT S5000 and mudnn v3300 setup, both
39+
float16 and bfloat16 execute the lower-precision matmul, linear, and convolution
40+
policies. Logarithm, layer normalization, MSE loss, and the default softmax
41+
policy return float32; an explicit softmax dtype is preserved; mixed inputs use
42+
the promote policy.
43+
44+
`torch.amp.GradScaler("flagos")` uses the existing PrivateUse1 fallback for
45+
`_amp_foreach_non_finite_check_and_unscale_`. That fallback moves the list and
46+
scalar operands to CPU, runs the reference kernel, and copies the mutated values
47+
and `found_inf` flag back to MUSA. This is correctness-oriented rather than a
48+
claim of native mudnn AMP-foreach acceleration. Finite scale growth, overflow
49+
backoff, optimizer-step skipping, and FP16/BF16 autocast training were measured
50+
on the same S5000 host.
3551

3652
## Ascend Boundaries
3753

‎docs/vendors/musa/installation.md‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ pytest tests/integration/ops/test_musa_dispatch.py -v
9999

100100
This test file checks that ops route to the `musa` backend, exercises per-op environment overrides, and validates results against CPU references. It replaces the generic per-op tests in `tests/integration/ops/`, which assert `-> cuda` routing that MUSA builds cannot produce (no CUDA boxing kernels are compiled).
101101

102+
Run the autocast and GradScaler suite:
103+
104+
```bash
105+
TORCH_DEVICE_BACKEND_AUTOLOAD=0 ACCELERATOR=musa \
106+
LD_LIBRARY_PATH=/usr/local/musa/lib:$LD_LIBRARY_PATH \
107+
pytest tests/integration/test_amp.py -v
108+
```
109+
102110
Run common operator smoke tests:
103111

104112
```bash
@@ -135,6 +143,44 @@ Category-driven codegen via `scripts/codegen_mudnn.py` covers:
135143
- Handles both in a single device pass
136144
- Without this, `copy_`/`clone`/`contiguous` would reach the CUDA `DispatchStub` and fail
137145

146+
### AMP and GradScaler
147+
148+
MUSA uses the shared `AutocastPrivateUse1` policies with its native mudnn routes.
149+
Both `torch.float16` and `torch.bfloat16` are supported autocast targets:
150+
151+
```python
152+
import torch
153+
import torch.nn.functional as F
154+
import torch_fl # noqa: F401
155+
156+
model = torch.nn.Linear(8, 4, device="flagos")
157+
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
158+
scaler = torch.amp.GradScaler("flagos")
159+
inputs = torch.randn(2, 8, device="flagos")
160+
targets = torch.randn(2, 4, device="flagos")
161+
162+
with torch.autocast("flagos", dtype=torch.bfloat16):
163+
output = model(inputs)
164+
loss = F.mse_loss(output, targets)
165+
166+
scaler.scale(loss).backward()
167+
scaler.step(optimizer)
168+
scaler.update()
169+
```
170+
171+
The standard policy groups cast matmul, linear, and convolution to the selected
172+
lower-precision dtype. Logarithm, layer normalization, MSE loss, and the default
173+
softmax policy run in float32; operations in the promote group use the widest
174+
input dtype. Nested autocast state and explicit softmax dtypes follow PyTorch's
175+
PrivateUse1 behavior.
176+
177+
GradScaler's `_amp_foreach_non_finite_check_and_unscale_` currently reaches the
178+
existing CPU fallback because mudnn has no fused AMP-foreach primitive. The
179+
fallback copies tensor-list operands and scalar state to CPU, invokes PyTorch's
180+
reference kernel, and copies the mutated gradients and `found_inf` flag back to
181+
MUSA. This preserves finite-step growth, overflow backoff, and optimizer-step
182+
skipping, but it is not a native device-side performance path.
183+
138184
### Native RNG and CPU fallback
139185

140186
Native RNG uses a per-device Philox generator from `libmurand.so`. Each operation consumes one seed from the selected PyTorch `flagos` generator under its mutex, then configures a cached muRAND generator on the shared MUSA stream. This preserves `torch.manual_seed`, `torch.flagos.manual_seed`, `manual_seed_all`, `get_rng_state`/`set_rng_state`, explicit `generator=` isolation, and independent per-device sequences without maintaining a second Python-side RNG state. The optional FlagGems bridge reserves operation seeds through the same C++ API and starts each FlagGems Philox invocation at offset zero, so mixed native/FlagGems call order has one authoritative state.
@@ -183,6 +229,7 @@ MUSA has no CI runner (no `.github/configs/musa.yml` config exists), so all test
183229

184230
The native RNG and hybrid FlagGems implementation were measured on 2026-08-17 on an eight-device Moore Threads MTT S5000 host. Device 0 reported capability 3.1, 60 multiprocessors, and 85,813,358,592 bytes of memory. The environment used CPU PyTorch 2.10.0, the installed `/usr/local/musa` toolkit (`mudnn` v3300), FlagGems 5.0.2, and the vendor `flagtree-0.5.0+mthreads3.1` wheel (Triton 3.1.0, backend `mthreads`). Results:
185231

232+
- `pytest tests/integration/test_amp.py -v`: **25 passed** in 9.00 seconds. Both FP16 and BF16 passed lower-precision matmul/linear/convolution, float32 and promote policies, nested state, mutable non-finite unscale, finite scale growth, overflow backoff, optimizer-step skipping, and autocast/GradScaler training.
186233
- `pytest tests/integration/ops/test_rng_dispatch.py -m "main_ops" -v`: the unified RNG suite passed, including explicit generators, state round trips, `torch.manual_seed`, full-width int64 ranges, native dropout, shared native/FlagGems reservation ordering, and multi-device sequence isolation. MUSA-only generator and reservation cases are selected by the `musa` mark.
187234
- `pytest tests/integration/ops/test_musa_dispatch.py -v`: **89 passed** in 36.31 seconds.
188235
- `pytest tests/unit/test_vendor_routing.py tests/unit/test_musa_rng_bridge.py -v`: **24 passed** in 2.19 seconds.

‎tests/integration/test_amp.py‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,23 @@
1515
import os
1616

1717
import pytest
18-
import torch_fl
1918
import torch
2019
import torch.nn.functional as F
20+
import torch_fl
2121

2222

2323
DEVICE = "flagos:0"
2424
AMP_DTYPES = (torch.float16, torch.bfloat16)
2525

26-
# PPU uses the CUDA-compatible build path, so ACCELERATOR alone cannot
27-
# distinguish it from an NVIDIA build. MetaX has an explicit build selector.
28-
# Run this hardware contract only on those two validated vendor runtimes.
26+
# PPU shares the CUDA build selector, so its SDK marker distinguishes it from
27+
# NVIDIA. Native AMP backends have explicit selectors. Device availability is
28+
# enforced by integration conftest.
2929
BUILD_ACCELERATOR = torch_fl._build_accelerator()
3030
PPU_RUNTIME = bool(os.environ.get("PPU_SDK") or os.environ.get("PPU_HOME"))
31-
AMP_RUNTIME = BUILD_ACCELERATOR == "metax" or PPU_RUNTIME
31+
AMP_RUNTIME = BUILD_ACCELERATOR in {"ascend", "dcu", "metax", "musa"} or PPU_RUNTIME
3232
pytestmark = pytest.mark.skipif(
3333
not AMP_RUNTIME,
34-
reason="AMP tests require a MetaX build or PPU_SDK/PPU_HOME runtime",
34+
reason="AMP tests require an Ascend, DCU, MetaX, MUSA, or PPU runtime",
3535
)
3636

3737

0 commit comments

Comments
 (0)