Skip to content

gfx1201 (RDNA4) rocBLAS/Tensile ISA1201 GEMM page fault — upstream report reference #113

Description

@ulises-c

Summary

During Gemma‑4‑31B QLoRA training on an AMD R9700 (gfx1201 / RDNA4, ROCm 7.2), a reproducible GPU page fault ("page not present") occurs inside a rocBLAS Tensile GEMM in the QLoRA backward pass. The fault survives full kernel serialization (so it is not an async race), reproduces on a verified‑clean GPU (so it is not a dirty‑KFD cascade), and the faulting address lies in unmapped space ~1 GB from both operands of the faulting GEMM (so it is not an undersized operand descriptor or an OOM).

This issue is the internal system‑of‑record consolidating the diagnosis from PR #101. Its purpose is to seed an upstream bug report against the ISA1201 GEMM kernels, filed at ROCm/rocm-libraries — component rocBLAS (projects/rocblas/) / Tensile (shared/tensile/). (The standalone ROCm/rocBLAS and ROCm/Tensile repos are retired; rocm-libraries is the source of truth.) The ready‑to‑paste upstream draft is in the comments. See the canonical ablation tracker: docs/GFX1201_FAULT_ABLATION_LOG.md.

Related: #100 (gfx1201 training investigation), #101 (PR where this was diagnosed), #109 (gfx1201 field report).

Environment

GPU AMD Radeon AI PRO R9700, gfx1201 / RDNA4, 32 GB
ROCm 7.2
PyTorch 2.11.0 (ROCm build)
bitsandbytes 0.49.2
Backend rocBLAS Tensile path (TORCH_USE_HIPBLASLT=0)
Workload Gemma‑4‑31B, NF4 QLoRA, SDPA, grad‑ckpt (use_reentrant=False), seq 1280, bs 1×16, seed 42

The fault

Memory access fault by GPU node-1 on address 0x7f6459a00000.
Reason: Page not present or supervisor privilege.

The fault is a 2 MB‑aligned host‑VA address arising during the gradient‑checkpoint forward recompute inside the backward pass. The faulting op is a rocBLAS Tensile GEMM that consumes the NF4‑dequantized weight — not the bitsandbytes dequant kernel (kDequantizeBlockwise<float> / <hip_bfloat16> succeed in every cycle).

Faulting kernel name — confirmed identical in both directions

On a verified‑clean GPU at AMD_LOG_LEVEL=3, the faulting kernel — captured in both the backward pass (runs #4/#5) and the grad‑ckpt forward recompute (run #9) — is the same gfx1201‑native Tensile GEMM, macro‑tile 64×64×64, ISA1201. Full ShaderName (run #9):

Cijk_Ailk_Bjlk_BBS_BH_Bias_HA_S_SAV_UserArgs_MT64x64x64_MI16x16x1_SN_LDSB0_AFC1_AFEM1_AFEM1_ASEM1_CLR1_CADS0_DTLA0_DTLB0_DTVA0_DTVB1_EPS0_FDSI0_GRPM1_GRVWA8_GRVWB8_GSUAMB_GLS0_ISA1201_IU1_K1_LDSTI0_LBSPPA1024_LBSPPB0_LBSPPM0_LPA32_LPB0_LPM0_LRVW8_LWPMn1_MIAV1_MIWT2_2_MO40_NTn1_NTA0_NTB0_NTC0_NTD0_NTM0_NEPBS0_NLCA1_NLCB2_ONLL0_PGR2_PLR1_PKA0_SIA3_SS0_SPO0_SRVW0_SSO0_SVW8_SK0_SKFTR0_SKXCCM0_TLDS0_ULSGRO0_USL1_UIOFGRO0_USFGROn1_VSn1_VWA2_VWB1_WSGRA0_WSGRB0_WS32_WG32_4_1

The same tile succeeds elsewhere in the same pass, so the fault is specific to a particular call's operands/addresses, not a categorically broken kernel. Discriminating flags that point at the B‑operand path: DTVB1 (B non‑default dtype/layout), LBSPPB0 (no B LDS prefetch), NLCB2 (B double‑unrolled), VWA2_VWB1 — consistent with the column‑major stride=(1,21504) B operand computing the wild address.

Fault‑address vs. operand descriptors (forward recompute — probe‑3)

probe‑3 (commit dad8f4a) instrumented both forward‑GEMM operands — the activation A (via MatMul4Bit.forward) and the dequantized weight B (via dequantize_4bit). The pair immediately preceding the fault:

[gemm_forward_input] shape=(1, 608, 21504) ptr=0x7f655ece8000 end=0x7f65605d8000   ← faulting GEMM A (contiguous, row-major)
[dequant_probe]      shape=(21504, 5376)   ptr=0x7f63f01a0000 end=0x7f63fde20000   ← faulting GEMM B (column-major, stride=(1,21504))
← FAULT 0x7f6459a00000
Operand ptr end fault inside?
A (1,608,21504) contig 0x7f655ece8000 0x7f65605d8000 No — fault ~1.0 GB below ptr
B (21504,5376) stride=(1,21504) 0x7f63f01a0000 0x7f63fde20000 No — fault ~1.2 GB above end

A full‑log scan finds 0 operands that bracket the fault address. Both operands of the faulting GEMM are present, valid, and contiguous; the fault sits in an unmapped gap ~1 GB from either cluster, not adjacent to any buffer boundary. The column‑major (stride=(1,N)) B operand is the prime suspect for a Tensile stride‑computation bug producing the wild address.

Why it is a strong upstream report

Property Evidence
Reproducible Faults across multiple runs / resume points (runs 4–7 in the ablation log).
Serialized — not a race Persists under AMD_SERIALIZE_KERNEL=3 HIP_LAUNCH_BLOCKING=1 (run #3). Serialization kills races, not this fault.
Both directions, same tile Backward fault (probe‑1) and forward‑recompute fault (probe‑3) resolve to the identical MT64x64x64 … ISA1201 ShaderName (run #9).
Not bitsandbytes NF4 dequant kernels succeed every cycle; the fault is in the GEMM consuming the dequant output (runs #5–7).
Not an undersized descriptor Fault is ~1 GB from any operand boundary, not adjacent to end (probe‑1, probe‑3).
Not a dirty‑KFD cascade Reproduces on a make gpu-preflight‑verified‑clean GPU (run #5).
Not OOM VRAM at fault is within headroom (alloc ~21 GB / reserved ~28 GB of 32 GB).

What would go in the upstream (rocm-libraries) report

  • Arch: gfx1201 (RDNA4 / Navi 48), ROCm 7.2, torch 2.11.0+rocm7.2.
  • Faulting kernel (forward recompute and backward — confirmed identical): full ShaderName above (…_MT64x64x64_…_ISA1201_…).
  • Operand descriptors at fault (forward GEMM): A (1,608,21504) row‑major contiguous; B (21504,5376) column‑major stride=(1,21504); bf16.
  • Fault address 0x7f6459a00000 lies outside both operand ranges (≥1 GB gap).
  • Reproducible and serialized; gfx1201 only.

Resolved since first filing

  • Forward tile name — CONFIRMED (run docs: rename resources/ to references/, add HuggingFace notes #9, AMD_LOG_LEVEL=3). The forward‑recompute faulting GEMM resolves to the same ShaderName as the backward kernel (see above). The earlier concern that they might be different tiles (the forward problem size (1,608,21504)@(21504,5376) differs) is settled by evidence: both dispatch the identical MT64x64x64 … ISA1201 tile. The upstream report can name the kernel directly for both directions.

Open / unconfirmed

  • Output buffer not instrumented. A page‑not‑present is formally consistent with an OOB write to the output rather than a wild read. Deemed implausible — the output (1,608,5376) bf16 is ~6 MB and the fault is ~1 GB from any logged buffer — but it was not ruled out by instrumentation. This is the sole residual ambiguity in the wild‑read characterization.

Mitigations under evaluation (PR #101)

Tracked in docs/GFX1201_FAULT_ABLATION_LOG.md, scored on two axes (does it eliminate the fault / does it improve steps‑per‑resume):

Both routing/placement arms are now exhausted. Remaining paths are the brute‑force checkpoint crawl (viability unmeasured) or relocating the SFT run to NVIDIA (see docs/SFT_NVIDIA_MIGRATION.md); the upstream fix is the only thing that unblocks gfx1201 itself.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdocumentationImprovements or additions to documentationexperiment

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions