Download code/models/tt_dit/tests/unit/test_feedforward.py from sunandbean/diffrhythm-1.2-p100a: direct link, hf CLI and curl.
- Browser
- Download file 7.36 kB
-
https://huggingface.co/sunandbean/diffrhythm-1.2-p100a/resolve/main/code/models/tt_dit/tests/unit/test_feedforward.py
- Command line
-
hf download hf://sunandbean/diffrhythm-1.2-p100a/code/models/tt_dit/tests/unit/test_feedforward.py
-
curl -L -o test_feedforward.py https://huggingface.co/sunandbean/diffrhythm-1.2-p100a/resolve/main/code/models/tt_dit/tests/unit/test_feedforward.py
7.36 kB
| # SPDX-FileCopyrightText: © 2025 Tenstorrent USA, Inc. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| import pytest | |
| import torch | |
| import ttnn | |
| from ...layers.feedforward import FeedForward, ParallelFeedForward | |
| from ...parallel.manager import CCLManager | |
| from ...utils.check import assert_quality | |
| from ...utils.tensor import bf16_tensor | |
| from ...utils.test import mesh_device_config_to_string | |
| class TorchFeedForward(torch.nn.Module): | |
| def __init__(self, dim, dim_out, bias=True, activation_fn=None, inner_dim=None): | |
| super().__init__() | |
| self.dim = dim | |
| self.dim_out = dim_out | |
| self.bias = bias | |
| self.activation_fn = activation_fn | |
| if activation_fn == "swiglu": | |
| ff1_inner_dim = inner_dim * 2 | |
| else: | |
| ff1_inner_dim = inner_dim | |
| self.ff1 = torch.nn.Linear(dim, ff1_inner_dim, bias=bias) | |
| self.ff2 = torch.nn.Linear(inner_dim, dim_out, bias=bias) | |
| def forward(self, x): | |
| x = self.ff1(x) | |
| if self.activation_fn == "gelu": | |
| x = torch.nn.functional.gelu(x) | |
| elif self.activation_fn == "swiglu": | |
| x, gate = torch.chunk(x, 2, -1) | |
| x = x * torch.nn.functional.silu(gate) | |
| return self.ff2(x) | |
| def test_feedforward( | |
| mesh_device: ttnn.MeshDevice, | |
| B: int, | |
| seq: int, | |
| dim: int, | |
| inner_dim: int, | |
| dim_out: int, | |
| bias: bool, | |
| activation_fn: str, | |
| ) -> None: | |
| torch_dtype = torch.bfloat16 | |
| torch_model = TorchFeedForward(dim, dim_out, bias=bias, activation_fn=activation_fn, inner_dim=inner_dim).to( | |
| dtype=torch_dtype | |
| ) | |
| torch_model.eval() | |
| tt_model = FeedForward( | |
| dim, dim_out, inner_dim=inner_dim, bias=bias, activation_fn=activation_fn, mesh_device=mesh_device | |
| ) | |
| tt_model.load_torch_state_dict(torch_model.state_dict()) | |
| torch_input_tensor = torch.randn((1, B, seq, dim), dtype=torch_dtype) | |
| tt_input_tensor = bf16_tensor(torch_input_tensor, device=mesh_device) | |
| with torch.no_grad(): | |
| torch_output = torch_model(torch_input_tensor) | |
| tt_output = tt_model(tt_input_tensor) | |
| for t in ttnn.get_device_tensors(tt_output): | |
| t = ttnn.to_torch(t) | |
| assert_quality(torch_output, t, pcc=0.999_400) | |
| def test_feedforward_swiglu_fused( | |
| mesh_device: ttnn.MeshDevice, | |
| B: int, | |
| seq: int, | |
| dim: int, | |
| inner_dim: int, | |
| dim_out: int, | |
| bias: bool, | |
| ) -> None: | |
| """FUSE_SWIGLU minimal_matmul path: silu(gate)*up fused into the matmul output stage. | |
| Compares the fused FeedForward against the torch golden (a*silu(b)). | |
| """ | |
| torch_dtype = torch.bfloat16 | |
| torch_model = TorchFeedForward(dim, dim_out, bias=bias, activation_fn="swiglu", inner_dim=inner_dim).to( | |
| dtype=torch_dtype | |
| ) | |
| torch_model.eval() | |
| tt_model = FeedForward( | |
| dim, | |
| dim_out, | |
| inner_dim=inner_dim, | |
| bias=bias, | |
| activation_fn="swiglu", | |
| mesh_device=mesh_device, | |
| ) | |
| tt_model.load_torch_state_dict(torch_model.state_dict()) | |
| torch_input_tensor = torch.randn((1, B, seq, dim), dtype=torch_dtype) | |
| tt_input_tensor = bf16_tensor(torch_input_tensor, device=mesh_device) | |
| with torch.no_grad(): | |
| torch_output = torch_model(torch_input_tensor) | |
| tt_output = tt_model(tt_input_tensor) | |
| for t in ttnn.get_device_tensors(tt_output): | |
| t = ttnn.to_torch(t) | |
| assert_quality(torch_output, t, pcc=0.999_900) | |
| def test_parallel_feedforward( | |
| mesh_device: ttnn.MeshDevice, | |
| B: int, | |
| seq: int, | |
| dim: int, | |
| inner_dim: int, | |
| dim_out: int, | |
| bias: bool, | |
| activation_fn: str, | |
| tp_mesh_axis: int, | |
| is_fsdp: bool, | |
| ) -> None: | |
| torch_dtype = torch.bfloat16 | |
| torch_model = TorchFeedForward(dim, dim_out, bias=bias, activation_fn=activation_fn, inner_dim=inner_dim).to( | |
| dtype=torch_dtype | |
| ) | |
| torch_model.eval() | |
| fsdp_mesh_axis = 1 - tp_mesh_axis if is_fsdp else None | |
| ccl_manager = CCLManager(mesh_device, topology=ttnn.Topology.Linear) | |
| tt_model = ParallelFeedForward( | |
| dim, | |
| dim_out, | |
| inner_dim=inner_dim, | |
| bias=bias, | |
| activation_fn=activation_fn, | |
| mesh_device=mesh_device, | |
| mesh_axis=tp_mesh_axis, | |
| fsdp_mesh_axis=fsdp_mesh_axis, | |
| ccl_manager=ccl_manager, | |
| ) | |
| tt_model.load_torch_state_dict(torch_model.state_dict()) | |
| torch_input_tensor = torch.randn((1, B, seq, dim), dtype=torch_dtype) | |
| tt_input_tensor = bf16_tensor(torch_input_tensor, device=mesh_device) | |
| with torch.no_grad(): | |
| torch_output = torch_model(torch_input_tensor) | |
| tt_output = tt_model(tt_input_tensor) | |
| shard_dims = [None, None] | |
| shard_dims[tp_mesh_axis] = -1 | |
| shard_dims[1 - tp_mesh_axis] = 0 | |
| tt_output = ttnn.to_torch( | |
| tt_output, | |
| mesh_composer=ttnn.ConcatMesh2dToTensor(mesh_device, dims=shard_dims, mesh_shape=tuple(mesh_device.shape)), | |
| ) | |
| for i in range(tt_output.shape[0]): | |
| assert_quality(torch_output.squeeze(), tt_output[i].squeeze(), pcc=0.999_400) | |