forked from tile-ai/TileOPs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_ada_layer_norm_zero.py
More file actions
104 lines (85 loc) · 3.92 KB
/
Copy pathtest_ada_layer_norm_zero.py
File metadata and controls
104 lines (85 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
from tileops.utils import get_backend_name
DEVICE = get_backend_name()
import pytest
import torch
import torch.nn.functional as F
from tests.test_base import FixtureBase, TestBase
from tileops.ops.norm.ada_layer_norm_zero import AdaLayerNormZeroFwdOp
from workloads.ada_layer_norm_zero import AdaLayerNormZeroTest as _AdaLayerNormZeroTestWorkload
class AdaLayerNormZeroTest(_AdaLayerNormZeroTestWorkload, TestBase):
def ref_program(
self, x: torch.Tensor, scale: torch.Tensor, shift: torch.Tensor, gate: torch.Tensor,
) -> torch.Tensor:
# AdaLN-Zero: y = gate * (scale * LayerNorm(x) + shift)
normed = F.layer_norm(
x.float(),
(self.n,),
weight=None,
bias=None,
eps=self.eps,
)
y = gate.float() * (scale.float() * normed + shift.float())
return y.to(x.dtype)
class AdaLayerNormZeroFixture(FixtureBase):
PARAMS = [
("m, n, dtype", [
# Standard aligned shapes -- fp32
pytest.param(1024, 4096, torch.float32, marks=pytest.mark.smoke),
# Standard aligned shapes -- fp16
pytest.param(1024, 4096, torch.float16, marks=pytest.mark.smoke),
# Standard aligned shapes -- bf16
pytest.param(1024, 4096, torch.bfloat16, marks=pytest.mark.smoke),
pytest.param(4096, 4096, torch.float32, marks=pytest.mark.full),
pytest.param(4096, 4096, torch.float16, marks=pytest.mark.full),
pytest.param(4096, 4096, torch.bfloat16, marks=pytest.mark.full),
# Non-power-of-two hidden dims
pytest.param(1024, 3000, torch.float32, marks=pytest.mark.full),
pytest.param(1024, 3000, torch.float16, marks=pytest.mark.full),
pytest.param(1024, 3000, torch.bfloat16, marks=pytest.mark.full),
# Tail-M: M not divisible by block_m
pytest.param(1025, 4096, torch.float16, marks=pytest.mark.full),
pytest.param(1025, 4096, torch.bfloat16, marks=pytest.mark.full),
]),
]
def _get_tolerances(dtype: torch.dtype) -> tuple[float, float]:
if dtype == torch.float32:
return 1e-5, 1e-5
elif dtype == torch.float16:
return 1e-3, 1e-3
else: # bfloat16
return 1.6e-2, 1.6e-2
@AdaLayerNormZeroFixture
def test_ada_layer_norm_zero_op(m: int, n: int, dtype: torch.dtype) -> None:
test = AdaLayerNormZeroTest(m, n, dtype)
op = AdaLayerNormZeroFwdOp(M=m, N=n, dtype=dtype)
atol, rtol = _get_tolerances(dtype)
test.check(op, *test.gen_inputs(), atol=atol, rtol=rtol)
class AdaLayerNormZero3DFixture(FixtureBase):
PARAMS = [
("batch, seq, hidden, dtype", [
pytest.param(2, 512, 4096, torch.float32, marks=pytest.mark.smoke),
pytest.param(2, 512, 4096, torch.float16, marks=pytest.mark.smoke),
pytest.param(2, 512, 4096, torch.bfloat16, marks=pytest.mark.smoke),
]),
]
@AdaLayerNormZero3DFixture
def test_ada_layer_norm_zero_3d(batch: int, seq: int, hidden: int, dtype: torch.dtype) -> None:
"""Test with 3D input (batch, seq, hidden)."""
x = torch.randn(batch, seq, hidden, dtype=dtype, device=DEVICE)
scale = torch.randn(batch, seq, hidden, dtype=dtype, device=DEVICE)
shift = torch.randn(batch, seq, hidden, dtype=dtype, device=DEVICE)
gate = torch.randn(batch, seq, hidden, dtype=dtype, device=DEVICE)
M = batch * seq
op = AdaLayerNormZeroFwdOp(M=M, N=hidden, dtype=dtype)
# Reference: gate * (scale * LayerNorm(x) + shift)
eps = 1e-5
normed = F.layer_norm(
x.float(), (hidden,), weight=None, bias=None, eps=eps,
)
y_ref = (gate.float() * (scale.float() * normed + shift.float())).to(dtype)
y = op(x, scale, shift, gate)
atol, rtol = _get_tolerances(dtype)
assert torch.allclose(y, y_ref, atol=atol, rtol=rtol), \
f"3D test failed, max err: {(y - y_ref).abs().max()}"
if __name__ == "__main__":
pytest.main([__file__, "-vvs"])