* v4.3 update. * Update the cute_dsl_api changelog's doc link * Update version to 4.3.0 * Update the example link * Update doc to encourage user to install DSL from requirements.txt --------- Co-authored-by: Larry Wu <larwu@nvidia.com>
36 KiB
36 KiB
In [1]:
import cutlass
import cutlass.cute as cuteIn [26]:
@cute.jit
def coalesce_example():
"""
Demonstrates coalesce operation flattening and combining modes
"""
layout = cute.make_layout(
(2, (1, 6)), stride=(1, (cutlass.Int32(6), 2))
) # Dynamic stride
result = cute.coalesce(layout)
print(">>> Original:", layout)
cute.printf(">?? Original: {}", layout)
print(">>> Coalesced:", result)
cute.printf(">?? Coalesced: {}", result)
coalesce_example()>>> Original: (2,(1,6)):(1,(?,2)) >>> Coalesced: 12:1 >?? Original: (2,(1,6)):(1,(6,2)) >?? Coalesced: 12:1
In [ ]:
@cute.jit
def coalesce_post_conditions():
"""
Demonstrates coalesce operation's 3 post-conditions:
1. size(@a result) == size(@a layout)
2. depth(@a result) <= 1
3. for all i, 0 <= i < size(@a layout), @a result(i) == @a layout(i)
"""
layout = cute.make_layout(
((2, (3, 4)), (3, 2), 1), stride=((4, (8, 24)), (2, 6), 12)
)
result = cute.coalesce(layout)
print(">>> Original:", layout)
print(">>> Coalesced:", result)
print(">>> Checking post-conditions:")
print(">>> 1. Checking size remains the same after the coalesce operation:")
original_size = cute.size(layout)
coalesced_size = cute.size(result)
print(f"Original size: {original_size}, Coalesced size: {coalesced_size}")
assert coalesced_size == original_size, (
f"Size mismatch: original {original_size}, coalesced {coalesced_size}"
)
print(">>> 2. Checking depth of coalesced layout <= 1:")
depth = cute.depth(result)
print(f"Depth of coalesced layout: {depth}")
assert depth <= 1, f"Depth of coalesced layout should be <= 1, got {depth}"
print(
">>> 3. Checking layout functionality remains the same after the coalesce operation:"
)
for i in cutlass.range_constexpr(original_size):
original_value = layout(i)
coalesced_value = result(i)
print(f"Index {i}: original {original_value}, coalesced {coalesced_value}")
assert coalesced_value == original_value, (
f"Value mismatch at index {i}: original {original_value}, coalesced {coalesced_value}"
)
coalesce_post_conditions()>>> Original: ((2,(3,4)),(3,2),1):((4,(8,24)),(2,6),12) >>> Coalesced: (24,6):(4,2) >>> Checking post-conditions: >>> 1. Checking size remains the same after the coalesce operation: Original size: 144, Coalesced size: 144 >>> 2. Checking depth of coalesced layout <= 1: Depth of coalesced layout: 1 >>> 3. Checking layout functionality remains the same after the coalesce operation: Index 0: original 0, coalesced 0 Index 1: original 4, coalesced 4 Index 2: original 8, coalesced 8 Index 3: original 12, coalesced 12 Index 4: original 16, coalesced 16 Index 5: original 20, coalesced 20 Index 6: original 24, coalesced 24 Index 7: original 28, coalesced 28 Index 8: original 32, coalesced 32 Index 9: original 36, coalesced 36 Index 10: original 40, coalesced 40 Index 11: original 44, coalesced 44 Index 12: original 48, coalesced 48 Index 13: original 52, coalesced 52 Index 14: original 56, coalesced 56 Index 15: original 60, coalesced 60 Index 16: original 64, coalesced 64 Index 17: original 68, coalesced 68 Index 18: original 72, coalesced 72 Index 19: original 76, coalesced 76 Index 20: original 80, coalesced 80 Index 21: original 84, coalesced 84 Index 22: original 88, coalesced 88 Index 23: original 92, coalesced 92 Index 24: original 2, coalesced 2 Index 25: original 6, coalesced 6 Index 26: original 10, coalesced 10 Index 27: original 14, coalesced 14 Index 28: original 18, coalesced 18 Index 29: original 22, coalesced 22 Index 30: original 26, coalesced 26 Index 31: original 30, coalesced 30 Index 32: original 34, coalesced 34 Index 33: original 38, coalesced 38 Index 34: original 42, coalesced 42 Index 35: original 46, coalesced 46 Index 36: original 50, coalesced 50 Index 37: original 54, coalesced 54 Index 38: original 58, coalesced 58 Index 39: original 62, coalesced 62 Index 40: original 66, coalesced 66 Index 41: original 70, coalesced 70 Index 42: original 74, coalesced 74 Index 43: original 78, coalesced 78 Index 44: original 82, coalesced 82 Index 45: original 86, coalesced 86 Index 46: original 90, coalesced 90 Index 47: original 94, coalesced 94 Index 48: original 4, coalesced 4 Index 49: original 8, coalesced 8 Index 50: original 12, coalesced 12 Index 51: original 16, coalesced 16 Index 52: original 20, coalesced 20 Index 53: original 24, coalesced 24 Index 54: original 28, coalesced 28 Index 55: original 32, coalesced 32 Index 56: original 36, coalesced 36 Index 57: original 40, coalesced 40 Index 58: original 44, coalesced 44 Index 59: original 48, coalesced 48 Index 60: original 52, coalesced 52 Index 61: original 56, coalesced 56 Index 62: original 60, coalesced 60 Index 63: original 64, coalesced 64 Index 64: original 68, coalesced 68 Index 65: original 72, coalesced 72 Index 66: original 76, coalesced 76 Index 67: original 80, coalesced 80 Index 68: original 84, coalesced 84 Index 69: original 88, coalesced 88 Index 70: original 92, coalesced 92 Index 71: original 96, coalesced 96 Index 72: original 6, coalesced 6 Index 73: original 10, coalesced 10 Index 74: original 14, coalesced 14 Index 75: original 18, coalesced 18 Index 76: original 22, coalesced 22 Index 77: original 26, coalesced 26 Index 78: original 30, coalesced 30 Index 79: original 34, coalesced 34 Index 80: original 38, coalesced 38 Index 81: original 42, coalesced 42 Index 82: original 46, coalesced 46 Index 83: original 50, coalesced 50 Index 84: original 54, coalesced 54 Index 85: original 58, coalesced 58 Index 86: original 62, coalesced 62 Index 87: original 66, coalesced 66 Index 88: original 70, coalesced 70 Index 89: original 74, coalesced 74 Index 90: original 78, coalesced 78 Index 91: original 82, coalesced 82 Index 92: original 86, coalesced 86 Index 93: original 90, coalesced 90 Index 94: original 94, coalesced 94 Index 95: original 98, coalesced 98 Index 96: original 8, coalesced 8 Index 97: original 12, coalesced 12 Index 98: original 16, coalesced 16 Index 99: original 20, coalesced 20 Index 100: original 24, coalesced 24 Index 101: original 28, coalesced 28 Index 102: original 32, coalesced 32 Index 103: original 36, coalesced 36 Index 104: original 40, coalesced 40 Index 105: original 44, coalesced 44 Index 106: original 48, coalesced 48 Index 107: original 52, coalesced 52 Index 108: original 56, coalesced 56 Index 109: original 60, coalesced 60 Index 110: original 64, coalesced 64 Index 111: original 68, coalesced 68 Index 112: original 72, coalesced 72 Index 113: original 76, coalesced 76 Index 114: original 80, coalesced 80 Index 115: original 84, coalesced 84 Index 116: original 88, coalesced 88 Index 117: original 92, coalesced 92 Index 118: original 96, coalesced 96 Index 119: original 100, coalesced 100 Index 120: original 10, coalesced 10 Index 121: original 14, coalesced 14 Index 122: original 18, coalesced 18 Index 123: original 22, coalesced 22 Index 124: original 26, coalesced 26 Index 125: original 30, coalesced 30 Index 126: original 34, coalesced 34 Index 127: original 38, coalesced 38 Index 128: original 42, coalesced 42 Index 129: original 46, coalesced 46 Index 130: original 50, coalesced 50 Index 131: original 54, coalesced 54 Index 132: original 58, coalesced 58 Index 133: original 62, coalesced 62 Index 134: original 66, coalesced 66 Index 135: original 70, coalesced 70 Index 136: original 74, coalesced 74 Index 137: original 78, coalesced 78 Index 138: original 82, coalesced 82 Index 139: original 86, coalesced 86 Index 140: original 90, coalesced 90 Index 141: original 94, coalesced 94 Index 142: original 98, coalesced 98 Index 143: original 102, coalesced 102
In [6]:
@cute.jit
def bymode_coalesce_example():
"""
Demonstrates by-mode coalescing
"""
layout = cute.make_layout((2, (1, 6)), stride=(1, (6, 2)))
# Coalesce with mode-wise profile (1,1) = coalesce both modes
result = cute.coalesce(layout, target_profile=(1, 1))
# Print results
print(">>> Original: ", layout)
print(">>> Coalesced Result: ", result)
bymode_coalesce_example()>>> Original: (2,(1,6)):(1,(6,2)) >>> Coalesced Result: (2,6):(1,2)
In [7]:
@cute.jit
def composition_example():
"""
Demonstrates basic layout composition R = A ◦ B
"""
A = cute.make_layout((6, 2), stride=(cutlass.Int32(8), 2)) # Dynamic stride
B = cute.make_layout((4, 3), stride=(3, 1))
R = cute.composition(A, B)
# Print static and dynamic information
print(">>> Layout A:", A)
cute.printf(">?? Layout A: {}", A)
print(">>> Layout B:", B)
cute.printf(">?? Layout B: {}", B)
print(">>> Composition R = A ◦ B:", R)
cute.printf(">?? Composition R: {}", R)
composition_example()>>> Layout A: (6,2):(?,2)
>>> Layout B: (4,3):(3,1)
>>> Composition R = A ◦ B: ((2,2),3):((?{div=3},2),?)
>?? Layout A: (6,2):(8,2)
>?? Layout B: (4,3):(3,1)
>?? Composition R: ((2,2),3):((24,2),8)
In [30]:
@cute.jit
def composition_static_vs_dynamic_layout():
"""
Shows difference between static and dynamic composition results
"""
# Static version - using compile-time values
A_static = cute.make_layout((10, 2), stride=(16, 4))
B_static = cute.make_layout((5, 4), stride=(1, 5))
R_static = cute.composition(A_static, B_static)
# Static print shows compile-time info
print(">>> Static composition:")
print(">>> A_static: ", A_static)
print(">>> B_static: ", B_static)
print(">>> R_static: ", R_static)
# Dynamic version - using runtime Int32 values
A_dynamic = cute.make_layout(
(cutlass.Int32(10), cutlass.Int32(2)),
stride=(cutlass.Int32(16), cutlass.Int32(4)),
)
B_dynamic = cute.make_layout(
(cutlass.Int32(5), cutlass.Int32(4)),
stride=(cutlass.Int32(1), cutlass.Int32(5)),
)
R_dynamic = cute.composition(A_dynamic, B_dynamic)
# Dynamic printf shows runtime values
cute.printf(">?? Dynamic composition:")
cute.printf(">?? A_dynamic: {}", A_dynamic)
cute.printf(">?? B_dynamic: {}", B_dynamic)
cute.printf(">?? R_dynamic: {}", R_dynamic)
composition_static_vs_dynamic_layout()>>> Static composition: >>> A_static: (10,2):(16,4) >>> B_static: (5,4):(1,5) >>> R_static: (5,(2,2)):(16,(80,4)) >?? Dynamic composition: >?? A_dynamic: (10,2):(16,4) >?? B_dynamic: (5,4):(1,5) >?? R_dynamic: ((5,1),(2,2)):((16,4),(80,4))
In [ ]:
@cute.jit
def bymode_composition_example():
"""
Demonstrates by-mode composition using a tiler
"""
# Define the original layout A
A = cute.make_layout(
(cutlass.Int32(12), (cutlass.Int32(4), cutlass.Int32(8))),
stride=(cutlass.Int32(59), (cutlass.Int32(13), cutlass.Int32(1))),
)
# Define the tiler for by-mode composition
tiler = (3, 8) # Apply 3:1 to mode-0 and 8:1 to mode-1
# Apply by-mode composition
result = cute.composition(A, tiler)
# Print static and dynamic information
print(">>> Layout A:", A)
cute.printf(">?? Layout A: {}", A)
print(">>> Tiler:", tiler)
cute.printf(">?? Tiler: {}", tiler)
print(">>> By-mode Composition Result:", result)
cute.printf(">?? By-mode Composition Result: {}", result)
bymode_composition_example()>>> Layout A: (?,(?,?)):(?,(?,?)) >>> Tiler: (3, 8) >>> By-mode Composition Result: (3,(?,?)):(?,(?,?)) >?? Layout A: (12,(4,8)):(59,(13,1)) >?? Tiler: (3,8) >?? By-mode Composition Result: (3,(4,2)):(59,(13,1))
In [10]:
@cute.jit
def logical_divide_1d_example():
"""
Demonstrates 1D logical divide
"""
# Define the original layout
layout = cute.make_layout((4, 2, 3), stride=(2, 1, 8)) # (4,2,3):(2,1,8)
# Define the tiler
tiler = cute.make_layout(4, stride=2) # Apply to layout 4:2
# Apply logical divide
result = cute.logical_divide(layout, tiler=tiler)
# Print results
print(">>> Layout:", layout)
print(">>> Tiler :", tiler)
print(">>> Logical Divide Result:", result)
cute.printf(">?? Logical Divide Result: {}", result)
logical_divide_1d_example()>>> Layout: (4,2,3):(2,1,8) >>> Tiler : 4:2 >>> Logical Divide Result: ((2,2),(2,3)):((4,1),(2,8)) >?? Logical Divide Result: ((2,2),(2,3)):((4,1),(2,8))
In [11]:
@cute.jit
def logical_divide_2d_example():
"""
Demonstrates 2D logical divide :
Layout Shape : (M, N, L, ...)
Tiler Shape : <TileM, TileN>
Result Shape : ((TileM,RestM), (TileN,RestN), L, ...)
"""
# Define the original layout
layout = cute.make_layout(
(9, (4, 8)), stride=(59, (13, 1))
) # (9,(4,8)):(59,(13,1))
# Define the tiler
tiler = (
cute.make_layout(3, stride=3), # Apply to mode-0 layout 3:3
cute.make_layout((2, 4), stride=(1, 8)),
) # Apply to mode-1 layout (2,4):(1,8)
# Apply logical divide
result = cute.logical_divide(layout, tiler=tiler)
# Print results
print(">>> Layout:", layout)
print(">>> Tiler :", tiler)
print(">>> Logical Divide Result:", result)
cute.printf(">?? Logical Divide Result: {}", result)
logical_divide_2d_example()>>> Layout: (9,(4,8)):(59,(13,1)) >>> Tiler : (<cutlass.cute.core._Layout object at 0x7fc95a4ca7b0>, <cutlass.cute.core._Layout object at 0x7fc958160f50>) >>> Logical Divide Result: ((3,3),((2,4),(2,2))):((177,59),((13,2),(26,1))) >?? Logical Divide Result: ((3,3),((2,4),(2,2))):((177,59),((13,2),(26,1)))
In [12]:
@cute.jit
def zipped_divide_example():
"""
Demonstrates zipped divide :
Layout Shape : (M, N, L, ...)
Tiler Shape : <TileM, TileN>
Result Shape : ((TileM,TileN), (RestM,RestN,L,...))
"""
# Define the original layout
layout = cute.make_layout(
(9, (4, 8)), stride=(59, (13, 1))
) # (9,(4,8)):(59,(13,1))
# Define the tiler
tiler = (
cute.make_layout(3, stride=3), # Apply to mode-0 layout 3:3
cute.make_layout((2, 4), stride=(1, 8)),
) # Apply to mode-1 layout (2,4):(1,8)
# Apply zipped divide
result = cute.zipped_divide(layout, tiler=tiler)
# Print results
print(">>> Layout:", layout)
print(">>> Tiler :", tiler)
print(">>> Zipped Divide Result:", result)
cute.printf(">?? Zipped Divide Result: {}", result)
zipped_divide_example()>>> Layout: (9,(4,8)):(59,(13,1)) >>> Tiler : (<cutlass.cute.core._Layout object at 0x7fc95a4ca7b0>, <cutlass.cute.core._Layout object at 0x7fc9581611f0>) >>> Zipped Divide Result: ((3,(2,4)),(3,(2,2))):((177,(13,2)),(59,(26,1))) >?? Zipped Divide Result: ((3,(2,4)),(3,(2,2))):((177,(13,2)),(59,(26,1)))
In [13]:
@cute.jit
def tiled_divide_example():
"""
Demonstrates tiled divide :
Layout Shape : (M, N, L, ...)
Tiler Shape : <TileM, TileN>
Result Shape : ((TileM,TileN), RestM, RestN, L, ...)
"""
# Define the original layout
layout = cute.make_layout(
(9, (4, 8)), stride=(59, (13, 1))
) # (9,(4,8)):(59,(13,1))
# Define the tiler
tiler = (
cute.make_layout(3, stride=3), # Apply to mode-0 layout 3:3
cute.make_layout((2, 4), stride=(1, 8)),
) # Apply to mode-1 layout (2,4):(1,8)
# Apply tiled divide
result = cute.tiled_divide(layout, tiler=tiler)
# Print results
print(">>> Layout:", layout)
print(">>> Tiler :", tiler)
print(">>> Tiled Divide Result:", result)
cute.printf(">?? Tiled Divide Result: {}", result)
tiled_divide_example()>>> Layout: (9,(4,8)):(59,(13,1)) >>> Tiler : (<cutlass.cute.core._Layout object at 0x7fc9581610d0>, <cutlass.cute.core._Layout object at 0x7fc958161070>) >>> Tiled Divide Result: ((3,(2,4)),3,(2,2)):((177,(13,2)),59,(26,1)) >?? Tiled Divide Result: ((3,(2,4)),3,(2,2)):((177,(13,2)),59,(26,1))
In [14]:
@cute.jit
def flat_divide_example():
"""
Demonstrates flat divide :
Layout Shape : (M, N, L, ...)
Tiler Shape : <TileM, TileN>
Result Shape : (TileM, TileN, RestM, RestN, L, ...)
"""
# Define the original layout
layout = cute.make_layout(
(9, (4, 8)), stride=(59, (13, 1))
) # (9,(4,8)):(59,(13,1))
# Define the tiler
tiler = (
cute.make_layout(3, stride=3), # Apply to mode-0 layout 3:3
cute.make_layout((2, 4), stride=(1, 8)),
) # Apply to mode-1 layout (2,4):(1,8)
# Apply flat divide
result = cute.flat_divide(layout, tiler=tiler)
# Print results
print(">>> Layout:", layout)
print(">>> Tiler :", tiler)
print(">>> Flat Divide Result:", result)
cute.printf(">?? Flat Divide Result: {}", result)
flat_divide_example()>>> Layout: (9,(4,8)):(59,(13,1)) >>> Tiler : (<cutlass.cute.core._Layout object at 0x7fc958161430>, <cutlass.cute.core._Layout object at 0x7fc9581610d0>) >>> Flat Divide Result: (3,(2,4),3,(2,2)):(177,(13,2),59,(26,1)) >?? Flat Divide Result: (3,(2,4),3,(2,2)):(177,(13,2),59,(26,1))
In [15]:
@cute.jit
def logical_product_1d_example():
"""
Demonstrates 1D logical product
"""
# Define the original layout
layout = cute.make_layout((2, 2), stride=(4, 1)) # (2,2):(4,1)
# Define the tiler
tiler = cute.make_layout(6, stride=1) # Apply to layout 6:1
# Apply logical product
result = cute.logical_product(layout, tiler=tiler)
# Print results
print(">>> Layout:", layout)
print(">>> Tiler :", tiler)
print(">>> Logical Product Result:", result)
cute.printf(">?? Logical Product Result: {}", result)
logical_product_1d_example()>>> Layout: (2,2):(4,1) >>> Tiler : 6:1 >>> Logical Product Result: ((2,2),(2,3)):((4,1),(2,8)) >?? Logical Product Result: ((2,2),(2,3)):((4,1),(2,8))
In [16]:
@cute.jit
def blocked_raked_product_example():
"""
Demonstrates blocked and raked products
"""
# Define the original layout
layout = cute.make_layout((2, 5), stride=(5, 1))
# Define the tiler
tiler = cute.make_layout((3, 4), stride=(1, 3))
# Apply blocked product
blocked_result = cute.blocked_product(layout, tiler=tiler)
# Apply raked product
raked_result = cute.raked_product(layout, tiler=tiler)
# Print results
print(">>> Layout:", layout)
print(">>> Tiler :", tiler)
print(">>> Blocked Product Result:", blocked_result)
print(">>> Raked Product Result:", raked_result)
cute.printf(">?? Blocked Product Result: {}", blocked_result)
cute.printf(">?? Raked Product Result: {}", raked_result)
blocked_raked_product_example()>>> Layout: (2,5):(5,1) >>> Tiler : (3,4):(1,3) >>> Blocked Product Result: ((2,3),(5,4)):((5,10),(1,30)) >>> Raked Product Result: ((3,2),(4,5)):((10,5),(30,1)) >?? Blocked Product Result: ((2,3),(5,4)):((5,10),(1,30)) >?? Raked Product Result: ((3,2),(4,5)):((10,5),(30,1))
In [17]:
@cute.jit
def zipped_tiled_flat_product_example():
"""
Demonstrates zipped, tiled, and flat products
Layout Shape : (M, N, L, ...)
Tiler Shape : <TileM, TileN>
zipped_product : ((M,N), (TileM,TileN,L,...))
tiled_product : ((M,N), TileM, TileN, L, ...)
flat_product : (M, N, TileM, TileN, L, ...)
"""
# Define the original layout
layout = cute.make_layout((2, 5), stride=(5, 1))
# Define the tiler
tiler = cute.make_layout((3, 4), stride=(1, 3))
# Apply zipped product
zipped_result = cute.zipped_product(layout, tiler=tiler)
# Apply tiled product
tiled_result = cute.tiled_product(layout, tiler=tiler)
# Apply flat product
flat_result = cute.flat_product(layout, tiler=tiler)
# Print results
print(">>> Layout:", layout)
print(">>> Tiler :", tiler)
print(">>> Zipped Product Result:", zipped_result)
print(">>> Tiled Product Result:", tiled_result)
print(">>> Flat Product Result:", flat_result)
cute.printf(">?? Zipped Product Result: {}", zipped_result)
cute.printf(">?? Tiled Product Result: {}", tiled_result)
cute.printf(">?? Flat Product Result: {}", flat_result)
zipped_tiled_flat_product_example()>>> Layout: (2,5):(5,1) >>> Tiler : (3,4):(1,3) >>> Zipped Product Result: ((2,5),(3,4)):((5,1),(10,30)) >>> Tiled Product Result: ((2,5),3,4):((5,1),10,30) >>> Flat Product Result: (2,5,3,4):(5,1,10,30) >?? Zipped Product Result: ((2,5),(3,4)):((5,1),(10,30)) >?? Tiled Product Result: ((2,5),3,4):((5,1),10,30) >?? Flat Product Result: (2,5,3,4):(5,1,10,30)