Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
b6f684d
Refine the support for D=256 on Blackwell server type GPUs
KshitijLakhani May 28, 2026
c03dcbb
Add deterministic tests for D=256 for sm10.x
KshitijLakhani May 28, 2026
91f8f1f
Test clean up
KshitijLakhani May 28, 2026
15f439e
Add PyT side tests for D=256 cuDNN fused attn on SM100-110
KshitijLakhani May 28, 2026
7cbe3c5
Refine the PyT D=256 tests
KshitijLakhani May 28, 2026
c364e32
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 28, 2026
e401e23
Fix the filtering condition for bias type for D=256 on sm10x for cudn…
KshitijLakhani May 29, 2026
7225c92
Code clean up
KshitijLakhani May 29, 2026
ebf8763
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 29, 2026
70f6e8a
Switching test check logic around
KshitijLakhani Jun 3, 2026
8f51016
Add THD xfail marked tests for testing
KshitijLakhani Jun 3, 2026
4482156
Fix the jax test bias condition fo skipping for D=256
KshitijLakhani Jun 5, 2026
0194673
nit: Fix comment
KshitijLakhani Jun 5, 2026
2184724
Move the D=256 changes so as to follow an order of increasing cuDNN v…
KshitijLakhani Jun 5, 2026
11bb897
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jun 5, 2026
337d035
Add support for D=256 THD in TE
KshitijLakhani Jul 1, 2026
6bb6f01
Add TE JAX CP test support to verify D=256 for AG and Ring
KshitijLakhani Jul 8, 2026
2bcd55f
Add PyTorch D256 CP tests
KshitijLakhani Jul 8, 2026
28af36f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 8, 2026
56738ea
nit: clean up comments
KshitijLakhani Jul 8, 2026
719449d
Correct the atgs passed to test dpa
KshitijLakhani Jul 21, 2026
55a884f
Simplify THD fused attention layout check
KshitijLakhani Jul 22, 2026
926a80a
Rename PyTorch D256 fused attention tests
KshitijLakhani Jul 22, 2026
ae016d1
Run JAX fused attention before softmax
KshitijLakhani Jul 22, 2026
c0c7752
Relabel THD D256 cuDNN guard to 9.25
KshitijLakhani Jul 22, 2026
2fd7206
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 23, 2026
e11c2b5
Fold D256 PyTorch CP tests
KshitijLakhani Jul 25, 2026
205dcd3
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 27, 2026
2c65a61
Rename D256 PyTorch attention tests
KshitijLakhani Jul 27, 2026
bfe62ea
Remove D256 PyTorch attention param ids
KshitijLakhani Jul 27, 2026
f61ef61
Disable FA4 D256 SWA on SM100
KshitijLakhani Jul 29, 2026
72958ee
Fix FA4 D256 packed QKV handling
KshitijLakhani Jul 30, 2026
41a3c17
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jul 30, 2026
bca22ba
Use is_training in DPA test helper
KshitijLakhani Jul 31, 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
6 changes: 3 additions & 3 deletions qa/L1_jax_distributed_unittest/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ python3 -m pytest -c $TE_PATH/tests/jax/pytest.ini -v --junitxml=$XML_LOG_DIR/py

python3 -m pytest -c $TE_PATH/tests/jax/pytest.ini -v --junitxml=$XML_LOG_DIR/pytest_dist_mlp.xml $TE_PATH/tests/jax/test_distributed_layernorm_mlp.py || test_fail "test_distributed_layernorm_mlp.py"

python3 -m pytest -c $TE_PATH/tests/jax/pytest.ini -v --junitxml=$XML_LOG_DIR/pytest_dist_fused_attn.xml $TE_PATH/tests/jax/test_distributed_fused_attn.py || test_fail "test_distributed_fused_attn.py"

# XLA_FLAGS to WAR for test_distributed_softmax issue with NCCL
# TODO(Kshitij): remove when NCCL issue is fixed
# TODO(KshitijLakhani): remove when NCCL issue is fixed
XLA_FLAGS="$XLA_FLAGS --xla_gpu_enable_nccl_comm_splitting=false" python3 -m pytest -c $TE_PATH/tests/jax/pytest.ini -v --junitxml=$XML_LOG_DIR/pytest_dist_softmax.xml $TE_PATH/tests/jax/test_distributed_softmax.py || test_fail "test_distributed_softmax.py"

python3 -m pytest -c $TE_PATH/tests/jax/pytest.ini -v --junitxml=$XML_LOG_DIR/pytest_dist_fused_attn.xml $TE_PATH/tests/jax/test_distributed_fused_attn.py || test_fail "test_distributed_fused_attn.py"

# NCCL EP multi-process suite. Self-skips on <4 GPUs.
TE_PATH=$TE_PATH bash $TE_PATH/tests/jax/multi_process_launch_ep.sh || test_fail "test_multi_process_ep.py"

Expand Down
167 changes: 167 additions & 0 deletions tests/jax/test_distributed_fused_attn.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
_has_cudnn_frontend_python,
)
from utils import pytest_parametrize_wrapper
from transformer_engine_jax import get_cudnn_version, get_device_compute_capability
from transformer_engine.jax.attention import (
is_fused_attn_kernel_available,
AttnBiasType,
Expand Down Expand Up @@ -345,6 +346,59 @@ def test_softcap_score_mod_with_aux_params_backward(
pytest.param([4, 256, 16, 64], id="4-256xCPx2-16-64"),
]

DISTRIBUTED_CONTEXT_SELF_ATTN_D256_DATA_SHAPES = {
"L0": [],
"L1": [[2, 128, 16, 256]],
"L2": [],
}

# Keep these as explicit tuples instead of independent layout/mask/window as:
# BSHD CP uses CAUSAL_MASK, THD CP uses PADDING_CAUSAL_MASK, SWA is
# only valid for THD, and stripe_size behavior is different for
# BSHD vs THD in these tests. Splitting the axes would mostly add
# invalid BSHD+SWA and THD+CAUSAL combinations that fail or skip.
DISTRIBUTED_CONTEXT_SELF_ATTN_D256_LAYOUTS_MASKS_WINDOWS = [
# BSHD with different layouts, but same causal mask and no sliding window
pytest.param(
QKVLayout.BSHD_BS2HD,
AttnMaskType.CAUSAL_MASK,
(-1, -1),
id="BSHD_KVPACKED-CAUSAL-NO_SWA",
),
pytest.param(
QKVLayout.BSHD_BSHD_BSHD,
AttnMaskType.CAUSAL_MASK,
(-1, -1),
id="BSHD_SEPARATE-CAUSAL-NO_SWA",
),
# THD with different sliding window sizes, but same packed layout and padding causal mask
pytest.param(
QKVLayout.THD_T2HD,
AttnMaskType.PADDING_CAUSAL_MASK,
(-1, -1),
id="THD_KVPACKED-PADDING_CAUSAL-NO_SWA",
),
pytest.param(
QKVLayout.THD_T2HD,
AttnMaskType.PADDING_CAUSAL_MASK,
(20, 0),
id="THD_KVPACKED-PADDING_CAUSAL-SWA",
),
# THD with different sliding window sizes, but same separate layout and padding causal mask
pytest.param(
QKVLayout.THD_THD_THD,
AttnMaskType.PADDING_CAUSAL_MASK,
(-1, -1),
id="THD_SEPARATE-PADDING_CAUSAL-NO_SWA",
),
pytest.param(
QKVLayout.THD_THD_THD,
AttnMaskType.PADDING_CAUSAL_MASK,
(20, 0),
id="THD_SEPARATE-PADDING_CAUSAL-SWA",
),
]


class TestDistributedContextParallelSelfAttn:
# TODO(KshitijLakhani): parametrize num_segments_per_seq for all CP tests
Expand Down Expand Up @@ -638,6 +692,119 @@ def test_context_parallel_ring_attn(
stripe_size=stripe_size,
)

# CP ring and all-gather tests for D=256
# TODO(KshitijLakhani): Replace this with common-provided fused-attn disable reasons once
# they can be surfaced to framework tests.
@staticmethod
def skip_if_d256_cp_unsupported(qkv_layout):
compute_capability = get_device_compute_capability(0)
if not 100 <= compute_capability < 110:
pytest.skip("D=256 CP fused attention is only enabled on Blackwell server GPUs.")

required_cudnn_version = 92500 if qkv_layout.is_thd() else 92300
required_cudnn_version_label = "9.25" if qkv_layout.is_thd() else "9.23"
if get_cudnn_version() < required_cudnn_version:
pytest.skip(
f"D=256 CP fused attention with {qkv_layout} requires cuDNN"
f" {required_cudnn_version_label} or newer."
)

@pytest_parametrize_wrapper(
"device_count,mesh_shape,mesh_axes,mesh_resource",
generate_context_parallel_configs_for_attn(),
)
@pytest_parametrize_wrapper(
"data_shape",
DISTRIBUTED_CONTEXT_SELF_ATTN_D256_DATA_SHAPES,
)
@pytest.mark.parametrize(
"dtype",
[pytest.param(jnp.float16, id="FP16"), pytest.param(jnp.bfloat16, id="BF16")],
)
@pytest.mark.parametrize(
"qkv_layout, attn_mask_type, window_size",
DISTRIBUTED_CONTEXT_SELF_ATTN_D256_LAYOUTS_MASKS_WINDOWS,
)
def test_context_parallel_ring_attn_d256(
self,
device_count,
mesh_shape,
mesh_axes,
mesh_resource,
data_shape,
dtype,
qkv_layout,
attn_mask_type,
window_size,
):
"""D=256 CP ring coverage."""
self.skip_if_d256_cp_unsupported(qkv_layout)

self.impl_test_context_parallel_attn(
device_count,
mesh_shape,
mesh_axes,
mesh_resource,
data_shape,
1,
attn_mask_type,
dtype,
qkv_layout,
True,
CPStrategy.RING,
use_scan_ring=False,
window_size=window_size,
stripe_size=1 if qkv_layout.is_thd() else None,
)

@pytest_parametrize_wrapper(
"device_count,mesh_shape,mesh_axes,mesh_resource",
generate_context_parallel_configs_for_attn(),
)
@pytest_parametrize_wrapper(
"data_shape",
DISTRIBUTED_CONTEXT_SELF_ATTN_D256_DATA_SHAPES,
)
@pytest.mark.parametrize(
"dtype",
[pytest.param(jnp.float16, id="FP16"), pytest.param(jnp.bfloat16, id="BF16")],
)
@pytest.mark.parametrize(
"qkv_layout, attn_mask_type, window_size",
DISTRIBUTED_CONTEXT_SELF_ATTN_D256_LAYOUTS_MASKS_WINDOWS,
)
def test_context_parallel_allgather_attn_d256(
self,
device_count,
mesh_shape,
mesh_axes,
mesh_resource,
data_shape,
dtype,
qkv_layout,
attn_mask_type,
window_size,
):
"""D=256 CP all-gather coverage."""
self.skip_if_d256_cp_unsupported(qkv_layout)

self.impl_test_context_parallel_attn(
device_count,
mesh_shape,
mesh_axes,
mesh_resource,
data_shape,
1,
attn_mask_type,
dtype,
qkv_layout,
True,
CPStrategy.ALL_GATHER,
window_size=window_size,
stripe_size=128 if qkv_layout.is_thd() else None,
num_segments_per_seq=5 if qkv_layout.is_thd() else None,
)


REORDER_CAUSAL_LOAD_BALANCING_DATA_SHAPES = {
"L0": [[]],
Expand Down
85 changes: 81 additions & 4 deletions tests/jax/test_fused_attn.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@ def _get_max_segments_per_sequence(self):
return 1

def _check_configs(self):
# TODO(rewang): probably adds this in is_fused_attn_available
# TODO(KshitijLakhani): probably add/move this to is_fused_attn_available
if self.qkv_layout.is_thd() and not self.attn_mask_type.is_padding():
pytest.skip("THD format requires padding masks.")

Expand All @@ -493,11 +493,62 @@ def _check_configs(self):
pytest.skip(
"seqlen_q > seqlen_kv is not supported with sliding window attention in cuDNN"
)
compute_capability = get_device_compute_capability(0)
cudnn_version = get_cudnn_version()
# D=256 bprop on SM10x uses the deterministic algorithm path only. BSHD support
# starts with cuDNN FE 1.24 / BE 9.23; THD execution-plan support starts with
# cuDNN FE 1.26 / BE 9.25. The kernel rejects dBias, dropout, and ALiBi, supports vanilla
# softmax only, and allows SWA together with a causal mask only.
is_sm10x = 100 <= compute_capability < 110
if self.is_training and is_sm10x and (self.head_dim_qk == 256 or self.head_dim_v == 256):
Comment thread
cyanguwa marked this conversation as resolved.
if self.head_dim_qk != 256 or self.head_dim_v != 256:
pytest.skip(
"D=256 BWD on Blackwell only supports d_qk == d_v == 256;"
f" got d_qk={self.head_dim_qk}, d_v={self.head_dim_v}."
)
required_cudnn_version = 92500 if self.qkv_layout.is_thd() else 92300
required_cudnn_version_label = "9.25" if self.qkv_layout.is_thd() else "9.23"
if cudnn_version < required_cudnn_version:
pytest.skip(
f"D=256 BWD on Blackwell with {self.qkv_layout} requires cuDNN"
f" {required_cudnn_version_label} or newer; got cuDNN {cudnn_version}."
)
# TODO(KshitijLakhani): cuDNN FE can model bias input separately from dBias,
# but TE does not yet plumb whether dBias is requested into the common backend selector.
# Until that distinction is available, the D=256 SM10x gate requires no bias.
Comment thread
cyanguwa marked this conversation as resolved.
unsupported = None
if self.attn_bias_type == AttnBiasType.PRE_SCALE_BIAS:
unsupported = "pre-scale bias"
elif self.attn_bias_type != AttnBiasType.NO_BIAS:
unsupported = (
"post-scale bias in TE's D=256 backend gate; bias-input-only"
" support needs TE to distinguish between bias input and dBias"
)
elif self.dropout_prob != 0.0:
unsupported = "dropout"
elif self.softmax_type != AttnSoftmaxType.VANILLA_SOFTMAX:
unsupported = "non-vanilla softmax"
if unsupported is not None:
pytest.skip(
"D=256 BWD on Blackwell uses the deterministic SM100 D=256 SDPA BWD"
f" kernel which does not support {unsupported}."
)
if self.window_size is not None and self.window_size != (-1, -1):
if not self.attn_mask_type.is_causal():
pytest.skip(
"D=256 BWD on Blackwell uses the SM100 D=256 SDPA BWD kernel"
" which requires window_size=(-1, -1) for non-causal masks."
)
if self.window_size[1] not in (-1, 0):
pytest.skip(
"D=256 BWD on Blackwell only supports right window -1 or 0"
" for causal masks."
)

Comment thread
cyanguwa marked this conversation as resolved.
if get_device_compute_capability(0) >= 100 and self.is_training:
if compute_capability >= 100 and self.is_training:
if FusedAttnHelper.is_non_deterministic_allowed() and (
(self.dropout_prob != 0.0 and self.attn_bias_type != AttnBiasType.NO_BIAS)
or get_cudnn_version() < 90700
or cudnn_version < 90700
):
pytest.skip(
"For sm100+, non-deterministic bprop (cuDNN 9.7+) does not support bias with"
Expand All @@ -506,7 +557,7 @@ def _check_configs(self):
if not FusedAttnHelper.is_non_deterministic_allowed() and (
self.dropout_prob != 0.0
or self.attn_bias_type != AttnBiasType.NO_BIAS
or get_cudnn_version() < 91801
or cudnn_version < 91801
):
pytest.skip(
"For sm100+, deterministic bprop (cuDNN 9.18.1+) does not support bias or"
Expand Down Expand Up @@ -1642,6 +1693,32 @@ def test_backward(
QKVLayout.THD_THD_THD,
id="2-1024-2048-12-6-128-64-BF16-CROSS-GQA-RAGGED_SEPARATE",
),
# D=256 deterministic backward on the SM100 dedicated SDPA bprop kernel.
# BSHD requires cuDNN FE 1.24 / BE 9.23+; THD requires cuDNN FE 1.26 / BE 9.25+.
pytest.param(
4,
128,
128,
16,
16,
256,
256,
jnp.float16,
QKVLayout.BSHD_BS2HD,
id="4-128-128-16-16-256-256-FP16-SELF-KV_PACKED",
),
pytest.param(
4,
128,
128,
16,
16,
256,
256,
jnp.float16,
QKVLayout.THD_T2HD,
id="4-128-128-16-16-256-256-FP16-SELF-RAGGED_KV_PACKED",
),
],
)
@pytest.mark.parametrize(
Expand Down
10 changes: 8 additions & 2 deletions tests/pytorch/attention/run_attention_with_cp.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
from transformer_engine.pytorch.attention.dot_product_attention.utils import combine_and_quantize
import transformer_engine_torch as tex
from transformer_engine.pytorch import DType
from test_attention_with_cp import model_configs_flash_attn, model_configs_fused_attn
from test_attention_with_cp import (
model_configs_flash_attn,
model_configs_fused_attn,
)
from transformer_engine.pytorch import (
autocast,
DotProductAttention,
Expand Down Expand Up @@ -236,7 +239,10 @@ def run_dpa_with_cp(
config = copy.deepcopy(model_configs_flash_attn[model])
if kernel_backend == "FusedAttention":
os.environ["NVTE_FUSED_ATTN"] = "1"
config = copy.deepcopy(model_configs_fused_attn[model])
if model in model_configs_fused_attn:
config = copy.deepcopy(model_configs_fused_attn[model])
else:
assert False, f"{model=} is not a known FusedAttention CP config!"
assert config.attn_mask_type in [
"causal",
"no_mask",
Expand Down
Loading
Loading