Repository navigation
Conversation
`_has_vllm` in fp8_kernel.py is True only on ROCm with SGLANG_USE_AITER off and vllm._C importable. No shipped configuration gets there: rocm.Dockerfile sets SGLANG_USE_AITER=1, rocm-gfx1151.Dockerfile sets it to 0 but installs no vLLM, and the nightly AMD CI runs with it on. The one configuration that does select the arm cannot complete a forward pass on current main: RMSNorm.forward_hip calls fused_add_rms_norm with AITER's 6-argument out-of-place signature, and with AITER off that name is bound to vLLM's 4-argument in-place op, so the first post-attention norm raises TypeError. Remove the probe and the three `elif _has_vllm:` arms. With AITER on nothing changes; with AITER off the native path takes over, which is what gfx1151 already runs. The native path is numerically the same algorithm as the vLLM ops: static quant is bit-identical, and dynamic quant differs only by rounding the scale in the input dtype (spread tracks bf16/fp16 epsilon, and collapses to 5e-8 when the same formula is evaluated in fp32). It is 2.4-11x slower per call, which no working deployment pays since the configuration that reached the removed arm cannot serve.
siliangchen-amd
requested review from
BBuf,
DarkSharpness,
HaiShaw,
HydraQYH,
celve and
yuan-luo
as code owners
September 23, 2026 08:15
HaiShaw
approved these changes
Sep 23, 2026
This was referenced Sep 24, 2026
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.
Motivation
Follow-up to #40557: The reviewer asked why
_has_vllmis still kept._has_vllminfp8_kernel.pyis only ever set insideif _is_hip:, and only in the arm where_use_aiteris false:So the vLLM arm is selected in exactly one configuration: ROCm,
SGLANG_USE_AITERoff, andvllm._Cimportable. Nothing shipped reaches it:SGLANG_USE_AITERdocker/rocm.Dockerfile1docker/rocm-gfx1151.Dockerfile0nightly-test-amd.yml1python/pyproject.tomlAnd the one configuration that does select it cannot complete a forward pass on current
main.RMSNorm.forward_hipcallsfused_add_rms_normwith AITER's 6-argument out-of-place signature; with AITER off,layernorm.pybinds that name to vLLM's 4-argument in-place op instead. Replaying layer 0's calls in execution order in that configuration:A real
RMSNormmodule called with a residual fails the same way, from the dispatch it actually takes:So the vLLM FP8 arm runs twice in layer 0 and then the first residual norm raises. The
fused_add_rms_normsignature is the same in vLLM 0.26.0 and 0.27.1.Modifications
_has_vllm, thevllm._Cimport probe, and the threeelif _has_vllm:arms (dynamic per-token, dynamic per-tensor, static). The import guard becomesif _is_hip and _use_aiter:.torch.emptyscale, so the allocation is hoisted. The comment added in [AMD] Drop the redundant scale zero-fill before AITER per-tensor FP8 quant #40557, which explained why only vLLM needed the pre-zero, goes with the vLLM arm.One file, +13/−36.
Accuracy Tests
The native fallback against the vLLM ops it replaces, on all three call sites: 144 cases over bf16/fp16, six shapes from
1x4096to4096x4096, and gaussian, heavy-tailed and zero-row inputs. Run against both vLLM 0.27.1 and 0.26.0 with identical results.Static is bit-identical, including scales chosen to push values between 224 and 240 — so vLLM caps
float8_e4m3fnuzat 224 exactly as sglang does.The dynamic gap is a dtype effect, not an algorithmic one. The native path divides in the input dtype, and the scale spread tracks that dtype's epsilon:
For scale: AITER, which every shipped ROCm image runs, divides by the type maximum 240 where vLLM and sglang divide by 224. Its scale is a constant 224/240 = 0.9333 of vLLM's and it agrees with vLLM on ~20% of dynamic-quant bytes. Bit-compatibility with vLLM is not something this code relies on today.
After the patch, the public
scaled_fp8_quantis bit-identical to calling AITER directly withSGLANG_USE_AITER=1, and to calling the native fallback directly withSGLANG_USE_AITER=0, on all three call sites (18 cases per mode).Speed Tests and Profiling
The native path is 2.4–11x slower per call than vLLM's fused ops. µs per call on MI325X, bf16, vLLM 0.26.0, median of 7×300:
Eager timings show the same ordering (per-token 5.9–7.9x, per-tensor 1.7–3.0x, static 3.8–6.1x).
No working deployment pays this: the only configuration that reached the removed arm cannot serve a model (see Motivation), and gfx1151 was already on the native path. If the AITER-off + vLLM mode is ever repaired at
layernorm.py:766, its FP8 activation quant should get a fused kernel rather than fall through to the native path.Not in scope
Left alone on purpose, each for a reason:
layernorm.py_has_vllm_rms_norm— also setTruewhen AITER is on, where it means "a fast rms_norm is available", so it needs restructuring rather than deletion. It is also where the AITER-off + vLLM breakage actually lives.moe/.../fused_moe.py_has_vllm_ops— gated onnot _is_cuda and not _is_hip and not _is_xpu, so it serves other platforms, not ROCm.rotary_embedding/base.py— a previous attempt to drop the vLLM dependency there was reverted in Revert "[ROCm] Remove vLLM rope dependency & use AITER impl" #12028 after it broke GPT-OSS.The manual quant test under
SGLANG_USE_AITER=0test/manual/quant/test_custom_ops.py(not run in CI) passes 6/6 with AITER on, before and after this change. With AITER off it exercises whichever fallback is selected, so it is worth being explicit about:On the native path it passed 11 of 60 across ten runs. That is the native fallback as it already is on any ROCm host without vLLM; this change does not touch its arithmetic. Two things fail:
test_scaled_fp8_quant_with_paddinghits a genuine shape bug: withnum_token_paddingthe native fallback copies aninput-sized result into a talleroutputand raises. On ROCm,apply_fp8_linearpads compressed-tensors FP8 activations to at least 17 rows unless torch.compile is on, so a batch of fewer than 17 tokens reaches it on a host running without AITER or vLLM. It predates this change and is left for a separate one.Checklist
ruff format --check: clean.ruff check: 48 findings before and after the change on this file, none introduced._has_vllm. The existing manual test is covered in the section above.CI States
Latest PR Test (Base): ❌ Run #35836133330
Latest PR Test (Extra): ❌ Run #35836133089
Latest PR Test (AMD ROCm 10): ❌ Run #35836133443