mirror of
https://github.com/tile-ai/tilelang.git
synced 2026-10-25 07:14:16 +08:00
Allow configuring pass configs, compile flags, and out_idx directly inside function bodies using T.annotate_compile_flags(), T.annotate_pass_configs(), and T.empty()+return. These are stored as proper PrimFunc attrs (tilelang_compile_flags, tilelang_pass_configs, tilelang_out_idx) instead of monkey-patching, and merged at compile time. Annotations can be placed before or after tensor type annotations. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
215 lines
6.6 KiB
Python
215 lines
6.6 KiB
Python
"""Test T.annotate_compile_flags, T.annotate_pass_configs, and out_idx via PrimFunc attrs."""
|
|
|
|
import pytest
|
|
import torch
|
|
import tilelang
|
|
from tilelang import language as T
|
|
from tilelang.transform import PassConfigKey
|
|
|
|
|
|
def test_out_idx_via_attr_lazy():
|
|
"""out_idx should be stored as PrimFunc attr when using T.empty + return."""
|
|
|
|
@T.prim_func
|
|
def kernel(A):
|
|
A: T.Tensor[[128, 128], T.float32]
|
|
B = T.empty([128, 128], T.float32)
|
|
with T.Kernel(1):
|
|
for i in T.serial(128):
|
|
for j in T.serial(128):
|
|
B[i, j] = A[i, j] + 1.0
|
|
return B
|
|
|
|
assert "tilelang_out_idx" in kernel.attrs
|
|
assert list(kernel.attrs["tilelang_out_idx"]) == [-1]
|
|
|
|
compiled = tilelang.compile(kernel)
|
|
a = torch.randn(128, 128, device="cuda")
|
|
b = compiled(a)
|
|
torch.testing.assert_close(b, a + 1.0)
|
|
|
|
|
|
def test_all_attrs_together_lazy():
|
|
"""annotate_pass_configs, annotate_compile_flags, and out_idx should all work together."""
|
|
|
|
@T.prim_func
|
|
def kernel(A):
|
|
A: T.Tensor[[64, 64], T.float32]
|
|
T.annotate_pass_configs({PassConfigKey.TL_ENABLE_FAST_MATH: True})
|
|
T.annotate_compile_flags(["--use_fast_math"])
|
|
B = T.empty([64, 64], T.float32)
|
|
with T.Kernel(1):
|
|
for i in T.serial(64):
|
|
for j in T.serial(64):
|
|
B[i, j] = A[i, j] * 2.0
|
|
return B
|
|
|
|
attrs = kernel.attrs
|
|
assert "tilelang_out_idx" in attrs
|
|
assert "tilelang_pass_configs" in attrs
|
|
assert "tilelang_compile_flags" in attrs
|
|
|
|
compiled = tilelang.compile(kernel)
|
|
a = torch.randn(64, 64, device="cuda")
|
|
b = compiled(a)
|
|
torch.testing.assert_close(b, a * 2.0)
|
|
|
|
|
|
def test_eager_mode_attrs():
|
|
"""Eager mode should support annotate_pass_configs and out_idx via T.empty."""
|
|
|
|
@tilelang.jit
|
|
def kernel(A):
|
|
M, N = T.const("M N")
|
|
A: T.Tensor[[M, N], T.float32]
|
|
B = T.empty([M, N], T.float32)
|
|
T.annotate_pass_configs({PassConfigKey.TL_ENABLE_FAST_MATH: True})
|
|
with T.Kernel(1):
|
|
for i in T.serial(M):
|
|
for j in T.serial(N):
|
|
B[i, j] = A[i, j] + 1.0
|
|
return B
|
|
|
|
a = torch.randn(32, 32, device="cuda")
|
|
result = kernel(a)
|
|
torch.testing.assert_close(result, a + 1.0)
|
|
|
|
|
|
def test_out_idx_conflict_detection():
|
|
"""Specifying both T.empty return and external out_idx should raise ValueError."""
|
|
|
|
@T.prim_func
|
|
def kernel(A):
|
|
A: T.Tensor[[32, 32], T.float32]
|
|
B = T.empty([32, 32], T.float32)
|
|
with T.Kernel(1):
|
|
for i in T.serial(32):
|
|
for j in T.serial(32):
|
|
B[i, j] = A[i, j]
|
|
return B
|
|
|
|
with pytest.raises(ValueError, match="Out index conflict"):
|
|
tilelang.compile(kernel, out_idx=[-1])
|
|
|
|
|
|
def test_no_out_idx_when_not_using_empty():
|
|
"""When T.empty is not used, tilelang_out_idx attr should not be present."""
|
|
|
|
@T.prim_func
|
|
def kernel(A, B):
|
|
A: T.Tensor[[32, 32], T.float32]
|
|
B: T.Tensor[[32, 32], T.float32]
|
|
with T.Kernel(1):
|
|
for i in T.serial(32):
|
|
for j in T.serial(32):
|
|
B[i, j] = A[i, j]
|
|
|
|
assert kernel.attrs is None or "tilelang_out_idx" not in kernel.attrs
|
|
|
|
compiled = tilelang.compile(kernel, out_idx=[-1])
|
|
a = torch.randn(32, 32, device="cuda")
|
|
b = compiled(a)
|
|
torch.testing.assert_close(b, a)
|
|
|
|
|
|
def test_pass_configs_only_lazy():
|
|
"""annotate_pass_configs should work without T.empty or annotate_compile_flags."""
|
|
|
|
@T.prim_func
|
|
def kernel(A, B):
|
|
A: T.Tensor[[32, 32], T.float32]
|
|
B: T.Tensor[[32, 32], T.float32]
|
|
T.annotate_pass_configs({PassConfigKey.TL_ENABLE_FAST_MATH: True})
|
|
with T.Kernel(1):
|
|
for i in T.serial(32):
|
|
for j in T.serial(32):
|
|
B[i, j] = A[i, j] + 1.0
|
|
|
|
assert "tilelang_pass_configs" in kernel.attrs
|
|
assert kernel.attrs is None or "tilelang_out_idx" not in kernel.attrs
|
|
|
|
compiled = tilelang.compile(kernel, out_idx=[-1])
|
|
a = torch.randn(32, 32, device="cuda")
|
|
b = compiled(a)
|
|
torch.testing.assert_close(b, a + 1.0)
|
|
|
|
|
|
def test_compile_flags_only_lazy():
|
|
"""annotate_compile_flags should work standalone."""
|
|
|
|
@T.prim_func
|
|
def kernel(A, B):
|
|
A: T.Tensor[[32, 32], T.float32]
|
|
B: T.Tensor[[32, 32], T.float32]
|
|
T.annotate_compile_flags(["--use_fast_math"])
|
|
with T.Kernel(1):
|
|
for i in T.serial(32):
|
|
for j in T.serial(32):
|
|
B[i, j] = A[i, j] + 1.0
|
|
|
|
assert "tilelang_compile_flags" in kernel.attrs
|
|
|
|
compiled = tilelang.compile(kernel, out_idx=[-1])
|
|
a = torch.randn(32, 32, device="cuda")
|
|
b = compiled(a)
|
|
torch.testing.assert_close(b, a + 1.0)
|
|
|
|
|
|
def test_annotations_before_tensor_type():
|
|
"""Annotations placed before tensor type annotations should work."""
|
|
|
|
@T.prim_func
|
|
def kernel(A, B):
|
|
T.annotate_pass_configs({PassConfigKey.TL_ENABLE_FAST_MATH: True})
|
|
T.annotate_compile_flags(["--use_fast_math"])
|
|
A: T.Tensor[[32, 32], T.float32]
|
|
B: T.Tensor[[32, 32], T.float32]
|
|
with T.Kernel(1):
|
|
for i in T.serial(32):
|
|
for j in T.serial(32):
|
|
B[i, j] = A[i, j] + 1.0
|
|
|
|
assert "tilelang_pass_configs" in kernel.attrs
|
|
assert "tilelang_compile_flags" in kernel.attrs
|
|
|
|
compiled = tilelang.compile(kernel, out_idx=[-1])
|
|
a = torch.randn(32, 32, device="cuda")
|
|
b = compiled(a)
|
|
torch.testing.assert_close(b, a + 1.0)
|
|
|
|
|
|
def test_annotations_after_tensor_type():
|
|
"""Annotations placed after tensor type annotations should work."""
|
|
|
|
@T.prim_func
|
|
def kernel(A, B):
|
|
A: T.Tensor[[32, 32], T.float32]
|
|
B: T.Tensor[[32, 32], T.float32]
|
|
T.annotate_pass_configs({PassConfigKey.TL_ENABLE_FAST_MATH: True})
|
|
T.annotate_compile_flags(["--use_fast_math"])
|
|
with T.Kernel(1):
|
|
for i in T.serial(32):
|
|
for j in T.serial(32):
|
|
B[i, j] = A[i, j] + 1.0
|
|
|
|
assert "tilelang_pass_configs" in kernel.attrs
|
|
assert "tilelang_compile_flags" in kernel.attrs
|
|
|
|
compiled = tilelang.compile(kernel, out_idx=[-1])
|
|
a = torch.randn(32, 32, device="cuda")
|
|
b = compiled(a)
|
|
torch.testing.assert_close(b, a + 1.0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_out_idx_via_attr_lazy()
|
|
test_all_attrs_together_lazy()
|
|
test_eager_mode_attrs()
|
|
test_out_idx_conflict_detection()
|
|
test_no_out_idx_when_not_using_empty()
|
|
test_pass_configs_only_lazy()
|
|
test_compile_flags_only_lazy()
|
|
test_annotations_before_tensor_type()
|
|
test_annotations_after_tensor_type()
|
|
print("All tests passed!")
|