qwen3-coder-next / code /models /tt_transformers /tests /test_attention_utils.py
raahemnabeel's picture
Add files using upload-large-folder tool
babe29f verified
Raw History Blame Contribute Delete
4.15 kB
# SPDX-FileCopyrightText: © 2026 Tenstorrent USA, Inc.
#
# SPDX-License-Identifier: Apache-2.0
from pathlib import Path
from types import SimpleNamespace
import torch
from models.tt_transformers.tt import attention as attention_module
class _StopAfterBiasConstruction(Exception):
pass
class _FakeDecoderOptimizations:
def get_tensor_dtype(self, **_):
return None
def get_math_fidelity(self, **_):
return None
def test_galaxy_qkv_bias_uses_weight_matching_2d_sharding_and_survives_column_reduce(monkeypatch, expect_error):
mesh_device = object()
mesh_mapper_calls = []
as_tensor_calls = []
monkeypatch.setattr(attention_module.ttnn, "ShardTensorToMesh", lambda *args, **kwargs: object())
monkeypatch.setattr(attention_module.ttnn, "ReplicateTensorToMesh", lambda *args, **kwargs: object())
monkeypatch.setattr(attention_module.ttnn, "from_torch", lambda *args, **kwargs: object())
def shard_tensor_2d_mesh(device, *, dims, mesh_shape):
mapper = object()
mesh_mapper_calls.append((device, dims, mesh_shape, mapper))
return mapper
def as_tensor(tensor, **kwargs):
as_tensor_calls.append((tensor, kwargs))
return SimpleNamespace(shape=(1, tensor.shape[-1]))
monkeypatch.setattr(attention_module.ttnn, "ShardTensor2dMesh", shard_tensor_2d_mesh)
monkeypatch.setattr(attention_module.ttnn, "as_tensor", as_tensor)
monkeypatch.setattr(
attention_module.ttnn,
"reshape",
lambda *args, **kwargs: (_ for _ in ()).throw(_StopAfterBiasConstruction("bias captured")),
)
configuration = SimpleNamespace(
num_devices=32,
dim=8192,
n_heads=64,
head_dim=128,
max_seq_len=32768,
max_batch_size=32,
n_kv_heads=8,
min_kv_prefill_shard_seqlen=0,
ccl_dtype=None,
MAX_QKV_MM_SEQ_LEN=2048,
tile_size=32,
tile_padded_batch_rows=32,
rms_norm_add_unit_offset=False,
use_qk_fused=False,
use_hf_rope=False,
arch_name="wormhole_b0",
max_grid_size=None,
compute_kernel_config_hifi2=None,
compute_kernel_config_hifi2_fp16=None,
compute_kernel_config_hifi4=None,
layer_types=None,
cluster_shape=[8, 4],
is_multichip=True,
dummy_weights=False,
qkv_size=10240,
get_model_config=lambda: {},
ccl_topology=lambda: None,
get_state_dict_prefix=lambda *_: "layers.0.attention",
)
args = SimpleNamespace(decoders_optimizations=_FakeDecoderOptimizations())
state_dict = {
"layers.0.attention.wq.bias": torch.arange(16),
"layers.0.attention.wk.bias": torch.arange(100, 108),
"layers.0.attention.wv.bias": torch.arange(200, 208),
}
with expect_error(_StopAfterBiasConstruction, "bias captured"):
attention_module.Attention(
mesh_device=mesh_device,
tt_ccl=None,
args=args,
state_dict=state_dict,
weight_cache_path=Path("cache"),
layer_num=0,
dtype=None,
transformation_mats=None,
configuration=configuration,
)
assert len(mesh_mapper_calls) == 1
assert mesh_mapper_calls[0][:3] == (mesh_device, (-1, None), [8, 4])
qkv_bias, tensor_kwargs = as_tensor_calls[0]
assert tensor_kwargs["mesh_mapper"] is mesh_mapper_calls[0][3]
assert tensor_kwargs["cache_file_name"].name.endswith("wqkv_bias_prefill_sharded_2d_col_reduce_4")
# Each row shard is replicated over all four mesh columns and added before
# the column all-reduce. Their sum must restore one copy of the model bias,
# rather than the four copies produced by an unscaled replicated bias.
expected_device_shards = [
torch.tensor([2 * i, 2 * i + 1, 100 + i, 200 + i], dtype=qkv_bias.dtype) for i in range(8)
]
reduced_device_shards = [shard * configuration.cluster_shape[1] for shard in torch.chunk(qkv_bias, 8)]
assert all(torch.equal(actual, expected) for actual, expected in zip(reduced_device_shards, expected_device_shards))