Improve device-init grouped linear module with single grouped weight support - #3224
Improve device-init grouped linear module with single grouped weight support #3224zhongbozhu wants to merge 21 commits into
Conversation
aa3b9d1 to
47ba66a
Compare
ff7eee2 to
a43f70f
Compare
6536aa1 to
1169d6e
Compare
| is_grad_enabled = torch.is_grad_enabled() | ||
| num_gemms = self.num_gemms | ||
|
|
||
| if FP8GlobalStateManager.fp8_graph_capturing(): |
There was a problem hiding this comment.
Note: this code block was deleted because it was duplicated
|
/te-ci pytorch |
Greptile SummaryThis PR improves the device-init grouped linear module by adding full single grouped weight/bias support restricted to the grouped tensor API, fixing numerical correctness issues where the old code allowed the single-weight path to silently fall through to the incompatible split-quantize path.
Confidence Score: 4/5Safe to merge with one minor concern about an implicit divisibility assumption in the MXFP8 kernel. The PR is a well-scoped correctness fix with extensive new test coverage (8+ new tests). The numerical correctness issues it addresses — silent fall-through to the split-quantize path, zero-row null-pointer crash, and incorrect MXFP8 column-wise scale strides — are all properly fixed. The only remaining concern is the integer division first_logical_dim / num_tensors in the MXFP8 kernel which lacks a divisibility assertion; in practice the grouped linear module always creates same-shape experts so this is unlikely to trigger, but it is a latent silent-correctness hazard. Files Needing Attention: transformer_engine/common/cast/mxfp8/group_quantize_mxfp8.cuh — the new tensor_rows_for_scales calculation lacks a divisibility guard. Important Files Changed
Sequence DiagramsequenceDiagram
participant User as Caller
participant GL_mod as GroupedLinear (module)
participant GL_ops as GroupedLinear (ops)
participant PrepW as _prepare_weights_for_grouped_tensor_gemm
participant GQ as group_quantize (C++ ext)
participant GEMM as grouped_gemm kernel
participant BiasAdd as launch_grouped_bias_add
User->>GL_mod: forward(inp, m_splits, single_grouped_weight)
GL_mod->>GL_mod: validate single_grouped_weight requires use_grouped_tensor
GL_mod->>GL_ops: fuser_forward(...)
GL_ops->>GL_ops: check is_op_fuser_grouped_tensor_path_supported()
alt "single_grouped_weight=True"
GL_ops->>PrepW: "_get_grouped_weight_for_gemm(single=True)"
PrepW->>GQ: "group_quantize(..., output=cached_workspace)"
GQ-->>PrepW: GroupedTensor (quantized, in-place reuse)
else discrete weights
GL_ops->>PrepW: "_prepare_weights_for_grouped_tensor_gemm(single=False)"
PrepW->>GQ: group_quantize(weight_i...)
GQ-->>PrepW: GroupedTensor
end
PrepW-->>GL_ops: grouped weight tensor
GL_ops->>GEMM: general_grouped_gemm_for_grouped_tensor(...)
GEMM-->>GL_ops: output activations
GL_ops->>BiasAdd: launch_grouped_bias_add(...)
Note over BiasAdd: early-return if total_rows==0
BiasAdd-->>GL_ops: biased output
GL_ops-->>GL_mod: output
GL_mod-->>User: output
User->>GL_mod: backward(grad_output)
GL_mod->>GL_ops: fuser_backward(...)
alt "single_grouped_weight=True"
GL_ops->>GL_ops: compute wgrad (single grouped)
GL_ops->>GL_mod: grad_weights (stacked or rowwise_data view)
GL_mod->>GL_mod: set self.weight.grad
else discrete weights
GL_ops->>GL_mod: grad_weights list
GL_mod->>GL_mod: set weight_i.grad for each expert
end
GL_ops-->>GL_mod: (dinp, dweights, dbiases)
GL_mod-->>User: dinput
Reviews (20): Last reviewed commit: "add another specific case guard" | Re-trigger Greptile |
There was a problem hiding this comment.
The biggest change in this PR is that TE is abandoning any attempt to make single_grouped_weight=True a general feature. Things must be exactly right, or we crash. Given how delicate and experimental this feature has been, I'm not opposed.
The second change is that users must opt-in to access the grouped GEMM kernel. This is also reasonable, since it has alignment requirements for m_splits and it's helpful having a way for users to accept that stricter contract.
We are experiencing many test failures. Given that single_grouped_weight is no longer a general feature, I think it's reasonable we move the corresponding tests to test_grouped_linear.py and test_grouped_mlp.py.
| raise ValueError( | ||
| "The native grouped_tensor path requires CUDA m_splits. Pass a CUDA int64 " | ||
| "tensor, or select grouped_gemm_backend='legacy'." | ||
| ) |
There was a problem hiding this comment.
I get that the h2d memcpy is suboptimal, but it's trivially easy to handle. Erroring out seems excessively rigid.
| raise ValueError( | |
| "The native grouped_tensor path requires CUDA m_splits. Pass a CUDA int64 " | |
| "tensor, or select grouped_gemm_backend='legacy'." | |
| ) | |
| m_splits = m_splits.to(device=device) |
We need to handle the d2h case anyways when the user has specified grouped_gemm_backend="grouped_tensor", but it's not supported and we fallback to split-quantize.
There was a problem hiding this comment.
But if the alignment is not provided in the first place, converting it to a device tensor also wouldn't work right, I am okay with another alignment check before adding this H2D copy.
b6a9482 to
25314b8
Compare
|
/te-ci pytorch |
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com> # Conflicts: # tests/pytorch/test_grouped_mlp.py
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
for more information, see https://pre-commit.ci
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
Signed-off-by: zhongboz <zhongboz@nvidia.com>
Signed-off-by: zhongboz <zhongboz@nvidia.com>
07b2f18 to
bb6c1b9
Compare
|
/te-ci pytorch |
| : tensor_base; | ||
| size_t tensor_base_for_scales = tensor_base; | ||
| size_t tensor_rows_for_scales = rows; | ||
| if constexpr (WITH_GEMM_SWIZZLED_SCALES && SHAPE_REP == ShapeRepresentation::SAME_BOTH_DIMS) { |
There was a problem hiding this comment.
Note: this is for single weight quantize for mxfp8.
Before this change, the weight quantizer didn't have the first_dims because moe weights are uniform shape for both dimension. This will then trigger a CUDA illegal access because offsets_ptr=nullptr
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
71a29ba to
13c60fb
Compare
Signed-off-by: zhongboz <zhongboz@nvidia.com>
2734746 to
5fc5db7
Compare
|
/te-ci pytorch |
Signed-off-by: Zhongbo Zhu <zhongboz@nvidia.com>
Signed-off-by: zhongboz <zhongboz@nvidia.com>
|
/te-ci pytorch |
Description
Fixes numerical issues when using single weight for TE module grouped linear. Limit the single weight feature to the grouped tensor API instead of the legacy path.
TODO: test E2E convergence, unit test directly from Mcore.
Note: needs to pay extra attention to whether bias grad and weight grad are generated properly.
Type of change
Changes
Please list the changes introduced in this PR:
Checklist: