mirror of
https://github.com/tile-ai/tilelang.git
synced 2026-10-20 06:30:07 +08:00
139 lines
3.9 KiB
Python
139 lines
3.9 KiB
Python
import torch
|
|
import tilelang.testing
|
|
import tilelang.language as T
|
|
|
|
|
|
@tilelang.jit
|
|
def get_select_kernel_1():
|
|
@T.prim_func
|
|
def main(
|
|
A: T.Tensor[(128, 8), T.float32],
|
|
B: T.Tensor[(128, 8), T.float32],
|
|
):
|
|
with T.Kernel(1, threads=128):
|
|
tx = T.get_thread_binding(0)
|
|
tmp = T.alloc_var(T.bfloat16)
|
|
tmp = A[tx, 3]
|
|
|
|
B[tx, 0] = T.Select(True, A[tx, 0], 0.0)
|
|
B[tx, 1] = T.Select(False, 1.0, A[tx, 1])
|
|
B[tx, 2] = T.Select(T.cast(A[tx, 3], T.bfloat16) == tmp, A[tx, 2], T.cast(tmp, T.float32))
|
|
B[tx, 3] = T.Select(B[tx, 0] != 0.0, T.if_then_else(B[tx, 1] != 0.0, A[tx, 3], 0.0), 0.0)
|
|
|
|
for i in T.serial(4):
|
|
B[tx, i + 4] = T.Select(
|
|
A[tx, 0] == 0, T.if_then_else(T.Select(True, False, True), 1.0, 2.0), T.Select(True, A[tx, i + 4], 3.0)
|
|
)
|
|
|
|
return main
|
|
|
|
|
|
def test_select_correctness():
|
|
A = torch.randn((128, 8), dtype=torch.float32, device="cuda")
|
|
B = torch.empty((128, 8), dtype=torch.float32, device="cuda")
|
|
kernel = get_select_kernel_1()
|
|
|
|
A = torch.clamp(A, min=1e-4)
|
|
kernel(A, B)
|
|
assert torch.allclose(A, B)
|
|
|
|
|
|
@tilelang.jit
|
|
def get_select_kernel_2():
|
|
@T.prim_func
|
|
def main(
|
|
A: T.Tensor[(128, 8), T.float32],
|
|
B: T.Tensor[(128, 8), T.float32],
|
|
):
|
|
with T.Kernel(1, threads=128):
|
|
tx = T.get_thread_binding(0)
|
|
tmp = T.alloc_var(T.bfloat16)
|
|
tmp = A[tx, 3]
|
|
|
|
B[tx, 0] = T.Select(True, A[tx, 0], 0.0)
|
|
B[tx, 1] = T.Select(False, 1.0, A[tx, 1])
|
|
B[tx, 2] = T.Select(T.cast(A[tx, 3], T.bfloat16) == tmp, A[tx, 2], T.cast(tmp, T.float32))
|
|
B[tx, 3] = T.Select(B[tx, 0] != 0.0, T.Select(B[tx, 1] != 0.0, A[tx, 3], 0.0), 0.0)
|
|
|
|
for i in T.serial(4):
|
|
B[tx, i + 4] = T.Select(
|
|
A[tx, 0] == 0,
|
|
T.Select(T.Select(True, False, True), 1.0, 2.0),
|
|
T.Select(T.sin(A[tx, 2]) == 1.0, T.sin(A[tx, 0]), T.cos(A[tx, 1])),
|
|
)
|
|
|
|
return main
|
|
|
|
|
|
def test_select_codegen_no_if():
|
|
kernel = get_select_kernel_2()
|
|
source = kernel.get_kernel_source()
|
|
assert "if (" not in source
|
|
|
|
|
|
@tilelang.jit
|
|
def get_parallel_select_kernel():
|
|
@T.prim_func
|
|
def main(
|
|
A: T.Tensor[(1024,), T.float32],
|
|
B: T.Tensor[(1024,), T.float32],
|
|
):
|
|
with T.Kernel(1, threads=128):
|
|
for i in T.Parallel(1024):
|
|
B[i] = T.Select(i < 512, A[i], 0.0)
|
|
|
|
return main
|
|
|
|
|
|
def test_parallel_select_uniform_condition():
|
|
kernel = get_parallel_select_kernel()
|
|
source = kernel.get_kernel_source()
|
|
|
|
assert "if (" not in source
|
|
assert ") ? " in source
|
|
assert "*(float4*)" in source or "load_global_256" in source
|
|
|
|
A = torch.randn((1024,), dtype=torch.float32, device="cuda")
|
|
B = torch.empty_like(A)
|
|
|
|
kernel(A, B)
|
|
|
|
expected = torch.zeros_like(A)
|
|
expected[:512] = A[:512]
|
|
torch.testing.assert_close(B, expected)
|
|
|
|
|
|
@tilelang.jit
|
|
def get_parallel_data_dependent_select_kernel():
|
|
@T.prim_func
|
|
def main(
|
|
A: T.Tensor[(256,), T.float32],
|
|
B: T.Tensor[(256,), T.float32],
|
|
):
|
|
with T.Kernel(1, threads=32):
|
|
for i in T.Parallel(256):
|
|
B[i] = T.Select(A[i] > T.float32(0), A[i], T.float32(0))
|
|
|
|
return main
|
|
|
|
|
|
def test_parallel_data_dependent_select_disables_auto_vectorization():
|
|
kernel = get_parallel_data_dependent_select_kernel()
|
|
source = kernel.get_kernel_source()
|
|
|
|
assert "if (" not in source
|
|
assert ") ? " in source
|
|
assert "*(float4*)" not in source
|
|
assert "load_global_256" not in source
|
|
|
|
A = torch.randn((256,), dtype=torch.float32, device="cuda")
|
|
B = torch.empty_like(A)
|
|
kernel(A, B)
|
|
|
|
expected = torch.where(A > 0, A, torch.zeros_like(A))
|
|
torch.testing.assert_close(B, expected)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
tilelang.testing.main()
|