feat: upgrade AIC stack to ROCm 7.14 with vLLM v0.26.0 source build - #112
Open
sbates130272 wants to merge 1 commit into
Open
feat: upgrade AIC stack to ROCm 7.14 with vLLM v0.26.0 source build#112sbates130272 wants to merge 1 commit into
sbates130272 wants to merge 1 commit into
Conversation
Moves the AIC stack from rocm/dev-ubuntu-24.04:7.2.4-complete to
rocm/dev-ubuntu-24.04:7.14.0-full. Replaces the pre-built vLLM wheel
with a full source build at v0.26.0. Adds and validates benchmark
infrastructure for SPUR cluster (MI355X/gfx950) tiered KV cache.
### Stack changes
- **Base image**: ROCm 7.2.4-complete → 7.14.0-full
- **hipFile**: removed separate ROCm/rocm-systems build — hipFile is GA
in ROCm 7.14 and ships in the base image
- **vLLM**: pre-built wheel → source build at v0.26.0 with two AMD patches:
- `01`: fix rocm_platform_plugin() — amdsmi returns 0 devices post-torch
init; add torch.version.hip fallback for ROCm detection
- `02`: break circular import in rocm.py _get_gcn_arch() — replace
logger.warning_once() with stderr print to avoid the vllm.platforms
import cycle
- **LMCache**: v0.5.2 with 9 AMD patches including:
- `09`: serialise NixlStorageAgent.make_prepped_xfer() — the NIXL C++
makeXferReq() is not thread-safe when called concurrently on shared
pre-built dlist handles. With max-gpu-workers > 1, multiple asyncio
coroutines reach make_prepped_xfer() simultaneously and hit
NIXL_ERR_INVALID_PARAM, silently zeroing all L2 reads
(agent_rx_bytes_total stays 0). Fix: _xfer_handle_lock serialises
handle creation only; in-flight DMA transfers remain parallel.
- **Torch**: switched to AMD native ROCm 7.14 wheel index (repo.amd.com)
- **Runtime env vars added**: HSA_ENABLE_IPC_MODE_LEGACY=1,
SAFETENSORS_FAST_GPU=1, HIP_FORCE_DEV_KERNARG=1
- **Monitoring exporters bumped**: node-exporter v1.8.2→v1.12.1,
device-metrics-exporter v1.4.2→v1.5.1
### SPUR cluster fixes
- **NIXL POSIX backend**: default `AIC_L2_BACKEND=nixl_posix` on SPUR —
hipFile P2PDMA (AIS_MT) hits NIXL_ERR_BACKEND on XFS LVM nodes because
GPUDirect storage is unavailable. POSIX plugin avoids hipFileBufRegister.
- **POSIX slot sizing**: `LMCACHE_NIXL_POSIX_SLOT_SIZE=16777216` (16 MiB)
replaces the 256 MiB AIS_MT default, which was 28× too large for POSIX
where only actual KV bytes are written per slot (gpt-oss-120b fp8: ~9 MiB
per chunk). Fixes 100–400s warmup times per concurrency point.
- **lmcache Prometheus port**: `--prometheus-port 9091` — the default 9090
conflicted with Prometheus itself, silencing all lmcache L1/L2 metrics.
prometheus.yml updated to scrape :9091.
- **NIXL prefetch cap**: `--l2-prefetch-max-in-flight 4` — prevents the
NIXL descriptor pool from exhausting under concurrent load.
- **Post-warmup drain**: `POST_WARMUP_SLEEP_S=300` (was 5s) — with
serialised POSIX writes, the warmup write queue takes hundreds of seconds
to flush; 5s left iter 0 measuring write-queue back-pressure not cache hits.
- **Monitoring on SPUR**: `AIC_EXPORTERS=0` — the spur-authz plugin blocks
`--pid=host`, causing the exporter fleet compose-up to fail and take
Prometheus down with it. Prometheus-only mode skips the blocked containers.
- **sbatch mkdir**: `_mkdir_shared()` helper — NVMe slab dirs on
/mnt/m2m_nobackup may be owned by root; falls back to passwordless sudo.
- **SPUR sbatch quirks**: drop `--no-requeue` (unsupported), clear
`--gres=gpu:1` with `--gres=`, fix `AIC_CLIFF_ARMS` pass-through.
- **Build failure bug**: `run-build-distribute.sh` previously treated Docker
buildx failures as cache-lock races and continued, silently shipping the
previous tarball. Now exits 1 on any buildx failure.
### New Makefile targets
- `cliff-spur-l2`: SPUR-tuned L2 cliff — per_client prefix, util=0.40,
8 GB DRAM L1, c=32, nvme arm only. Designed to overflow the LMCache DRAM
L1 (32 × 630 MiB ≈ 20 GB > 8 GB) and produce ext_hit > 0%.
- `cliff-kvd`: focused KVD cliff — shared prefix, sparse c ladder
(1,8,32,64,128,250), 2 iters.
- `$(origin)` guards on all per-target variable overrides — fixes silent
no-op when Makefile exports empty `?=` variables (e.g.
VLM_GPU_MEMORY_UTILIZATION) that are set-but-empty in the sbatch shell,
causing `:-default` guards to never fire.
### Streaming container logs
`docker logs -f --timestamps` for lmcache and vllm are now streamed to
`logs/<job-id>/lmcache/lmcache-stream.log` and
`logs/<job-id>/vllm/vllm-stream.log` throughout each kvd arm, enabling
fine-grained timing analysis rather than only capturing logs at teardown.
### Validated on SPUR MI355X (gfx950)
All three cliff arms pass (jobs 6273, 6382):
vram_only: ~146k tok/s
kvd_nvme: POSIX L2 functional; NIXL lock fix confirmed zero NIXL errors
kvd_gds: ~10k tok/s
Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Stephen Bates <sbates@raithlin.com>
sbates130272
requested review from
amd-ivaganev,
gaoikawa and
vcave
as code owners
July 29, 2026 21:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Moves the AIC stack from rocm/dev-ubuntu-24.04:7.2.4-complete to rocm/dev-ubuntu-24.04:7.14.0-full. Replaces the pre-built vLLM wheel with a full source build at v0.26.0. Adds and validates benchmark infrastructure for SPUR cluster (MI355X/gfx950) tiered KV cache.
Stack changes
01: fix rocm_platform_plugin() — amdsmi returns 0 devices post-torch init; add torch.version.hip fallback for ROCm detection02: break circular import in rocm.py _get_gcn_arch() — replace logger.warning_once() with stderr print to avoid the vllm.platforms import cycle09: serialise NixlStorageAgent.make_prepped_xfer() — the NIXL C++ makeXferReq() is not thread-safe when called concurrently on shared pre-built dlist handles. With max-gpu-workers > 1, multiple asyncio coroutines reach make_prepped_xfer() simultaneously and hit NIXL_ERR_INVALID_PARAM, silently zeroing all L2 reads (agent_rx_bytes_total stays 0). Fix: _xfer_handle_lock serialises handle creation only; in-flight DMA transfers remain parallel.SPUR cluster fixes
AIC_L2_BACKEND=nixl_posixon SPUR — hipFile P2PDMA (AIS_MT) hits NIXL_ERR_BACKEND on XFS LVM nodes because GPUDirect storage is unavailable. POSIX plugin avoids hipFileBufRegister.LMCACHE_NIXL_POSIX_SLOT_SIZE=16777216(16 MiB) replaces the 256 MiB AIS_MT default, which was 28× too large for POSIX where only actual KV bytes are written per slot (gpt-oss-120b fp8: ~9 MiB per chunk). Fixes 100–400s warmup times per concurrency point.--prometheus-port 9091— the default 9090 conflicted with Prometheus itself, silencing all lmcache L1/L2 metrics. prometheus.yml updated to scrape :9091.--l2-prefetch-max-in-flight 4— prevents the NIXL descriptor pool from exhausting under concurrent load.POST_WARMUP_SLEEP_S=300(was 5s) — with serialised POSIX writes, the warmup write queue takes hundreds of seconds to flush; 5s left iter 0 measuring write-queue back-pressure not cache hits.AIC_EXPORTERS=0— the spur-authz plugin blocks--pid=host, causing the exporter fleet compose-up to fail and take Prometheus down with it. Prometheus-only mode skips the blocked containers._mkdir_shared()helper — NVMe slab dirs on /mnt/m2m_nobackup may be owned by root; falls back to passwordless sudo.--no-requeue(unsupported), clear--gres=gpu:1with--gres=, fixAIC_CLIFF_ARMSpass-through.run-build-distribute.shpreviously treated Docker buildx failures as cache-lock races and continued, silently shipping the previous tarball. Now exits 1 on any buildx failure.New Makefile targets
cliff-spur-l2: SPUR-tuned L2 cliff — per_client prefix, util=0.40, 8 GB DRAM L1, c=32, nvme arm only. Designed to overflow the LMCache DRAM L1 (32 × 630 MiB ≈ 20 GB > 8 GB) and produce ext_hit > 0%.cliff-kvd: focused KVD cliff — shared prefix, sparse c ladder (1,8,32,64,128,250), 2 iters.$(origin)guards on all per-target variable overrides — fixes silent no-op when Makefile exports empty?=variables (e.g. VLM_GPU_MEMORY_UTILIZATION) that are set-but-empty in the sbatch shell, causing:-defaultguards to never fire.Streaming container logs
docker logs -f --timestampsfor lmcache and vllm are now streamed tologs/<job-id>/lmcache/lmcache-stream.logandlogs/<job-id>/vllm/vllm-stream.logthroughout each kvd arm, enabling fine-grained timing analysis rather than only capturing logs at teardown.Validated on SPUR MI355X (gfx950)