Skip to content

feat(backend/python): build vllm from source for AMD consumer/RDNA GPUs - #10998

Draft
walcz-de wants to merge 7 commits into
mudler:masterfrom
walcz-de:feat/rocm-vllm-source-build
Draft

walcz-de wants to merge 7 commits into
mudler:masterfrom
walcz-de:feat/rocm-vllm-source-build

Conversation

@walcz-de

@walcz-de walcz-de commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

What

vllm's ROCm install pulls a prebuilt wheel from wheels.vllm.ai/rocm, but that wheel exists only for CDNA data-center arches (gfx942/gfx950) and is pinned to a rocm7.2.3 torch that can't enumerate consumer/RDNA GPUs (device_count == 0 on e.g. gfx1151). There is no prebuilt vllm wheel for these GPUs anywhere — which is why AMD ships a whole rocm/vllm:*_rdna_* container. This builds vllm from source against AMD's ROCm 7.14 torch, reproducing that container's recipe inside LocalAI's normal Dockerfile.python build (FROM-scratch, portable venv — no external gRPC / no 73 GB image).

How

  • torch[device-gfx<arch>] + rocm-sdk-devel (hipcc + the HIP CMake packages the runtime _rocm_sdk_core lacks) from AMD's multi-arch index; ROCM_PATH/CMAKE_PREFIX_PATH resolved from the SDK's own rocm-sdk path CLI — self-contained, no system /opt/rocm needed.
  • vLLM detects ROCm at runtime via import amdsmi; register the SDK's in-place amd_smi with a .pth. A pip copy breaks its relative libamd_smi.so lookup, and forcing the lib via LD_LIBRARY_PATH shadows torch's own ROCm runtime and zeroes device_count.
  • run.sh exposes the bundled amdclang as CC/CXX: Triton JIT-compiles kernels at first inference and the runtime image ships hipcc but not cc/gcc, so without it inference dies with "Failed to find C compiler". Mirrors the CPU-toolchain block just above it.

The prebuilt path is kept, not replaced

install.sh picks between the two on the target arch: a target set covered entirely by gfx942/gfx950 installs the wheels.vllm.ai wheel exactly as before, anything else builds from source. So the published ROCm image stays what it is today, build time included — and its matrix entry pins amdgpu-targets: 'gfx942,gfx950' so the repo-wide default list (which contains consumer arches) cannot silently turn it into a multi-hour source build.

Consumer GPUs get their own image, because the two install paths cannot share one venv:

image arch vllm
-gpu-rocm-hipblas-vllm (rocm-vllm) gfx942, gfx950 prebuilt wheel, unchanged
-gpu-rocm-hipblas-gfx1151-vllm (rocm-gfx1151-vllm) gfx1151 built from source

The new backend is deliberately not in the amd: capability map: that map cannot know the caller's gfx arch, so rocm-vllm stays the automatic choice and the consumer image is installed by name. One arch per image because each AMD torch device package is ~1.6 GB installed (measured), so bundling arches is not free.

Testing

Hardware-validated on gfx1151: builds from a single make, is loaded natively by LocalAI from /backends/vllm (no external gRPC), and generates. Only gfx1151 was tested on real hardware; other AMD arches use the same mechanism but are unverified.

Dependency

Stacks on #10978 (ROCm 7.14 base) and #10997 (multi-arch torch / AMDGPU_TARGETS). Reviewable change is the top commit.

@localai-org-maint-bot localai-org-maint-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ROCm work is substantial, but the stacked commit fix(rocm): update Go backend Dockerfile for TheRock packaging contains Co-authored-by: localai-org-maint-bot .... LocalAI policy explicitly forbids AI/bot Co-Authored-By trailers; AI assistance must be recorded with Assisted-by: AGENT_NAME:MODEL_VERSION [TOOLS] instead (see .agents/ai-coding-assistants.md). Please rewrite that commit trailer before merge.

@mudler tagging you because this is a repository-policy blocker on the otherwise valuable ROCm series.

@walcz-de
walcz-de force-pushed the feat/rocm-vllm-source-build branch from 836fe95 to 3f39cec Compare July 26, 2026 06:28
@walcz-de

Copy link
Copy Markdown
Contributor Author

Addressed the policy blocker: removed the Co-authored-by: localai-org-maint-bot trailer from the Go-backend Dockerfile commit and added the required Assisted-by: AGENT:MODEL trailers across the whole ROCm series (#10978 / #10997 / #10998) per .agents/ai-coding-assistants.md. Only commit messages changed — trees are byte-identical (verified via git range-diff), each commit keeps its human Signed-off-by, DCO is green on all three. Force-pushed the stacked branches. Thanks for the catch.

@localai-org-maint-bot
localai-org-maint-bot force-pushed the feat/rocm-vllm-source-build branch 2 times, most recently from e4389d4 to 9501bc2 Compare August 19, 2026 15:13

@localai-org-maint-bot localai-org-maint-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DCO passes. Two blocking issues:

  1. Same gfx1151 CDNA regression as #10997vllm/install.sh defaults to gfx1151 with AMDGPU_TARGETS never set in the matrix. vLLM on AMD is primarily a CDNA (MI300X/MI356) workload — a gfx1151-default torch is wrong for the common case. Same fix needed (per-entry AMDGPU_TARGETS).

  2. Source build CI unverified — Pinned to VLLM_REF=v0.23.0 built from source with MAX_JOBS=8 (hours-long build). The old path pulled a prebuilt wheel from wheels.vllm.ai/rocm; this PR drops that entirely, so there's no fallback if the source build fails. Need to confirm a green CI build before merge.

Also needs rebase onto a merged #10997 (which itself needs #10978 first).

The amdsmi.pth trick and amdclang PATH setup for Triton JIT are well-documented and handle non-obvious issues correctly.

…1 / Strix Halo)

ROCm 7.14 adds native gfx1151 (Strix Halo / RDNA 3.5) runtime support. The
prebuilt ROCm images pinned rocm/dev-ubuntu-24.04:7.2.1, which predates gfx1151
support, so the published -gpu-rocm-hipblas-* images do not run on that hardware
even though gfx1151 is already in AMDGPU_TARGETS.

Bump the pin to rocm/dev-ubuntu-24.04:7.14.0-full everywhere it is referenced:
- .github/backend-matrix.yml  (all hipblas backend build entries)
- .github/workflows/base-images.yml  (base-grpc-rocm-amd64 gRPC cache is rebuilt
  on 7.14 so it stays ABI-compatible with the new runtime base)
- .github/workflows/image.yml + image-pr.yml  (core hipblas image)
- .agents/*.md examples + backend/Dockerfile.base-grpc-builder comment

Verified on gfx1151 / Strix Halo: a full ROCm 7.14 stack (LocalAI + llama.cpp
hipblas, vLLM, embeddings/reranker) runs natively, no HSA_OVERRIDE_GFX_VERSION
needed. Other AMD architectures (gfx908/90a/942/1030/1100/1200/1201) build on
the same base and are covered by CI; I do not have that hardware to test at runtime.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: stefanwalcz <stefan.walcz@walcz.de>
…gister lib paths)

ROCm 7.x moved to 'TheRock' packaging. Bumping the base to
rocm/dev-ubuntu-24.04:7.14.0-full surfaces two build breakages, fixed here in
ALL THREE spots that installed the legacy ROCm dev metapackages:

1) Legacy hipblas-dev / hipblaslt-dev / rocblas-dev metapackages were removed
   (consolidated + arch-split: amdrocm-blas<ver>-gfx*, amdrocm-blas-dev, ...).
   'apt-get install' of the old names fails. The -full base already ships the
   BLAS dev libs+headers, so the install is dropped in:
     - Dockerfile (requirements-drivers)          -> core image
     - .docker/install-base-deps.sh (section 6)   -> C++ backend builder
     - backend/Dockerfile.python (hipblas block)  -> Python backends (vllm,
       sglang, transformers, diffusers, kokoro, ...)

2) TheRock scatters the ROCm libs across /opt/rocm/lib,
   /opt/rocm/lib/rocm_sysdeps/lib and /opt/rocm/llvm/lib with no ld.so.conf.d
   entry, so the dynamic linker can't resolve them and the built backends fail
   at RUNTIME ('... cannot open shared object file') — a failure CI never sees
   because it only surfaces when a backend loads on an AMD GPU. Fixed by
   registering all three lib dirs in /etc/ld.so.conf.d/rocm.conf before ldconfig
   in all three blocks.

Validated end-to-end on gfx1151 / Strix Halo (build + GPU inference, llama-cpp).
Ref: https://rocm.docs.amd.com/en/latest/about/transition-guide-TheRock.html

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: stefanwalcz <stefan.walcz@walcz.de>
Apply the same ROCm 7.14 dependency + linker-path migration to
backend/Dockerfile.golang: the removed legacy hipblas-dev / hipblaslt-dev /
rocblas-dev metapackages are no longer installed (the rocm/dev-ubuntu-*:*-full
base already ships them), and TheRock's scattered ROCm lib dirs are registered
in /etc/ld.so.conf.d/rocm.conf before ldconfig so cgo-based Go backends resolve
the ROCm runtime libraries at build/link and runtime.

Identified by the LocalAI maintenance bot; re-authored under my identity per DCO.

Assisted-by: Codex:gpt-5
Signed-off-by: stefanwalcz <stefan.walcz@walcz.de>
…kends

The -full base ships the ROCm BLAS runtime libraries but not the CMake
package-config files (hipblasConfig.cmake / hipblas-config.cmake) that
find_package(hipblas) resolves against. Dropping the legacy -dev metapackages
is correct for runtime-only paths, but from-source CMake/cgo backends (e.g.
qwen3-tts) fail at configure time (find_package(hipblas)) without them.

Install TheRock's development component amdrocm-blas-dev in the Go/C++ backend
hipblas path so those backends build again, while keeping runtime-only paths
dev-free. Fixes the qwen3-tts hipblas configure failure surfaced in CI.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: stefanwalcz <stefan.walcz@walcz.de>
Select the BLAS development package set advertised by each ROCm base image so shared Go backend builds work with both legacy ROCm 6.x and TheRock-based ROCm 7.x images.

Assisted-by: Codex:GPT-5 [Codex CLI]
Signed-off-by: Stefan Walcz <stefan.walcz@walcz.de>
…users/kokoro

The community whl/rocm7.0 torch wheel these backends install does not enumerate
consumer/RDNA AMD GPUs (torch.cuda.device_count() == 0 on e.g. Strix Halo /
gfx1151), so they silently fall back to CPU or fail to load. AMD publishes a
stable ROCm 7.14 torch for essentially every AMD arch on its multi-arch index,
selected per GPU via the torch[device-gfx<arch>] extra.

Install torch from that index in an isolated step: the index returns 403 for
packages it doesn't serve (accelerate/transformers/...), which uv treats as
fatal, so only the torch family is pulled there and everything else resolves
from PyPI. The arch comes from the build via a new AMDGPU_TARGETS ARG/ENV on
backend/Dockerfile.python.

AMDGPU_TARGETS is the repo-wide comma-separated gfx list, and the device extras
compose: torch[device-gfx942,device-gfx1151] installs both device packages side
by side (verified against the index). So the whole list is mapped, not its first
entry.

Which arches an image carries is therefore a matrix decision, and the hipblas
entries for these three backends now say so explicitly (gfx942,gfx950,gfx1151:
both CDNA data-center arches plus Strix Halo) instead of inheriting the repo-wide
11-arch default. Each device package is ~1.6 GB installed, measured, so that
default would add ~17 GB per image; adding a further arch is one matrix entry at
~1.6 GB.

Only gfx1151 was validated on real hardware (transformers generates text,
diffusers runs SD-1.5, kokoro runs TTS); the mechanism is arch-generic for any
AMD GPU AMD ships a device wheel for.

Signed-off-by: stefanwalcz <stefan.walcz@walcz.de>
vllm's ROCm install pulls a prebuilt wheel from wheels.vllm.ai/rocm, but that
wheel exists only for CDNA data-center arches (gfx942/gfx950) and is pinned to a
rocm7.2.3 torch that cannot enumerate consumer/RDNA GPUs (device_count == 0 on
e.g. gfx1151). There is no prebuilt vllm wheel for these GPUs anywhere, which is
why AMD ships a whole rocm/vllm:*_rdna_* container.

Build vllm from source against AMD's ROCm 7.14 torch, reproducing that
container's recipe inside LocalAI's normal Dockerfile.python build (FROM-scratch,
portable venv, no external gRPC, no 73 GB image):

  * torch[device-gfx<arch>] plus rocm-sdk-devel (hipcc and the HIP CMake packages
    the runtime _rocm_sdk_core lacks) from AMD's multi-arch index, with
    ROCM_PATH/CMAKE_PREFIX_PATH resolved from the SDK's own `rocm-sdk path` CLI.
    Self-contained: no system /opt/rocm.
  * vLLM detects ROCm at runtime via `import amdsmi`, so register the SDK's
    in-place amd_smi with a .pth. A pip copy breaks its relative libamd_smi.so
    lookup, and forcing the lib via LD_LIBRARY_PATH shadows torch's own ROCm
    runtime and zeroes device_count.
  * run.sh exposes the bundled amdclang as CC/CXX: Triton JIT-compiles kernels at
    first inference and the runtime image ships hipcc but no cc/gcc, so without it
    inference dies with "Failed to find C compiler". Mirrors the CPU-toolchain
    block just above it.

The prebuilt path is kept, not replaced. install.sh picks between the two on the
target arch: a target set covered entirely by gfx942/gfx950 installs the
wheels.vllm.ai wheel exactly as before, anything else builds from source. The
published ROCm image therefore stays what it is today, build time included, and
its matrix entry pins amdgpu-targets to those two arches so the repo-wide default
list (which contains consumer arches) cannot silently turn it into a multi-hour
source build.

Consumer GPUs get their own image instead, because the two install paths cannot
share one venv: matrix entry -gpu-rocm-hipblas-gfx1151-vllm and the backend
rocm-gfx1151-vllm in backend/index.yaml. It is deliberately not in the `amd:`
capability map -- that map cannot know the caller's gfx arch, so rocm-vllm stays
the automatic choice and this one is installed by name.

Hardware-validated on gfx1151: builds from a single make, is loaded natively by
LocalAI from /backends/vllm, and generates. Only gfx1151 was tested on real
hardware; other AMD arches use the same mechanism but are unverified.

Signed-off-by: stefanwalcz <stefan.walcz@walcz.de>
@walcz-de
walcz-de force-pushed the feat/rocm-vllm-source-build branch from 9501bc2 to cef188b Compare September 12, 2026 16:19

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants