Repository navigation
Conversation
ROCm builds now skip the NVIDIA-only FlashAttention candidates during auto selection, and pinned host metadata is readable by Triton after a one-time hipHostGetDevicePointer identity check. VLLM_RLT_UVA=0 keeps the H2D fallback. Validated on MI350X/gfx950 with ROCm 7.2 and PyTorch 2.14.1.
FlashAttention, FA4 packed prefill and CUDA allocator-residue tests cannot run on ROCm; multi-GPU PD skips when fewer than two devices are visible. The remaining GPU suite passes on one MI350X.
Document the ROCm wheel install, the Triton-only backend matrix, probed UVA, measured Ouro-1.4B and Nanbeige4.2-3B throughput on MI350X, and the FlashAttention/packed-prefill/PD limits.
ROCm Triton accepts only ieee for tl.dot; BF16/FP16 prefill failed to compile because the kernel always requested tf32. CUDA keeps tf32 for FP16/BF16 and ieee for FP32.
The optional _C SiLU-and-Mul kernel is not built on ROCm, so its GPU vectors and the native-dispatch assertion cannot run there; the Torch fallback remains covered by the CPU tests.
StageEngine fixes an unset cuda_graph_max_batch_size before execution, so the test's raw ExecutionConfig was never the effective value. Compare against resolve_cuda_graph_rows instead.
Re-measure on the rebased main runtime (2e7b variant removed): Ouro-1.4B 855 tok/s, Nanbeige4.2-3B 1012 tok/s at 128 concurrent requests.
VLLM_RLT_UVA=1 is still false when no accelerator is visible, so the tests compare against torch.cuda.is_available() instead of asserting True on CPU CI.
A tiny Ouro model compares default execution with prefill_uva (Triton packed prefill) and wavefront chunked prefill; both must produce the same greedy tokens.
Add the all-features-first A/B table, model support rows, and the packed/WCPB/prefix/preemption/speculation status for Ouro-1.4B on MI350X.
Baseline is the same device/commit with default Triton execution and the same exit mode; warmed medians give 2.80x at batch 128 and 2.43x at batch 256 with all features. Record HIP_FORCE_DEV_KERNARG and HSA_ENABLE_INTERRUPT micro-tuning, hipBLASLt default, and validated Thinking/Huginn checkpoints.
Batch 512 all-features reaches 3760 tok/s (2.72x) and the 256-output-token decode run is 1.75x over baseline; short cells are prefill-heavy.
Packed engine parity fails on a real Ouro prompt despite passing kernel tests; exclude it from all-features and record the warmed per-feature matrix (WCPB 1.45x, all 2.86x at batch 128, decode-heavy 1.72x).
Long-context high-concurrency reaches 4.82x at batch 64 (27102 prefill tok/s). Speculation stays opt-in: graphs and K/draft tuning still lose to baseline (best 0.95x).
Priority scheduling cuts high-priority completion 7.80s to 2.22s; incremental KV gives +3.8%; sparse decode InferMatrixLab#157 passes 137 tests on the merged ROCm branch.
Pipeline K2/draft1 gives 814 vs 500 tok/s (1.63x) on Ouro-2.6B at batch 64/128 output, with 0.797 greedy match; 1.4B remains negative.
Packed prefill: FP32 greedy matches per-row; BF16 differs by <=0.0156 and stays opt-in. Ouro-2.6B speculation is 1.63x but GSM8K 0/20 both arms, so it is not default.
1.4B 256-output: pipeline K4/draft1 3270 (2842 confirmed), block K2/draft1 2148/2251, async K2/draft1 2314 vs 1527 baseline; 32-output remains prefill-dominated and loses.
runtime reaches 2.59x on short b256 and 5.73x on 1k b128; speculative long-context reaches 16.2x at 4k b8 (37150 prefill tok/s).
Ouro 8k spec reaches 21.4x (26800 prefill tok/s); Nanbeige 8k runtime 20.7x; Huginn is 4k-limited and graph replay gives 1.03x at batch 1.
One table with model column for Ouro/Nanbeige/Huginn at 1k/4k/8k, plus Huginn 1k/4k multi-batch and updated spec rows (256-out positive, 32-out negative).
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.
Summary
Add AMD Instinct (ROCm) as a supported execution platform for vllm-rlt without changing the Stage/Loop runtime or model arithmetic. On one MI350X it runs Ouro-1.4B, Ouro-2.6B, Nanbeige4.2-3B and Huginn-0125, and exercises the v0.2.0 feature set: Triton attention, packed prefill via
prefill_uva, WCPB, prefix cache, preemption/recovery, asynchronous scheduling, token pipeline, synchronous self-speculation, CUDA Graph replay, static buffers, multi-stream, probed UVA and serving.The CUDA path is unchanged: ROCm branches are capability-gated, auto selection still prefers FA4/FA3/FA2 on NVIDIA, and the native CUDA build is untouched.
Required human contributor answers
1. What outcome are you trying to achieve?
Make the current v0.2.0 runtime features usable on AMD Instinct with the same public interfaces, validated on the supported model families, in one reviewable PR.
2. What is the highest-leverage variable for that outcome?
The platform-specific decisions that were hard-coded to NVIDIA: attention-backend selection, host-metadata accessibility, and Triton's dot precision. Fixing those unlocks the existing scheduler, graphs, packed-prefill, async and speculation paths without new kernels.
3. How will this work move that variable rather than create busywork?
ROCm auto selection tries Triton then Torch and never imports FlashAttention. UVA is enabled only after a
hipHostGetDevicePointeridentity probe and has an environment fallback. Triton prefill usesieeedot precision where ROCm rejectstf32. NVIDIA-only and allocator-specific tests skip with explicit reasons.4. Who is the customer or user, and what do they actually need?
Users running Ouro, Nanbeige and Huginn on MI300/MI350 who need the same scheduling, cache and graph features without a CUDA stack, and maintainers who need a testable platform boundary.
PR necessity and bugfix evidence
A PR is needed. Before this change ROCm ran only because Triton happened to be the first importable backend after three NVIDIA imports failed; UVA was disabled by
not torch.version.hip; Triton prefill failed to compile because ROCm rejectsinput_precision="tf32"; and the ROCm GPU suite produced 163 native-extension errors plus 13 failures from NVIDIA-only parametrizations. With this PR the suite is green apart from explicit skips, and the new packed/WCPB parity test passes.Scope
tests/test_attention.py, A/Bprefill_uvaalltests/test_rocm.pyparity, A/Btests/test_speculative.py, A/Btests/test_tensor_transfer.py,tests/test_rocm.pytests/test_serving.pyModel support
Changes
vllm_rlt/platform.py:is_rocm()/is_cuda()/supports_flash_attention().vllm_rlt/attention/backend.py: ROCm auto order istriton,torch; FlashAttention reason is reported.vllm_rlt/kernels/triton_attention.py:ieeedot precision on ROCm.vllm_rlt/worker/tensors.py: probed UVA withVLLM_RLT_UVA=auto|0|1.vllm_rlt/engine/stage_engine.py: platform-neutral graph message.tests/test_rocm.py(platform, UVA, packed/WCPB parity); NVIDIA-only, allocator and multi-GPU skips; resolved graph-row comparison.docs/rocm.md, README/docs index/launching links.Test Plan
vllm-rlt commit: 47c25c3 (branch
rocm-support, based on444638b)Environment: 1× AMD Instinct MI350X VF (
gfx950, 288 GiB HBM), ROCm 7.2, PyTorch 2.14.1+rocm7.2, Triton 3.5.1, Python 3.12,CUDA_VISIBLE_DEVICES=0.ruff check .andruff format --check .: pass.pytest -q -m "not gpu"→ 909 passed, 46 skipped.pytest -q --run-gpu→ 1240 passed, 314 skipped.Test Result
All features (A/B first)
Baseline: same commit, model, device and wheel set,
attention_backend="triton",ExecutionConfig()defaults, sameouro_delayedexit mode,VLLM_RLT_UVA=0, and no optional features. There was no earlier ROCm baseline, so all numbers are ROCm-relative; CUDA numbers were not measured on this lease. One warm-up generation is discarded, then the median of three runs is reported (32 output tokens).The 32-token runs are prefill-heavy (80 prompt tokens per request); the 256-token run is decode-heavy. Baseline is 6.3 ms/step versus 3.4 ms/step for all features at batch 128, so the decode path still has host-sync and kernel-count headroom.
all= async scheduling + CUDA Graphs + static buffers + power-of-two padding + UVA + WCPB + prefix cache. Packed prefill is excluded because its BF16 output is not token-identical.Full-feature sweep
Short context (80-token prompt, 64 output), Ouro-1.4B:
Long context and checkpoints (1k/4k/8k).
runtime= async + graphs + static/pad2 + UVA + WCPB + prefix;specadds pipeline K4/draft1. Huginn's optimized column is graph replay; Nanbeige has no spec path:Huginn is compute-bound by 32 recurrent steps (flat across batch), graph replay adds 3-9%, and 8k is rejected by its context limit. 8k Ouro prefill: 1247 -> 11544 -> 26800 tok/s.
ROCm micro-tuning
HIP_FORCE_DEV_KERNARG=1HSA_ENABLE_INTERRUPT=0PyTorch already reports
preferred_blas_library=hipblaslt; forcing it explicitly did not improve throughput, so no rocBLAS fallback is needed.rocprofv3is available for kernel-vs-wall validation.Per-feature cold A/B
Single cold run per cell, no warm-up, so it includes JIT and graph-capture cost; directional only. Short is batch 128 output tok/s, long is batch 8 prefill tok/s.
Spec rows use 256 output tokens; at 32 output they lose (0.51x/0.95x/0.89x), see the workload-dependent paragraph.
Batch 128, 32 output tokens, one warm-up discarded, median of three; non-spec rows use the same
ouro_delayedbaseline, spec rows use the legalourobaseline.Priority scheduling is positive: with 64 low- and 8 high-priority requests at 16 slots, the high-priority median completion drops from 7.80s (fcfs) to 2.22s (priority); total time moves 7.81s to 8.15s. Incremental KV gives 817 -> 848 tok/s at batch 64 (+3.8%).
Sparse decode (#157) merged with this branch passes
137 passed, 3 skippedon ROCm (attention/batched/fused/sync suites); evidence in #157 (comment). It is tracked in #157 and not part of this PR.Speculation is workload-dependent. At 32 output tokens the 80-token prefill dominates and it loses; at 256 output tokens the decode-heavy path wins on Ouro-1.4B (baseline 1527 tok/s): pipeline K4/draft1 3270 in the sweep and 2842 in a confirmation run (1.82x), block K2/draft1 2148/2251 (1.41-1.44x), async K2/draft1 2314 (1.48x). On Ouro-2.6B (batch 64, 128 output) pipeline K2/draft1 is 814 vs 500 (1.63x). Greedy token match against baseline is 0.66-0.80 and a 20-question GSM8K check scored 0/20 for both arms, so it stays opt-in and is not enabled by
all.Functional checks
tests/test_rocm.py). Packed prefill kernel tests pass, but engine parity on a real Ouro prompt fails and is not claimed." Paris.\n\nThe final answer is"." Paris.\n\nThe capital of France is Paris."." Paris.\n\nThe answer is (A) Paris.\n\n\\boxed{A}".--cuda-graphs:" Paris. It is the most populous city in France...", 32 exit depths.Limitations and follow-ups
all.