Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
815cb99
improve device grouped linear
zhongbozhu Jul 20, 2026
649155b
proper support for grouped bias
zhongbozhu Jul 21, 2026
1e8cda9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 21, 2026
6842f03
fixes and improvements
zhongbozhu Jul 28, 2026
e5090c4
fix unit test failure
zhongbozhu Jul 23, 2026
2369d11
fix group linear UT
zhongbozhu Jul 23, 2026
b781f84
fix group mlp UT by disabling wrong fallback
zhongbozhu Jul 23, 2026
58f3512
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2026
66aae6e
lint
zhongbozhu Jul 23, 2026
1e4b695
fix CI errors
zhongbozhu Aug 5, 2026
28d570a
rename toggle resolve comments
zhongbozhu Jul 25, 2026
79d4de6
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 25, 2026
90e0ad9
don't always set optimize_for_gemm=True
zhongbozhu Jul 25, 2026
a17aac4
test other fp8 recipes on hopper
zhongbozhu Jul 25, 2026
3e91d01
fix test failure
zhongbozhu Jul 25, 2026
5a2a308
relax atol for bf16 sum errors
zhongbozhu Jul 25, 2026
dd31cd6
fix CI
zhongbozhu Jul 28, 2026
de59aae
continue to fix edge cases
zhongbozhu Jul 28, 2026
4f85d44
unify grouped tensor check
zhongbozhu Jul 28, 2026
92a9d6b
special case handling for all empty moe inputs for fp8 CS
zhongbozhu Jul 28, 2026
d1b34aa
add another specific case guard
zhongbozhu Jul 29, 2026
0a7bb60
fix cublas setup meta data issue for empty inputs
zhongbozhu Jul 31, 2026
4e38f4b
mcore integration fixes
zhongbozhu Aug 1, 2026
657bdfb
chore fix after rebase
zhongbozhu Aug 6, 2026
ddddc3f
chore
zhongbozhu Aug 6, 2026
5a948af
chore fix after rebase
zhongbozhu Aug 7, 2026
2657448
resolve comments, enable save original input
zhongbozhu Aug 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
972 changes: 882 additions & 90 deletions tests/pytorch/test_grouped_linear.py

Large diffs are not rendered by default.

56 changes: 38 additions & 18 deletions tests/pytorch/test_grouped_mlp.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from transformer_engine.pytorch.ops.basic.grouped_linear import (
OUTPUT_BUFFER_KEY,
GRAD_INPUT_BUFFER_KEY,
is_op_fuser_grouped_tensor_path_supported,
)
from transformer_engine.pytorch import (
QuantizedTensor,
Expand Down Expand Up @@ -278,6 +279,26 @@ def test_meta_single_grouped_weight_with_delayed_wgrad(self, monkeypatch) -> Non

assert grouped_weight.skip_backward_post_hook

def test_single_grouped_bias_uses_registered_packed_storage(self, monkeypatch) -> None:
"""The grouped bias compute view must alias the registered trainable parent."""
monkeypatch.setenv("NVTE_GROUPED_LINEAR_SINGLE_PARAM", "1")
op = te.ops.GroupedLinear(
2,
128,
128,
bias=True,
device="cuda",
dtype=torch.bfloat16,
single_grouped_bias=True,
)

bias_packed = op._get_packed_bias_tensor(torch.bfloat16)

assert bias_packed.shape == (op.num_groups, op.out_features)
assert bias_packed.untyped_storage().data_ptr() == op.bias.rowwise_data.data_ptr()
assert op.bias.requires_grad
assert dict(op.named_parameters())["bias"] is op.bias

@pytest.mark.parametrize("bias", (False, True))
@pytest.mark.parametrize("dtype", _dtypes)
@pytest.mark.parametrize("quantization", _quantization_list)
Expand Down Expand Up @@ -338,6 +359,16 @@ def test_grouped_linear(

if single_grouped_bias and not bias:
pytest.skip("single_grouped_bias requires bias=True")
recipe = make_recipe(quantization)
compute_recipe = recipe if quantized_compute else None
if (
single_grouped_weight or single_grouped_bias
) and not is_op_fuser_grouped_tensor_path_supported(
compute_recipe,
dtype,
):
# Single grouped parameters intentionally have no split-quantize fallback.
pytest.skip("Single grouped parameters require the native grouped-tensor path")
if single_grouped_weight and quantized_weight and quantization in ("fp8_delayed_scaling"):
pytest.skip(
"single_grouped_weight does not support FP8 delayed scaling "
Expand Down Expand Up @@ -393,7 +424,6 @@ def test_grouped_linear(
y_ref.backward(dy_ref)

# Construct fusible operation
recipe = make_recipe(quantization)
with te.quantized_model_init(enabled=quantized_weight, recipe=recipe):
op = te.ops.GroupedLinear(
group_size,
Expand Down Expand Up @@ -707,22 +737,6 @@ def test_grouped_linear_cuda_graph_safe(
"single_grouped_weight/single_grouped_bias requires"
" NVTE_GROUPED_LINEAR_SINGLE_PARAM=1"
)
device_capability = torch.cuda.get_device_capability()
if device_capability < (9, 0):
pytest.skip(
"Grouped GEMM CUDA-graph-safe path requires Hopper (SM90) or Blackwell (SM100+)"
)
# BF16/FP16 and FP8 per-tensor current scaling run on the Hopper grouped GEMM path,
# but MXFP8/NVFP4 grouped quantization kernels require Blackwell (SM100+).
requires_blackwell = quantization is not None and quantization != "fp8_current_scaling"
if requires_blackwell and device_capability < (10, 0):
pytest.skip("MXFP8/NVFP4 grouped GEMM CUDA-graph-safe path requires SM100+ (Blackwell)")
# Grouped GEMM on Hopper requires cuBLAS 13.4+; Blackwell requires cuBLAS 13.3+.
cublaslt_version = tex.get_cublasLt_version()
if device_capability < (10, 0) and cublaslt_version < 130400:
pytest.skip("Grouped GEMM on Hopper requires cuBLAS 13.4+.")
if cublaslt_version < 130300:
pytest.skip("Grouped GEMM requires cuBLAS 13.3+.")
if quantization is None and quantized_weight:
pytest.skip("quantized_weight requires a quantization recipe")
if (
Expand All @@ -740,6 +754,13 @@ def test_grouped_linear_cuda_graph_safe(
"only discrete weights (single_grouped_weight=False) are supported."
)

recipe = make_recipe(quantization)
if not is_op_fuser_grouped_tensor_path_supported(
recipe,
dtype,
):
pytest.skip("Configuration falls back to the non-CUDA-graph-safe path")

single_grouped_bias = bias and single_grouped_weight

# Split sizes (statically pinned for graph capture)
Expand All @@ -752,7 +773,6 @@ def test_grouped_linear_cuda_graph_safe(
in_shape = (num_active_tokens + token_padding, in_features)
out_shape = (in_shape[0], out_features)

recipe = make_recipe(quantization)
with te.quantized_model_init(enabled=quantized_weight, recipe=recipe):
op = te.ops.GroupedLinear(
group_size,
Expand Down
Loading
Loading