* 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>
14 KiB
14 KiB
In [1]:
import cutlass
import cutlass.cute as cute
import numpy as npIn [2]:
@cute.jit
def print_example(a: cutlass.Int32, b: cutlass.Constexpr[int]):
"""
Demonstrates different printing methods in CuTe and how they handle static vs dynamic values.
This example shows:
1. How Python's `print` function works with static values at compile time but can't show dynamic values
2. How `cute.printf` can display both static and dynamic values at runtime
3. The difference between types in static vs dynamic contexts
4. How layouts are represented in both printing methods
Args:
a: A dynamic Int32 value that will be determined at runtime
b: A static (compile-time constant) integer value
"""
# Use Python `print` to print static information
print(">>>", b) # => 2
# `a` is dynamic value
print(">>>", a) # => ?
# Use `cute.printf` to print dynamic information
cute.printf(">?? {}", a) # => 8
cute.printf(">?? {}", b) # => 2
print(">>>", type(a)) # => <class 'cutlass.Int32'>
print(">>>", type(b)) # => <class 'int'>
layout = cute.make_layout((a, b))
print(">>>", layout) # => (?,2):(1,?)
cute.printf(">?? {}", layout) # => (8,2):(1,8)In [3]:
print_example(cutlass.Int32(8), 2)>>> 2 >>> ? >>> Int32 >>> <class 'int'> >>> (?,2):(1,?) >?? 8 >?? 2 >?? (8,2):(1,8)
In [4]:
print_example_compiled = cute.compile(print_example, cutlass.Int32(8), 2)>>> 2 >>> ? >>> Int32 >>> <class 'int'> >>> (?,2):(1,?)
In [5]:
print_example_compiled(cutlass.Int32(8))>?? 8 >?? 2 >?? (8,2):(1,8)
In [6]:
@cute.jit
def format_string_example(a: cutlass.Int32, b: cutlass.Constexpr[int]):
"""
Format string is evaluated at compile time.
"""
print(f"a: {a}, b: {b}")
layout = cute.make_layout((a, b))
print(f"layout: {layout}")
print("Direct run output:")
format_string_example(cutlass.Int32(8), 2)Direct run output: a: ?, b: 2 layout: (?,2):(1,?)
In [7]:
from cutlass.cute.runtime import from_dlpack
@cute.jit
def print_tensor_basic(x: cute.Tensor):
# Print the tensor
print("Basic output:")
cute.print_tensor(x)
@cute.jit
def print_tensor_verbose(x: cute.Tensor):
# Print the tensor with verbose mode
print("Verbose output:")
cute.print_tensor(x, verbose=True)
@cute.jit
def print_tensor_slice(x: cute.Tensor, coord: tuple):
# slice a 2D tensor from the 3D tensor
sliced_data = cute.slice_(x, coord)
y = cute.make_rmem_tensor(sliced_data.layout, sliced_data.element_type)
# Convert to TensorSSA format by loading the sliced data into the fragment
y.store(sliced_data.load())
print("Slice output:")
cute.print_tensor(y)In [8]:
def tensor_print_example1():
shape = (4, 3, 2)
# Creates [0,...,23] and reshape to (4, 3, 2)
data = np.arange(24, dtype=np.float32).reshape(*shape)
print_tensor_basic(from_dlpack(data))
tensor_print_example1()Basic output:
tensor(raw_ptr(0x000000000a5f1d50: f32, generic, align<4>) o (4,3,2):(6,2,1), data=
[[[ 0.000000, 2.000000, 4.000000, ],
[ 6.000000, 8.000000, 10.000000, ],
[ 12.000000, 14.000000, 16.000000, ],
[ 18.000000, 20.000000, 22.000000, ]],
[[ 1.000000, 3.000000, 5.000000, ],
[ 7.000000, 9.000000, 11.000000, ],
[ 13.000000, 15.000000, 17.000000, ],
[ 19.000000, 21.000000, 23.000000, ]]])
In [9]:
def tensor_print_example2():
shape = (4, 3)
# Creates [0,...,11] and reshape to (4, 3)
data = np.arange(12, dtype=np.float32).reshape(*shape)
print_tensor_verbose(from_dlpack(data))
tensor_print_example2()Verbose output: tensor(raw_ptr(0x000000000a814cc0: f32, generic, align<4>) o (4,3):(3,1), data= ( (0,0)= 0.000000 (0,1)= 1.000000 (0,2)= 2.000000 (1,0)= 3.000000 (1,1)= 4.000000 (1,2)= 5.000000 (2,0)= 6.000000 (2,1)= 7.000000 (2,2)= 8.000000 (3,0)= 9.000000 (3,1)= 10.000000 (3,2)= 11.000000 )
In [10]:
def tensor_print_example3():
shape = (4, 3)
# Creates [0,...,11] and reshape to (4, 3)
data = np.arange(12, dtype=np.float32).reshape(*shape)
print_tensor_slice(from_dlpack(data), (None, 0))
print_tensor_slice(from_dlpack(data), (1, None))
tensor_print_example3()Slice output:
tensor(raw_ptr(0x00007ffeeae1fc60: f32, rmem, align<32>) o (4):(3), data=
[ 0.000000, ],
[ 3.000000, ],
[Slice output:
6.000000, ],
[ 9.000000, ])
tensor(raw_ptr(0x00007ffeeae1fc60: f32, rmem, align<32>) o (3):(1), data=
[ 3.000000, ],
[ 4.000000, ],
[ 5.000000, ])
In [13]:
@cute.kernel
def print_tensor_gpu(src: cute.Tensor):
print(src)
cute.print_tensor(src)
@cute.jit
def print_tensor_host(src: cute.Tensor):
print_tensor_gpu(src).launch(grid=(1, 1, 1), block=(1, 1, 1))In [15]:
import torch
def tensor_print_example4():
a = torch.randn(4, 3, device="cuda")
cutlass.cuda.initialize_cuda_context()
print_tensor_host(from_dlpack(a))
tensor_print_example4()tensor<ptr<f32, gmem> o (4,3):(3,1)>
tensor(raw_ptr(0x00007f5f81200400: f32, gmem, align<4>) o (4,3):(3,1), data=
[[-0.690547, -0.274619, -1.659539, ],
[-1.843524, -1.648711, 1.163431, ],
[-0.716668, -1.900705, 0.592515, ],
[ 0.711333, -0.552422, 0.860237, ]])