Skip to content

feat: MLA prefill NVFP4 fused output - #8

Open
carlyou wants to merge 4 commits into
feat--fa4-pergroup-fp8-outputfrom
feat--fa4-nvfp4-output
Open

feat: MLA prefill NVFP4 fused output#8
carlyou wants to merge 4 commits into
feat--fa4-pergroup-fp8-outputfrom
feat--fa4-nvfp4-output

Conversation

@carlyou

@carlyou carlyou commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Wire FA4's fused NVFP4 output into the MLA prefill path: when the o_proj input quant is kNvfp4Dynamic, forward_mha passes the packed-e2m1 output buffer, the global scale, and the 128x4-swizzled e4m3 block-scale buffer straight to flash-attention, eliminating the standalone scaled_fp4_quant kernel. FA writes the swizzled scale-factor layout consumed by the cutlass/flashinfer NVFP4 GEMMs directly.

Fusion is gated to pure-prefill batches: the swizzled buffer's 128-row tiles cannot be split between FA (prefill tokens) and the separate decode-token post-quant.

Purpose

Test Plan

Test Result


Essential Elements of an Effective PR Description Checklist
  • The purpose of the PR, such as "Fix some issue (link existing issues this PR will resolve)".
  • The test plan, such as providing test command.
  • The test results, such as pasting the results comparison before and after, or e2e results
  • (Optional) The necessary documentation update, such as updating supported_models.md and examples for a new model.

Wire FA4's fused NVFP4 output into the MLA prefill path: when the o_proj
input quant is kNvfp4Dynamic, forward_mha passes the packed-e2m1 output
buffer, the global scale, and the 128x4-swizzled e4m3 block-scale buffer
straight to flash-attention, eliminating the standalone scaled_fp4_quant
kernel. FA writes the swizzled scale-factor layout consumed by the
cutlass/flashinfer NVFP4 GEMMs directly.

Fusion is gated to pure-prefill batches: the swizzled buffer's 128-row
tiles cannot be split between FA (prefill tokens) and the separate
decode-token post-quant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Carl You <4531192+carlyou@users.noreply.github.com>
Comment on lines +2337 to +2344
(
# NVFP4: packed e2m1 codes, two per byte.
output.view(torch.float4_e2m1fn_x2).view(
-1, self.num_heads, self.v_head_dim // 2
)
if is_nvfp4
else output.view(-1, self.num_heads, self.v_head_dim)
)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

define a variable instead putting this inline.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Hoisted into a named fused_out (and fused_out_scales alongside it) in 7ae76c6.

Comment thread vllm/model_executor/layers/attention/mla_attention.py
Comment on lines 731 to 736
output_scales=(
mha_output_scales[num_mqa_tokens:num_actual_toks]
mha_output_scales
if quant_key == kNvfp4Dynamic
else mha_output_scales[num_mqa_tokens:num_actual_toks]
if mha_output_scales is not None
else None

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

define a variable above for better readibility

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Hoisted the slicing into the mha_output_scales assignment in 7ae76c6. mypy also caught that the hoisted version would have sliced None for static FP8 - guarded.

carlyou and others added 2 commits July 7, 2026 00:17
Name the fused out/scales views instead of inlining them in the
forward_mha call, and derive is_nvfp4 from _detect_output_quant_key
rather than dtype-sniffing the scales buffer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Carl You <4531192+carlyou@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Carl You <4531192+carlyou@users.noreply.github.com>
and attn_metadata.prefill.chunked_context is None
and self.impl.dcp_world_size <= 1
and (not is_pergroup or pergroup_layout_ok)
and nvfp4_ok

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

put quant_key != kNvfp4Dynamic or num_mqa_tokens == 0 inline here.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Inlined in 79f55c4 (comment moved onto the conjunct).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Carl You <4531192+carlyou@users.noreply.github.com>
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.

1 participant