mirror of
https://github.com/tile-ai/tilelang.git
synced 2026-10-20 06:30:07 +08:00
* [BugFix] Transpose only the final two axes * [Test] Cover transpose boundary predicate mapping * [BugFix] Guard transpose bounds with generated indices --------- Co-authored-by: LeiWang1999 <leiwang1999@outlook.com>
141 lines
3.4 KiB
Python
141 lines
3.4 KiB
Python
import math
|
|
|
|
import pytest
|
|
import torch
|
|
|
|
import tilelang
|
|
import tilelang.language as T
|
|
from tilelang import tvm
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"src_shape",
|
|
[
|
|
(2, 3, 4),
|
|
(2, 3, 4, 5),
|
|
(2, 3, 1),
|
|
(2, 1, 3),
|
|
],
|
|
)
|
|
def test_cpu_transpose_swaps_only_the_final_two_axes(src_shape):
|
|
dst_shape = (*src_shape[:-2], src_shape[-1], src_shape[-2])
|
|
|
|
@T.prim_func
|
|
def main(
|
|
src: T.Tensor(src_shape, T.float32),
|
|
dst: T.Tensor(dst_shape, T.float32),
|
|
):
|
|
with T.Kernel(1):
|
|
T.transpose(src, dst)
|
|
|
|
with tvm.target.Target("c"):
|
|
kernel = tilelang.compile(
|
|
main,
|
|
out_idx=[1],
|
|
target="c",
|
|
target_host="c",
|
|
execution_backend="cython",
|
|
)
|
|
|
|
src = torch.arange(math.prod(src_shape), dtype=torch.float32).reshape(src_shape)
|
|
actual = kernel(src)
|
|
expected = src.transpose(-2, -1)
|
|
|
|
torch.testing.assert_close(actual, expected)
|
|
|
|
|
|
def test_cpu_transpose_maps_destination_boundary_predicate():
|
|
src_shape = (2, 3, 4)
|
|
dst_shape = (2, 4, 3)
|
|
|
|
@T.prim_func
|
|
def main(
|
|
src: T.Tensor(src_shape, T.float32),
|
|
dst: T.Tensor(dst_shape, T.float32),
|
|
):
|
|
with T.Kernel(1):
|
|
T.fill(dst, -1.0)
|
|
T.transpose(
|
|
src[0:2, 0:3, 0:4],
|
|
dst[0:2, 0:4, 1:4],
|
|
)
|
|
|
|
with tvm.target.Target("c"):
|
|
kernel = tilelang.compile(
|
|
main,
|
|
out_idx=[1],
|
|
target="c",
|
|
target_host="c",
|
|
execution_backend="cython",
|
|
)
|
|
|
|
src = torch.arange(math.prod(src_shape), dtype=torch.float32).reshape(src_shape)
|
|
actual = kernel(src)
|
|
expected = torch.full(dst_shape, -1.0)
|
|
expected[:, :, 1:] = src[:, :2, :].transpose(-2, -1)
|
|
|
|
torch.testing.assert_close(actual, expected)
|
|
|
|
|
|
def test_cpu_transpose_guards_out_of_bounds_singleton_destination():
|
|
src_shape = (2, 3, 1)
|
|
dst_shape = (2, 1, 3)
|
|
|
|
@T.prim_func
|
|
def main(
|
|
src: T.Tensor(src_shape, T.float32),
|
|
dst: T.Tensor(dst_shape, T.float32),
|
|
):
|
|
with T.Kernel(1):
|
|
T.fill(dst, -1.0)
|
|
T.transpose(
|
|
src[0:2, 0:3, 0:1],
|
|
dst[0:2, 1:2, 0:3],
|
|
)
|
|
|
|
with tvm.target.Target("c"):
|
|
kernel = tilelang.compile(
|
|
main,
|
|
out_idx=[1],
|
|
target="c",
|
|
target_host="c",
|
|
execution_backend="cython",
|
|
)
|
|
|
|
src = torch.arange(math.prod(src_shape), dtype=torch.float32).reshape(src_shape)
|
|
actual = kernel(src)
|
|
expected = torch.full(dst_shape, -1.0)
|
|
|
|
torch.testing.assert_close(actual, expected)
|
|
|
|
|
|
def test_cpu_transpose_guards_out_of_bounds_singleton_source():
|
|
src_shape = (2, 3, 1)
|
|
dst_shape = (2, 1, 3)
|
|
|
|
@T.prim_func
|
|
def main(
|
|
src: T.Tensor(src_shape, T.float32),
|
|
dst: T.Tensor(dst_shape, T.float32),
|
|
):
|
|
with T.Kernel(1):
|
|
T.transpose(
|
|
src[0:2, 0:3, 1:2],
|
|
dst[0:2, 0:1, 0:3],
|
|
)
|
|
|
|
with tvm.target.Target("c"):
|
|
kernel = tilelang.compile(
|
|
main,
|
|
out_idx=[1],
|
|
target="c",
|
|
target_host="c",
|
|
execution_backend="cython",
|
|
)
|
|
|
|
src = torch.arange(math.prod(src_shape), dtype=torch.float32).reshape(src_shape)
|
|
actual = kernel(src)
|
|
expected = torch.zeros(dst_shape, dtype=torch.float32)
|
|
|
|
torch.testing.assert_close(actual, expected)
|