This is an automated email from the ASF dual-hosted git repository.

syfeng pushed a commit to branch unity
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/unity by this push:
     new 7bb37a54b4 [Unity][Dlight] Improve Dlight Tensorization Rule (#15427)
7bb37a54b4 is described below

commit 7bb37a54b48dbf6c35d69a47bcfbcd5b31ff6035
Author: Bao Anchang <[email protected]>
AuthorDate: Sat Jul 29 11:18:22 2023 +0800

    [Unity][Dlight] Improve Dlight Tensorization Rule (#15427)
    
    * enhance dlight tensorize
    
    * fix test
---
 python/tvm/dlight/gpu/matmul.py                  | 23 ++++++---
 tests/python/dlight/test_gpu_matmul_tensorize.py | 64 ++++++++++++------------
 2 files changed, 49 insertions(+), 38 deletions(-)

diff --git a/python/tvm/dlight/gpu/matmul.py b/python/tvm/dlight/gpu/matmul.py
index 5ea3aa4dee..5a179c485c 100644
--- a/python/tvm/dlight/gpu/matmul.py
+++ b/python/tvm/dlight/gpu/matmul.py
@@ -322,10 +322,13 @@ class MatmulTensorization(ScheduleRule):
         micro_size_y = 16
         micro_size_k = 16
 
+        warp_size = 32
+        vector_size = 4
+
         i_factors, j_factors, k_factors = (
-            [None, 1, 2, 2],
-            [1, None, 2, 2],
-            [None, 2],
+            [None, 1, 4, 2],
+            [1, None, 4, 2],
+            [None, 4],
         )
 
         num_ty = i_factors[2] * j_factors[2]
@@ -385,8 +388,6 @@ class MatmulTensorization(ScheduleRule):
         def fetch_to_shared(block, idx, ndim):
             block_read = sch.cache_read(block, idx, "shared.dyn")
             sch.compute_at(block_read, k0)
-            vector_size = 4
-            warp_size = 32
             fused = sch.fuse(*sch.get_loops(block_read)[-ndim:])
 
             _, f_1, f_2, f_3 = sch.split(fused, factors=[None, num_ty, 
warp_size, vector_size])
@@ -483,6 +484,12 @@ class MatmulTensorization(ScheduleRule):
                 return None
 
         auto_inline_consumers(sch, accumulator_shared_to_global)
+
+        fused = sch.fuse(*sch.get_loops(accumulator_shared_to_global)[-2:])
+        _, f1, f2 = sch.split(fused, factors=[None, warp_size, vector_size])
+        sch.bind(f1, "threadIdx.x")
+        sch.vectorize(f2)
+
         return sch if tensorize_success else None
 
 
@@ -525,7 +532,7 @@ class Matmul(ScheduleRule):
         # Tensorization config:
         # If any value of I, J, K is fixed and less than this threshold,
         # tensorization rule will not be applied.
-        minimal_tensorize_threshold = 128
+        minimal_tensorize_threshold = 64
 
         # Step 1. Normalize generic matmul to C[S, I, J] += A[S, I, K] * B[S, 
J, K]
         block = sch.reindex(main_block, ("read", 0))
@@ -546,7 +553,9 @@ class Matmul(ScheduleRule):
                     if extent.value <= minimal_tensorize_threshold:
                         apply_tensorization = False
             if apply_tensorization:
-                return MatmulTensorization().apply(func, target, _)
+                tensorize_sch = MatmulTensorization().apply(func, target, _)
+                if tensorize_sch is not None:
+                    return tensorize_sch
 
         # Step 2. Padding for dynamic shape kernels
         sch.pad_einsum(
diff --git a/tests/python/dlight/test_gpu_matmul_tensorize.py 
b/tests/python/dlight/test_gpu_matmul_tensorize.py
index 349b4bf256..0008dcdcd4 100644
--- a/tests/python/dlight/test_gpu_matmul_tensorize.py
+++ b/tests/python/dlight/test_gpu_matmul_tensorize.py
@@ -61,14 +61,14 @@ class TestMatmulTensorize(BaseBeforeAfter):
         compute_reindex_shared_dyn = T.alloc_buffer((1, 256, 256), "float16", 
scope="shared.dyn")
         compute_reindex_shared_dyn_wmma_accumulator = T.alloc_buffer((1, 256, 
256), "float16", scope="wmma.accumulator")
         for ax0 in T.thread_binding(T.int64(1), thread="blockIdx.z"):
-            for ax1_0_0_ax2_0_0_fused in T.thread_binding(4, 
thread="blockIdx.x"):
-                for ax1_0_1_ax2_0_1_fused in T.thread_binding(4, 
thread="blockIdx.y"):
-                    for ax2_0_2_ax1_0_2_fused in T.thread_binding(4, 
thread="threadIdx.y"):
+            for ax1_0_0_ax2_0_0_fused in T.thread_binding(2, 
thread="blockIdx.x"):
+                for ax1_0_1_ax2_0_1_fused in T.thread_binding(2, 
thread="blockIdx.y"):
+                    for ax2_0_2_ax1_0_2_fused in T.thread_binding(16, 
thread="threadIdx.y"):
                         for ax1_0_3_init, ax2_0_3_init in T.grid(2, 2):
                             with T.block("compute_o_init"):
                                 v0_o = T.axis.spatial(T.int64(1), ax0)
-                                v1_o = T.axis.spatial(16, 
ax1_0_0_ax2_0_0_fused * 4 + ax2_0_2_ax1_0_2_fused % 2 * 2 + ax1_0_3_init)
-                                v2_o = T.axis.spatial(16, 
ax1_0_1_ax2_0_1_fused * 4 + ax2_0_2_ax1_0_2_fused // 2 * 2 + ax2_0_3_init)
+                                v1_o = T.axis.spatial(16, 
ax1_0_0_ax2_0_0_fused * 8 + ax2_0_2_ax1_0_2_fused % 4 * 2 + ax1_0_3_init)
+                                v2_o = T.axis.spatial(16, 
ax1_0_1_ax2_0_1_fused * 8 + ax2_0_2_ax1_0_2_fused // 4 * 2 + ax2_0_3_init)
                                 T.reads()
                                 
T.writes(compute_reindex_shared_dyn_wmma_accumulator[0, v1_o * 16:v1_o * 16 + 
16, v2_o * 16:v2_o * 16 + 16])
                                 with T.block("compute_init_o"):
@@ -78,38 +78,38 @@ class TestMatmulTensorize(BaseBeforeAfter):
                                     
T.writes(compute_reindex_shared_dyn_wmma_accumulator[0, v1_o * 16:v1_o * 16 + 
16, v2_o * 16:v2_o * 16 + 16])
                                     C = 
T.match_buffer(compute_reindex_shared_dyn_wmma_accumulator[0, v1_o * 16:v1_o * 
16 + 16, v2_o * 16:v2_o * 16 + 16], (16, 16), "float16", strides=("C_s0", 
"C_s1"), scope="wmma.accumulator", offset_factor=16)
                                     T.tvm_fill_fragment(C.data, 16, 16, 16, 
C.elem_offset // C.strides[0] // 16 * (C.strides[0] // 16) + C.elem_offset % 
C.strides[0] // 16, T.float32(0))
-                        for ax3_0_0 in range(8):
+                        for ax3_0_0 in range(4):
                             for ax0_ax1_fused_0 in range(4):
-                                for ax0_ax1_fused_1 in T.thread_binding(4, 
thread="threadIdx.y"):
+                                for ax0_ax1_fused_1 in T.thread_binding(16, 
thread="threadIdx.y"):
                                     for ax0_ax1_fused_2 in 
T.thread_binding(32, thread="threadIdx.x"):
                                         for ax0_ax1_fused_3 in T.vectorized(4):
                                             with 
T.block("X_reindex_shared.dyn"):
                                                 v0 = T.axis.spatial(1, 0)
-                                                v1 = T.axis.spatial(256, 
ax1_0_0_ax2_0_0_fused * 64 + (ax0_ax1_fused_0 * 512 + ax0_ax1_fused_1 * 128 + 
ax0_ax1_fused_2 * 4 + ax0_ax1_fused_3) // 32)
-                                                v2 = T.axis.spatial(256, 
ax3_0_0 * 32 + (ax0_ax1_fused_0 * 512 + ax0_ax1_fused_1 * 128 + ax0_ax1_fused_2 
* 4 + ax0_ax1_fused_3) % 32)
+                                                v1 = T.axis.spatial(256, 
ax1_0_0_ax2_0_0_fused * 128 + (ax0_ax1_fused_0 * 2048 + ax0_ax1_fused_1 * 128 + 
ax0_ax1_fused_2 * 4 + ax0_ax1_fused_3) // 64)
+                                                v2 = T.axis.spatial(256, 
ax3_0_0 * 64 + (ax0_ax1_fused_0 * 2048 + ax0_ax1_fused_1 * 128 + 
ax0_ax1_fused_2 * 4 + ax0_ax1_fused_3) % 64)
                                                 T.reads(X[v1, v2])
                                                 
T.writes(X_reindex_shared_dyn[v0, v1, v2])
                                                 
T.block_attr({"buffer_dim_align": [[0, 1, 16, 8]]})
                                                 X_reindex_shared_dyn[v0, v1, 
v2] = X[v1, v2]
                             for ax0_ax1_fused_0 in range(4):
-                                for ax0_ax1_fused_1 in T.thread_binding(4, 
thread="threadIdx.y"):
+                                for ax0_ax1_fused_1 in T.thread_binding(16, 
thread="threadIdx.y"):
                                     for ax0_ax1_fused_2 in 
T.thread_binding(32, thread="threadIdx.x"):
                                         for ax0_ax1_fused_3 in T.vectorized(4):
                                             with 
T.block("W_reindex_shared.dyn"):
                                                 v0 = T.axis.spatial(1, 0)
-                                                v1 = T.axis.spatial(256, 
ax1_0_1_ax2_0_1_fused * 64 + (ax0_ax1_fused_0 * 512 + ax0_ax1_fused_1 * 128 + 
ax0_ax1_fused_2 * 4 + ax0_ax1_fused_3) // 32)
-                                                v2 = T.axis.spatial(256, 
ax3_0_0 * 32 + (ax0_ax1_fused_0 * 512 + ax0_ax1_fused_1 * 128 + ax0_ax1_fused_2 
* 4 + ax0_ax1_fused_3) % 32)
+                                                v1 = T.axis.spatial(256, 
ax1_0_1_ax2_0_1_fused * 128 + (ax0_ax1_fused_0 * 2048 + ax0_ax1_fused_1 * 128 + 
ax0_ax1_fused_2 * 4 + ax0_ax1_fused_3) // 64)
+                                                v2 = T.axis.spatial(256, 
ax3_0_0 * 64 + (ax0_ax1_fused_0 * 2048 + ax0_ax1_fused_1 * 128 + 
ax0_ax1_fused_2 * 4 + ax0_ax1_fused_3) % 64)
                                                 T.reads(W[v1, v2])
                                                 
T.writes(W_reindex_shared_dyn[v0, v1, v2])
                                                 
T.block_attr({"buffer_dim_align": [[0, 1, 16, 8]]})
                                                 W_reindex_shared_dyn[v0, v1, 
v2] = W[v1, v2]
-                            for ax3_0_1 in range(2):
+                            for ax3_0_1 in range(4):
                                 for ax0_0 in T.unroll(2):
                                     for ax1_0 in T.unroll(1):
                                         with 
T.block("X_reindex_shared.dyn_wmma.matrix_a_o"):
                                             v0_o = T.axis.spatial(1, 0)
-                                            v1_o = T.axis.spatial(16, 
ax1_0_0_ax2_0_0_fused * 4 + ax2_0_2_ax1_0_2_fused % 2 * 2 + ax0_0)
-                                            v2_o = T.axis.spatial(16, ax3_0_0 
* 2 + ax3_0_1 + ax1_0)
+                                            v1_o = T.axis.spatial(16, 
ax1_0_0_ax2_0_0_fused * 8 + ax2_0_2_ax1_0_2_fused % 4 * 2 + ax0_0)
+                                            v2_o = T.axis.spatial(16, ax3_0_0 
* 4 + ax3_0_1 + ax1_0)
                                             T.reads(X_reindex_shared_dyn[v0_o, 
v1_o * 16:v1_o * 16 + 16, v2_o * 16:v2_o * 16 + 16])
                                             
T.writes(X_reindex_shared_dyn_wmma_matrix_a[v0_o, v1_o * 16:v1_o * 16 + 16, 
v2_o * 16:v2_o * 16 + 16])
                                             A = 
T.match_buffer(X_reindex_shared_dyn[v0_o, v1_o * 16:v1_o * 16 + 16, v2_o * 
16:v2_o * 16 + 16], (16, 16), "float16", strides=("A_s0", "A_s1"), 
scope="shared.dyn", offset_factor=16)
@@ -119,8 +119,8 @@ class TestMatmulTensorize(BaseBeforeAfter):
                                     for ax1_0 in T.unroll(1):
                                         with 
T.block("W_reindex_shared.dyn_wmma.matrix_b_o"):
                                             v0_o = T.axis.spatial(1, 0)
-                                            v1_o = T.axis.spatial(16, 
ax1_0_1_ax2_0_1_fused * 4 + ax2_0_2_ax1_0_2_fused // 2 * 2 + ax0_0)
-                                            v2_o = T.axis.spatial(16, ax3_0_0 
* 2 + ax3_0_1 + ax1_0)
+                                            v1_o = T.axis.spatial(16, 
ax1_0_1_ax2_0_1_fused * 8 + ax2_0_2_ax1_0_2_fused // 4 * 2 + ax0_0)
+                                            v2_o = T.axis.spatial(16, ax3_0_0 
* 4 + ax3_0_1 + ax1_0)
                                             T.reads(W_reindex_shared_dyn[v0_o, 
v1_o * 16:v1_o * 16 + 16, v2_o * 16:v2_o * 16 + 16])
                                             
T.writes(W_reindex_shared_dyn_wmma_matrix_b[v0_o, v1_o * 16:v1_o * 16 + 16, 
v2_o * 16:v2_o * 16 + 16])
                                             A = 
T.match_buffer(W_reindex_shared_dyn[v0_o, v1_o * 16:v1_o * 16 + 16, v2_o * 
16:v2_o * 16 + 16], (16, 16), "float16", strides=("A_s0", "A_s1"), 
scope="shared.dyn", offset_factor=16)
@@ -129,9 +129,9 @@ class TestMatmulTensorize(BaseBeforeAfter):
                                 for ax1_0_3, ax2_0_3 in T.grid(2, 2):
                                     with T.block("compute_o_update"):
                                         v0_o = T.axis.spatial(T.int64(1), ax0)
-                                        v1_o = T.axis.spatial(16, 
ax1_0_0_ax2_0_0_fused * 4 + ax2_0_2_ax1_0_2_fused % 2 * 2 + ax1_0_3)
-                                        v2_o = T.axis.spatial(16, 
ax1_0_1_ax2_0_1_fused * 4 + ax2_0_2_ax1_0_2_fused // 2 * 2 + ax2_0_3)
-                                        v3_o = T.axis.reduce(16, ax3_0_0 * 2 + 
ax3_0_1)
+                                        v1_o = T.axis.spatial(16, 
ax1_0_0_ax2_0_0_fused * 8 + ax2_0_2_ax1_0_2_fused % 4 * 2 + ax1_0_3)
+                                        v2_o = T.axis.spatial(16, 
ax1_0_1_ax2_0_1_fused * 8 + ax2_0_2_ax1_0_2_fused // 4 * 2 + ax2_0_3)
+                                        v3_o = T.axis.reduce(16, ax3_0_0 * 4 + 
ax3_0_1)
                                         
T.reads(compute_reindex_shared_dyn_wmma_accumulator[0, v1_o * 16:v1_o * 16 + 
16, v2_o * 16:v2_o * 16 + 16], X_reindex_shared_dyn_wmma_matrix_a[0, v1_o * 
16:v1_o * 16 + 16, v3_o * 16:v3_o * 16 + 16], 
W_reindex_shared_dyn_wmma_matrix_b[0, v2_o * 16:v2_o * 16 + 16, v3_o * 16:v3_o 
* 16 + 16])
                                         
T.writes(compute_reindex_shared_dyn_wmma_accumulator[0, v1_o * 16:v1_o * 16 + 
16, v2_o * 16:v2_o * 16 + 16])
                                         with T.block("compute_o"):
@@ -147,22 +147,24 @@ class TestMatmulTensorize(BaseBeforeAfter):
                         for ax0_0, ax1_0 in T.grid(2, 2):
                             with 
T.block("compute_reindex_shared.dyn_wmma.accumulator_o"):
                                 v0_o = T.axis.spatial(1, 0)
-                                v1_o = T.axis.spatial(16, 
ax1_0_0_ax2_0_0_fused * 4 + ax2_0_2_ax1_0_2_fused % 2 * 2 + ax0_0)
-                                v2_o = T.axis.spatial(16, 
ax1_0_1_ax2_0_1_fused * 4 + ax2_0_2_ax1_0_2_fused // 2 * 2 + ax1_0)
+                                v1_o = T.axis.spatial(16, 
ax1_0_0_ax2_0_0_fused * 8 + ax2_0_2_ax1_0_2_fused % 4 * 2 + ax0_0)
+                                v2_o = T.axis.spatial(16, 
ax1_0_1_ax2_0_1_fused * 8 + ax2_0_2_ax1_0_2_fused // 4 * 2 + ax1_0)
                                 
T.reads(compute_reindex_shared_dyn_wmma_accumulator[v0_o, v1_o * 16:v1_o * 16 + 
16, v2_o * 16:v2_o * 16 + 16])
                                 T.writes(compute_reindex_shared_dyn[v0_o, v1_o 
* 16:v1_o * 16 + 16, v2_o * 16:v2_o * 16 + 16])
                                 A = 
T.match_buffer(compute_reindex_shared_dyn_wmma_accumulator[v0_o, v1_o * 16:v1_o 
* 16 + 16, v2_o * 16:v2_o * 16 + 16], (16, 16), "float16", strides=("A_s0", 
"A_s1"), scope="wmma.accumulator", offset_factor=16)
                                 C = 
T.match_buffer(compute_reindex_shared_dyn[v0_o, v1_o * 16:v1_o * 16 + 16, v2_o 
* 16:v2_o * 16 + 16], (16, 16), "float16", strides=("C_s0", "C_s1"), 
scope="shared.dyn", offset_factor=16)
                                 T.tvm_store_matrix_sync(A.data, 16, 16, 16, 
A.elem_offset // A.strides[0] // 16 * (A.strides[0] // 16) + A.elem_offset % 
A.strides[0] // 16, T.tvm_access_ptr(T.type_annotation("float16"), C.data, 
C.elem_offset, C.strides[0] * 16, 2), C.strides[0], "row_major")
-                        for ax0_1, ax1 in T.grid(32, 32):
-                            with T.block("compute_reindex_shared.dyn"):
-                                v0 = T.axis.spatial(1, 0)
-                                v1 = T.axis.spatial(256, ax1_0_0_ax2_0_0_fused 
* 64 + ax2_0_2_ax1_0_2_fused % 2 * 32 + ax0_1)
-                                v2 = T.axis.spatial(256, ax1_0_1_ax2_0_1_fused 
* 64 + ax2_0_2_ax1_0_2_fused // 2 * 32 + ax1)
-                                T.reads(compute_reindex_shared_dyn[v0, v1, v2])
-                                T.writes(compute[v1, v2])
-                                T.block_attr({"buffer_dim_align": [[0, 1, 16, 
4]]})
-                                compute[v1, v2] = 
compute_reindex_shared_dyn[v0, v1, v2]
+                        for ax0_ax1_fused_0 in range(8):
+                            for ax0_ax1_fused_1 in T.thread_binding(32, 
thread="threadIdx.x"):
+                                for ax0_ax1_fused_2 in T.vectorized(4):
+                                    with T.block("compute_reindex_shared.dyn"):
+                                        v0 = T.axis.spatial(1, 0)
+                                        v1 = T.axis.spatial(256, 
ax1_0_0_ax2_0_0_fused * 128 + ax2_0_2_ax1_0_2_fused % 4 * 32 + (ax0_ax1_fused_0 
* 128 + ax0_ax1_fused_1 * 4 + ax0_ax1_fused_2) // 32)
+                                        v2 = T.axis.spatial(256, 
ax1_0_1_ax2_0_1_fused * 128 + ax2_0_2_ax1_0_2_fused // 4 * 32 + 
(ax0_ax1_fused_0 * 128 + ax0_ax1_fused_1 * 4 + ax0_ax1_fused_2) % 32)
+                                        T.reads(compute_reindex_shared_dyn[v0, 
v1, v2])
+                                        T.writes(compute[v1, v2])
+                                        T.block_attr({"buffer_dim_align": [[0, 
1, 16, 4]]})
+                                        compute[v1, v2] = 
compute_reindex_shared_dyn[v0, v1, v2]
 
     # fmt: on
 

Reply via email to