Build and runtime notes for the AMD Radeon AI PRO R9700 (and RX 9070 XT) on ROCm 7.2.
AMD's RDNA4 architecture (gfx1201 / Navi 48) is new enough that pre-built vllm wheels do not target it. The official pip package is compiled for CUDA, and the AMD-published ROCm wheels are built for MI300-series datacenter GPUs (gfx942). Installing either will either fail at import or silently miscompile kernels for the wrong ISA.
Building from source with PYTORCH_ROCM_ARCH=gfx1201 produces HIP kernels compiled specifically for RDNA4's instruction set, which is meaningfully different from the MI300 and RDNA3 targets.
| Requirement | Version in use |
|---|---|
| ROCm | 7.2.4 at /opt/rocm |
| Python | 3.12 (.venv/) |
| uv | 0.11+ |
| Rust / cargo | 1.95 (for vllm's Rust frontend) |
| cmake | 3.26+ (system) |
System packages ninja-build and protobuf-compiler are installed by the script via apt-get.
vllm/ ← this directory (working root)
├── .venv/ ← Python 3.12 virtual environment
├── build_rocm.sh ← build script
└── vllm/ ← vllm source (git clone of vllm-project/vllm)
Clone the source if you haven't already:
git clone https://github.com/vllm-project/vllm.git./build_rocm.sh 2>&1 | tee build.logThe script runs five steps:
- System tools — installs
ninja-buildandprotobuf-compilerviaapt-get - PyTorch — installs
torch==2.11.0+rocm7.2(cp312) from the official PyTorch wheel index, plus matchingtorchvision,torchaudio, andtriton - Python build deps —
setuptools,setuptools-scm,setuptools-rust,jinja2,tilelang, etc. - Rust frontend — builds
vllm-rsand the_rust_tool_parserPyO3 extension viabuild_rust.sh - HIP compilation —
uv pip install -e .with--no-build-isolationso the already-installed ROCm torch is used rather than a CPU-only fallback
--no-build-isolation is critical: without it pip creates a fresh isolated environment, finds no ROCm index, and pulls a CPU-only torch that breaks the entire HIP build.
vllm's requirements/build/rocm.txt pins amdsmi==7.0.2, but ROCm 7.2.4 ships its own amdsmi with a different version scheme — AMD switched to calendar versioning, so the installed package is 26.2.2 (year 2026, month 2). The two version strings are not comparable; 26.2.2 is the newer, correct package for this ROCm installation.
The build script intentionally skips reinstalling amdsmi from pip. Letting pip resolve amdsmi==7.0.2 would either fail outright or downgrade to a package built against an older ROCm ABI. The version already in .venv (26.2.2+97f5574fe2, installed from the ROCm package tree) is what vllm uses at runtime to detect the GPU via amdsmi_init() / amdsmi_get_processor_handles() in platforms/__init__.py. If that call returns GPU handles, vllm knows it is on a ROCm system and loads the ROCm platform plugin. Do not reinstall or pin amdsmi from pip.
If amdsmi is not yet in your venv, the source tree is at /opt/rocm-7.2.4/share/amd_smi but it is owned by root, so uv pip install on that path directly will fail with a permission error when it tries to create a build cache. Copy it somewhere writable first:
cp -r /opt/rocm-7.2.4/share/amd_smi /tmp/amd_smi
uv pip install /tmp/amd_smiVerify afterwards:
.venv/bin/python -c "import amdsmi; print(amdsmi.__version__)"First build takes 20–40 minutes. The bottleneck is HIP kernel compilation. Subsequent builds reuse cmake's incremental build cache inside vllm/build/.
source .venv/bin/activate
vllm serve <model>Or without activating:
.venv/bin/vllm serve <model>| Variable | Default | Effect |
|---|---|---|
PYTORCH_ROCM_ARCH |
gfx1201 |
Set by the build; leave it in your shell for any tools that re-compile kernels (e.g. triton JIT) |
ROCBLAS_USE_HIPBLASLT |
1 |
Prefers hipBLASLt over rocBLAS for GEMM on gfx12xx; measurably faster |
VLLM_ROCM_USE_AITER |
1 (but ineffective) |
AITER is MI300-only; setting this has no effect on gfx1201 |
HIP_VISIBLE_DEVICES |
unset | Same role as CUDA_VISIBLE_DEVICES |
VLLM_WORKER_MULTIPROC_METHOD |
fork |
Default; fine for single-GPU |
vllm selects an attention backend per attention layer based on what the layer type requires and what the hardware supports. On gfx1201 you get:
ROCM_ATTN is selected automatically. This is vllm's native ROCm attention path: a C++ paged-attention kernel for decode, and a Triton chunked-prefill kernel for prefill. Block sizes must be multiples of 16; non-standard sizes (e.g. Qwen3's 544 or 784) are transparently routed to an optimised Triton kernel.
TRITON_ATTN is also available and can be forced with --attention-backend TRITON_ATTN if you need sink tokens, KV connectors, or ENCODER_DECODER attention type in a custom model.
Both use standard decoder attention on the draft model's layers. The draft runner (Step3p5MTPProposer / EagleProposer) inherits whatever backend was assigned to each attention layer — no special requirement. ROCM_ATTN handles it.
DFlash is a parallel-drafting method where the draft model attends to the target model's hidden states via cross-attention (ENCODER_DECODER type). ROCM_ATTN explicitly does not support ENCODER_DECODER (it would produce incorrect results for cached cross-attention K/V). vllm detects this per-layer and falls back automatically:
- Decoder self-attention layers →
ROCM_ATTN - Cross-attention layers →
TRITON_ATTN(fallback; supports all attention types)
You do not need to configure anything. The split is transparent at runtime; you will see log lines like:
Found incompatible backend(s) [ROCM_ATTN] with ENCODER_DECODER.
Overriding with TRITON_ATTN out of potential backends: ['TRITON_ATTN', 'TURBOQUANT'].
This is expected and correct behaviour.
TRITON_MLA only. The AITER MLA backends (ROCM_AITER_MLA, ROCM_AITER_TRITON_MLA) require MI300-series hardware and are not available on gfx1201.
TORCH_SDPA by default.
To enable Flash Attention's Triton path for ViT layers, install a ROCm build of flash-attn and set:
FLASH_ATTENTION_TRITON_AMD_ENABLE=TRUE vllm serve <model>The AITER library (aiter package) contains precompiled ASM kernels tuned for MI300's matrix engines. Its entire backend family is hard-gated behind on_mi3xx() in vllm's platform code and will not activate on RDNA4, regardless of whether the package is installed:
ROCM_AITER_FA— MI300 flash attentionROCM_AITER_MLA/ROCM_AITER_TRITON_MLA— MI300 MLAROCM_AITER_UNIFIED_ATTN— unified attention with FP8 fused output quant
Installing aiter is harmless but pointless on this hardware.
gfx1201 supports FP8 (float8_e4m3fn — standard IEEE format, not the MI300-specific e4m3fnuz). Models quantised to FP8 will run correctly. The supported quantisation schemes are listed in vllm/platforms/rocm.py:RocmPlatform.supported_quantization and include fp8, deepseek_v4_fp8, compressed-tensors, fbgemm_fp8, and others.
cd vllm
git pull
cd ..
./build_rocm.sh 2>&1 | tee build.logcmake will perform an incremental rebuild; only changed files are recompiled. Pure Python changes (no .cu / .hip / .cpp modifications) are picked up immediately without rebuilding because the install is editable (-e).