Skip to content

[Pytorch] Add support for row-wise quanted input for grouped gemm#3244

Draft
YangFei1990 wants to merge 2 commits into
NVIDIA:mainfrom
YangFei1990:mxfp8_input_groupedgemm
Draft

[Pytorch] Add support for row-wise quanted input for grouped gemm#3244
YangFei1990 wants to merge 2 commits into
NVIDIA:mainfrom
YangFei1990:mxfp8_input_groupedgemm

Conversation

@YangFei1990

Copy link
Copy Markdown
Collaborator

Description

To support the NCCL EP FP8 dispatch, this PR introduce a capability to allow grouped gemm to take input that is already quantized in row-wise. We directly pass the row-wise quantized for forward grouped gemm and dequant + requant with col-wise to save for backward.

Fixes # (issue)

Type of change

  • Documentation change (change only to the documentation, either a fix or a new content)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Infra/Build change
  • Code refactoring

Checklist:

  • I have read and followed the contributing guidelines
  • The functionality is complete
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Signed-off-by: YangFei1990 <feiw@nvidia.com>
@YangFei1990
YangFei1990 requested a review from phu0ngng July 23, 2026 18:28
Comment on lines +1309 to +1310
and isinstance(input_quantizers[0], MXFP8Quantizer)
and isinstance(input_.quantizer, MXFP8Quantizer)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we also assert input_quantizers[0] == input_.quantizer?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I think == comparison is too strict. It will compare all value fields, I think things like columnwise_usage or optimize_for_gemm could mismatch? Maybe we should explicit assert dype to be E4M3? But let me know if the dispatch output tensor's quantizer can match all value fields.

with_columnwise: bool,
tensor_offsets: Optional[torch.Tensor] = None,
) -> None:
"""Prepare a rowwise-only MXFP8 grouped input for grouped GEMM (in place).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks like this helper actually "prepares" colwise besides rowwise. I think we should make the function name and docstring clearer and more consistent.

format; they are converted to the GEMM-swizzled layout afterwards.
TODO: optimize and fuse the round-trips requant
"""
if grouped_x.rowwise_data is None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we validate grouped_x.rowwise_scale as well?

raise ValueError("Pre-quantized MXFP8 grouped input is missing rowwise data.")
if grouped_x._with_gemm_swizzled_scales:
raise NotImplementedError(
"Pre-quantized MXFP8 grouped input must have scales in compact format."

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

compact -> unswizzled.

Comment on lines +175 to +178
scale_shape = (
round_up_to_nearest_multiple(total_tokens, 128),
round_up_to_nearest_multiple(cols // 32, 4),
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do we need to do this while we already have 128 per-expert-alignment in Dispatch? The total tokens should already be divisible by 128.

For hidden size, there will be an assertion in Dispatch to expect % 512 = 0.

Here, I think we can add assertions instead.

@phu0ngng
phu0ngng requested a review from vthumbe1503 July 23, 2026 20:42

def prepare_prequantized_mxfp8_grouped_input(
grouped_x: GroupedTensorStorage,
quantizer: MXFP8Quantizer,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Actually, is there a GroupedQuantizer in TE/PyT? If so, we probably need to use it instead.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I do not see a GroupedQuantizer in Pytorch. I see what used is tex.group_quantize. Let me know if I missed it. Also can you help me understand the benefit of GroupedQuantizer and how it compared with current Pytorch approach?

Signed-off-by: YangFei1990 <feiw@nvidia.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.

2 participants