Skip to content

Commit 003ed0c

Browse files
kmbandyclaude
andcommitted
fix(mi300x): driverless Triton AOT + HIP exe link for the gfx942 image
Rebuilding the MI300X image surfaced two breakages vs the current tree: 1. Triton 3.7.0's tools/compile.py touches driver.active in two spots that need a live GPU despite an explicit --target, so the AITER AOT step died in the no-GPU rootless podman build ("0 active drivers"). Add patch_triton_driverless_aot.py (drop create_binder + use triton.compiler .ASTSource directly; import ty_to_cpp from the amd backend module) and a build-time gate that AOT-compiles for gfx942 with NO GPU and fails the build if artifacts stop emitting -- the old `--help | grep --target` only proved the flag existed, which is how the regression shipped. 2. llama-perplexity failed to link (undefined hip* refs, disallowed by --no-allow-shlib-undefined). Add -DCMAKE_EXE_LINKER_FLAGS so the exe links the HIP runtime (-L/opt/rocm/lib -lamdhip64), matching the local build. Verified: gfx942 AOT artifacts emit with no GPU; v2 builds + tags clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 153a7f6 commit 003ed0c

2 files changed

Lines changed: 85 additions & 1 deletion

File tree

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env python3
2+
"""Make Triton's AOT compiler (tools/compile.py) DRIVERLESS.
3+
4+
Why this exists
5+
---------------
6+
Triton 3.7.0 (the pinned 4768da5e the MI300X image builds) regressed ahead-of-time
7+
compilation: `triton.tools.compile.compile_kernel()` touches `driver.active` in two
8+
spots that require a *live* GPU, even when an explicit `--target hip:gfx942:64` is
9+
passed. A rootless `podman build` container has no GPU, so the AITER AOT step dies
10+
with `RuntimeError: 0 active drivers ([])`. AOT cross-compilation must NOT need the
11+
target (or any) GPU — that's the entire point of compiling ahead of time.
12+
13+
Both accesses are gratuitous:
14+
1. `kernel.create_binder()` -> jit.py `driver.active.get_current_target()`. The
15+
binder is a *runtime-launch* helper; AOT only needs `ASTSource`. Older Triton
16+
called `triton.compiler.ASTSource(...)` directly, with no binder.
17+
2. `ty_to_cpp = driver.active.map_python_to_cpp_type`. That method body is just
18+
`return ty_to_cpp(ty)` (the instance `self` is unused) — a thin shim over the
19+
module-level `ty_to_cpp` in the AMD backend driver. Import it directly.
20+
21+
After patching, `python3 -m triton.tools.compile ... --target hip:gfx942:64` emits
22+
real gfx942 HIP AOT artifacts with no GPU present (verified: emits the .c/.h pair).
23+
24+
This patch is AMD/HIP-specific (the image only ever AOT-compiles `hip:gfx942`), and
25+
idempotent. If an anchor is missing AND the patched form is also absent, it exits
26+
non-zero so a Triton version bump can't silently reintroduce the GPU dependency.
27+
28+
Usage: patch_triton_driverless_aot.py [/opt/triton]
29+
"""
30+
import sys
31+
from pathlib import Path
32+
33+
root = Path(sys.argv[1] if len(sys.argv) > 1 else "/opt/triton")
34+
target = root / "python" / "triton" / "tools" / "compile.py"
35+
if not target.is_file():
36+
sys.exit(f"[patch_triton_driverless_aot] not found: {target}")
37+
38+
src = target.read_text()
39+
40+
# (anchor, replacement). An empty replacement means "delete the anchor line".
41+
EDITS = [
42+
# 1a. drop the runtime-only binder (needs the live driver's current target)
43+
(" kernel.create_binder()\n", ""),
44+
# 1b. ...and source the AST directly instead of via the binder's class attr
45+
("src = kernel.ASTSource(", "src = triton.compiler.ASTSource("),
46+
# 2. pull the python->c++ type map from the module, not the live driver instance
47+
("ty_to_cpp = triton.runtime.driver.active.map_python_to_cpp_type",
48+
"from triton.backends.amd.driver import ty_to_cpp"),
49+
]
50+
51+
for anchor, repl in EDITS:
52+
if anchor in src:
53+
src = src.replace(anchor, repl)
54+
continue
55+
# idempotent: already patched? removal -> anchor simply absent; replace -> repl present
56+
if repl == "" or repl in src:
57+
continue
58+
sys.exit(
59+
f"[patch_triton_driverless_aot] ANCHOR NOT FOUND: {anchor!r}\n"
60+
f" Triton's AOT source changed — re-verify the driverless fix before trusting it."
61+
)
62+
63+
target.write_text(src)
64+
print(f"[patch_triton_driverless_aot] patched {target} — AOT is now driverless (gfx942, no GPU)")

scripts/calibration/mi300x/Dockerfile

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,25 @@ WORKDIR /opt/mad-lab/llama.cpp
5050
# local build trees, model blobs, and datasets so the context stays ~800 MB.
5151
COPY . .
5252

53+
# --- Make Triton's AOT compiler DRIVERLESS, then PROVE it with no GPU ---
54+
# Triton 3.7.0's tools/compile.py touches driver.active in two spots that need a
55+
# live GPU even with an explicit --target; a rootless `podman build` has none, so
56+
# the AITER AOT step below would die with "0 active drivers". The patcher removes
57+
# that gratuitous coupling (cross-compilation must not need the target GPU). The
58+
# gate then AOT-compiles a kernel for gfx942 with NO GPU and fails the build if it
59+
# ever stops emitting artifacts — the `--help | grep --target` check only proved
60+
# the flag EXISTS, which is how the original regression shipped. (The Triton install
61+
# above stays cached; this runs post-COPY so the patcher is in the context.) #170.
62+
RUN python3 ggml/src/ggml-cuda/aiter-integration/cmake/patch_triton_driverless_aot.py /opt/triton && \
63+
python3 -m triton.tools.compile ggml/src/ggml-cuda/aiter-integration/kernels/vector_add.py \
64+
--kernel-name add_kernel --target hip:gfx942:64 \
65+
--signature "*fp32:16, *fp32:16, *fp32:16, i32, 1024" \
66+
--grid "n_elements / 1024, 1, 1" --num-warps 4 --num-stages 1 \
67+
--out-name _aotgate --out-path /tmp/_aotgate && \
68+
ls /tmp/_aotgate*.c >/dev/null 2>&1 && \
69+
echo "[gate] driverless Triton AOT OK (gfx942 artifacts emitted, no GPU)" && \
70+
rm -f /tmp/_aotgate*
71+
5372
# --- build llama.cpp HIP libs + the perplexity binary for gfx942 ---
5473
# GGML_NATIVE=OFF: the local build bakes -march=native for THIS host CPU; off here
5574
# so the image runs on whatever CPU the MI300X host has.
@@ -72,7 +91,8 @@ RUN cmake -S . -B build-hip -G Ninja \
7291
-DGGML_NATIVE=OFF -DGGML_RPC=OFF -DLLAMA_CURL=OFF \
7392
-DCMAKE_C_COMPILER=/opt/rocm/llvm/bin/clang \
7493
-DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ \
75-
-DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ && \
94+
-DCMAKE_HIP_COMPILER=/opt/rocm/llvm/bin/clang++ \
95+
-DCMAKE_EXE_LINKER_FLAGS="-L/opt/rocm/lib -lamdhip64" && \
7696
cmake --build build-hip --target llama llama-perplexity -j"${JOBS:-$(nproc)}" && \
7797
test -e build-hip/bin/libllama.so && test -e build-hip/bin/llama-perplexity
7898

0 commit comments

Comments
 (0)