Activation + GroupedLinear Fusion for MOE#3238
Conversation
Signed-off-by: Varun Thumbe <vthumbe@nvidia.com>
for more information, see https://pre-commit.ci
Greptile SummaryThis PR adds a fused
Confidence Score: 4/5Safe to merge for standard full-training runs; the new fused path has an untested crash for partially-frozen MoE configurations. The fused forward and backward kernels are correct for the common training case where all ops have requires_grad=True. However, BackwardScaledActivationGroupedLinear.fuser_backward unconditionally reads linear_ctx.saved_tensors[0] regardless of whether fc1's context actually saved anything. When fc1 weights are frozen but the per-row scales are trainable, the TE fuser still enters the fused backward, hits a NoneType subscript error, and crashes. This is a real failure mode in fine-tuning scenarios and is not covered by any test. transformer_engine/pytorch/ops/fused/backward_activation_grouped_linear.py — the fuser_backward method needs a guard around the linear_ctx.saved_tensors access when linear_ctx.requires_grad is False. Important Files Changed
Sequence DiagramsequenceDiagram
participant Fuser
participant ForwardSAGL as ForwardScaledActivationGroupedLinear
participant tex as tex (C++ kernels)
participant GroupedLinear as GroupedLinear._fuser_forward_grouped_tensor
Note over Fuser: Forward pass (activation→fc2 fused)
Fuser->>ForwardSAGL: fuser_forward(input_, scales, split_sizes)
ForwardSAGL->>tex: grouped_scaled_swiglu/srelu(x, scales, quantizer, split_sizes)
tex-->>ForwardSAGL: grouped_x (quantized activation output)
ForwardSAGL->>GroupedLinear: _fuser_forward_grouped_tensor(grouped_x, ...)
GroupedLinear-->>ForwardSAGL: (out, tensors_to_save)
ForwardSAGL->>ForwardSAGL: save_for_backward(input_, scales) on activation_ctx
ForwardSAGL-->>Fuser: out
Note over Fuser: Backward pass (fc1 backward fused with activation backward)
Fuser->>Fuser: GroupedLinear(fc2).fuser_backward(dL/dfc2_out)
Note over Fuser: Returns dL/d(activation_out * scales) as grad_output
participant BackwardSAGL as BackwardScaledActivationGroupedLinear
Fuser->>BackwardSAGL: fuser_backward(dL/d_activation_out)
BackwardSAGL->>tex: grouped_scaled_dswiglu/dsrelu(grad, input_, scales, quantizer)
tex-->>BackwardSAGL: (grouped_dy, dense_dy, grad_scales)
BackwardSAGL->>GroupedLinear: _fuser_backward_grouped_tensor(fc1_ctx, dense_dy, grouped_dy)
GroupedLinear-->>BackwardSAGL: (dL/dfc1_input, wgrad_fc1, ...)
BackwardSAGL-->>Fuser: (grad_input, grad_params, grad_extra_inputs)
Reviews (2): Last reviewed commit: "[pre-commit.ci] auto fixes from pre-comm..." | Re-trigger Greptile |
Signed-off-by: Varun Thumbe <vthumbe@nvidia.com>
for more information, see https://pre-commit.ci
| scales = maybe_dequantize(scales, activation_ctx.dtype) | ||
| grad_output = maybe_dequantize(grad_output, activation_ctx.dtype) | ||
|
|
||
| split_sizes = linear_ctx.saved_tensors[0] |
There was a problem hiding this comment.
Crash when fc1 is frozen but activation scales are trainable
linear_ctx.saved_tensors is None whenever linear_ctx.requires_grad=False, because fuser_forward_save_ctx returns early (if not requires_grad[0]: return) without ever calling save_for_backward. The backward loop only skips this fused op when all of its basic-op contexts have requires_grad=False; when fc1 is frozen (so first_op_requiring_backward = idx_of_activation) but the per-row scales are trainable, fc1's context has requires_grad=False while the activation context has requires_grad=True. The loop therefore enters fuser_backward, which unconditionally does linear_ctx.saved_tensors[0], raising TypeError: 'NoneType' object is not subscriptable.
A concrete path: MoE fine-tuning where fc1 weights are frozen, the module input is a non-leaf tensor, and the scales (activation extra input) carry requires_grad=True. The fix is either to guard the access with if linear_ctx.requires_grad: and skip the linear backward when fc1 doesn't need it, or to save split_sizes directly on activation_ctx so the offset computation does not depend on linear_ctx.saved_tensors.
Description
Please include a brief summary of the changes, relevant motivation and context.
Fixes # (issue)
Type of change
Changes
Please list the changes introduced in this PR:
Checklist: