Conversation
FP8ScaledMMLinearKernel.apply_weights already consumes a matching QuantizedActivation, but the AITER PTPC kernels never exposed input_quant_key(), so expose_input_quant_key left the layer unmarked. Return the key from the AITER PTPC kernels and expose it on Fp8PtpcOnlineLinearMethod. Do not override input_quant_key on FP8ScaledMMLinearKernel: torch fallbacks call get_output_padding() via get_current_vllm_config(), which is unset in profile_run. Signed-off-by: Rebecca Lee <rebecca.lee@amd.com>
When o_proj.input_quant_key is kFp8DynamicTokenSym, fuse gated RMSNorm and per-token FP8 in one Triton kernel so the linear skips scaled_fp8_quant. Skip o_norm on that path so we do not double-norm. Signed-off-by: Rebecca Lee <rebecca.lee@amd.com> Co-authored-by: Cursor <cursoragent@cursor.com>
|
This pull request has merge conflicts that must be resolved before it can be |
|
I think this may be a dup of #52968 |
| @@ -0,0 +1,155 @@ | |||
| # SPDX-License-Identifier: Apache-2.0 | |||
| # SPDX-FileCopyrightText: Copyright contributors to the vLLM project | |||
| """Fused gated RMSNorm + per-token FP8 for Kimi-K3 KDA ``o_proj``. | |||
There was a problem hiding this comment.
can we look at putting this into aiter also if it's not already there?
|
This pull request has merge conflicts that must be resolved before it can be |
| return (xn.to(dtype) * weight.to(dtype)) * torch.sigmoid(gate) | ||
|
|
||
|
|
||
| def rmsnorm_gated_fp8_per_token( |
There was a problem hiding this comment.
Suggestion: should we UT this? I saw the description mentioned a tests/models/kimi_k3/test_amd_kda_oproj_ptpc.py
| ) | ||
| if used_fused_decode: | ||
| x_2d = rearrange(core_attn_out, "1 n h d -> n (h d)") | ||
| q, scale = per_token_fp8_quant(x_2d, fp8_dtype) |
There was a problem hiding this comment.
Question: is there a reason for now using rocm_aiter_ops.per_token_quant here?
| t, heads, h = x.shape | ||
| fp8_max = float(torch.finfo(quant_dtype).max) | ||
| if not _HAS_TRITON or t == 0 or h > 8192: | ||
| normed = _rmsnorm_gated_torch(x, weight, gate, eps).reshape(t, heads * h) |
There was a problem hiding this comment.
Question: Is the fused torch variant better than unfused default impl?
| if isinstance(attn_metadata_raw, dict) | ||
| else None | ||
| ) | ||
| used_fused_decode = bool( |
There was a problem hiding this comment.
Question: is this safe with breakable cudagraphs? or might this condition be misaligned with that inside _forward
Signed-off-by: Rebecca Lee <rebecca.lee@amd.com> # Conflicts: # tests/fusion/test_quant_activation_contract.py # vllm/models/kimi_k3/amd/kda.py
This branch carried its own copy of vllm-project#54248: the three aiter.py input_quant_key() methods, the online/fp8.py QuantizedActivation plumbing, and the contract test's AITER kernel registrations. Those files now come from vllm-project#54248 alone, and this branch keeps only the KDA gated-RMSNorm fusion, inert until vllm-project#54248 lands -- the same dependency that vllm-project#55043 already has. Signed-off-by: Rebecca Lee <rebecca.lee@amd.com> Co-authored-by: Cursor <cursoragent@cursor.com>
Purpose
Depends on #54248 (K3
o_projbecomesFp8PtpcOnlineLinearMethod). Until this lands, this path is a no-op.Kimi-K3 KDA is gated RMSNorm then
o_proj. With PTPC that isFusedRMSNormGatedplus standalone dynamic_per_token_scaled_quant` in the linear. Fuse them in one Triton kernel with per-token amax.Wrap
(fp8, scale)asQuantizedActivation(kFp8DynamicTokenSym)wheno_proj.input_quant_keymatches. Skipo_normon that path so we do not double-norm.fused_kda_decode(#50654) already applied gated RMSNorm on pure non-spec decode. Quantize that output withper_token_fp8_quantso we do not double-norm.Profile
8×MI355X, TP8, Kimi-K3 + DSpark, 50 decode steps. Overlay is
--quantization-configPTPCo_projonly.Kimi-K3 mix in this window: 69 KDA / 24 MLA → 3450 KDA launches (
69 × 50).Unfused
Gated RMSNorm and per-token quant are still two launches.
layer_norm_gated_fwd_kernel.kddynamic_per_token_scaled_quantThe 4650 quant launches are 3450 KDA + 1200 MLA. KDA-only epilogue ≈ 8.5 µs (4.4 + 4.1).
Fused (this PR)
Gated RMSNorm and per-token quant are one launch.
_rmsnorm_gated_fp8_per_token_kernel.kdlayer_norm_gated_fwd_kernel.kddynamic_per_token_scaled_quantKDA epilogue 8.5 → 4.2 µs (−4.3 µs / KDA layer, ~0.30 ms/step × 69 KDA).
Accuracy
8×MI355X, TP8, DSpark MTP (
num_speculative_tokens=2). Same recipe as the fused PTPC KDAo_projpath (this change). Full GSM8K, 1,319 examples,lm_eval5-shot (local-completions). No unfused PTPC pair in this run.Tests
tests/models/kimi_k3/test_amd_kda_oproj_ptpc.py— fused vs sequential;per_token_fp8_quantvs already-normed (fused_kda_decodepath).rmsnorm_gated_fp8_per_tokenmatches sequential gated RMSNorm + per-token amax (scaleexact, dequant atol/rtol 1e-3). Allself.o_norm(...)sites stay behindif not _o_proj_is_ptpc_fp8(...)so PTPC does not double-norm.