Note

This page is a rendered version of 004_fake_tensors.ipynb available on GitHub.

Using fake tensors with the CUTLASS Operator API#

Fake tensors (e.g., torch’s FakeTensor) are useful for describing the properties of a tensor without actually allocating backing data.

This example shows how fake tensors can be used within the CUTLASS Operator API for discovering and compiling a GEMM Operator.

[1]:
import torch

import cutlass.operators as ops

torch.manual_seed(2025)

if not (status := ops.utils.device.device_or_env_supports("80")):
    print(
        f"This notebook requires a GPU with compute capability >= 80.\n{status.error}"
    )
    import sys

    sys.exit(0)

We first set up operands A, B, and out in torch’s FakeTensorMode. These will have all the properties needed for CUTLASS Operator API to construct the internal representations of tensors used for discovering and compiling operators.

[2]:
M, N, K = 128, 256, 512

with torch._subclasses.fake_tensor.FakeTensorMode():
    A_fake = torch.randint(-2, 3, (M, K), device="cuda", dtype=torch.float16)
    B_fake = torch.randint(-2, 3, (K, N), device="cuda", dtype=torch.float16)
    out_fake = torch.empty(M, N, device="cuda", dtype=torch.float16)

print(A_fake)
print(B_fake)
print(out_fake)
FakeTensor(..., device='cuda:0', size=(128, 512), dtype=torch.float16)
FakeTensor(..., device='cuda:0', size=(512, 256), dtype=torch.float16)
FakeTensor(..., device='cuda:0', size=(128, 256), dtype=torch.float16)

We can now use these fake tensors to create GemmArguments, and use these to discover and compile a compatible operator. Note that the same APIs are used in creating GemmArguments as would be used if using “real” tensors.

[3]:
args_fake = ops.GemmArguments(A_fake, B_fake, out_fake, accumulator_type=torch.float32)

target_sm = ops.utils.device.device_or_env_target_sm()
operators = ops.get_operators(args_fake, target_sm=target_sm)
assert len(operators) > 0

operator = operators[0]
compiled_artifact = operator.compile(args_fake)

The operator and compiled_artifact discovered using fake tensors above can now used for running the operator using real tensors.

[4]:
# Create real tensors
A_real = torch.randint(-2, 3, (M, K), device="cuda", dtype=torch.float16)
B_real = torch.randint(-2, 3, (K, N), device="cuda", dtype=torch.float16)
out_real = torch.empty(M, N, device="cuda", dtype=torch.float16)

args_real = ops.GemmArguments(A_real, B_real, out_real, accumulator_type=torch.float32)

# Run the operator using the compiled_artifact from resulting
# from compiling with fake tensors.
operator.run(args_real, compiled_artifact)
[5]:
ref = A_real @ B_real
torch.testing.assert_close(out_real, ref)