8.6 KiB
8.6 KiB
In [ ]:
!#nvidia-smiIn [ ]:
!#pip install nvidia-cutlassIn [ ]:
import torch
import cutlass
from cutlass.epilogue import relu
from cutlass import Tensor as FakeTensor
from cutlass.utils.profiler import CUDAEventProfiler
# This controls whether ther C++ GEMM declaration will be printed at each step. Set to `false` to
# omit this information.
print_module = True
# The Epilogue Visitor feature currently only works for SM80 and 90
from cutlass.backend.utils.device import device_cc
if device_cc() not in [80, 90]:
import sys
sys.exit()
m = 16384
n = m
k = 512
type_A = torch.float16
type_B = torch.float16
type_C = torch.float16
type_D = torch.float16
torch.manual_seed(2023)
scope_min = -4
scope_max = 4
tensor_A = torch.ceil(torch.empty(size=(m, k), dtype=type_A, device="cuda").uniform_(scope_min, scope_max))
tensor_B = torch.ceil(torch.empty(size=(k, n), dtype=type_B, device="cuda").uniform_(scope_min, scope_max))
tensor_C = torch.ceil(torch.empty(size=(m, n), dtype=type_C, device="cuda").uniform_(scope_min, scope_max))
tensor_D = torch.zeros_like(tensor_C)
plan = cutlass.op.Gemm(element=torch.float16, layout=cutlass.LayoutType.RowMajor, element_accumulator=torch.float32)In [ ]:
# Define epilogue visitor
def example_epilogue(accum, alpha, C, beta, aux, bias):
F = alpha * accum + (beta * C + aux)
E = relu(F + 1) + bias
D = E + F
return D, F
# Construct inputs and outputs
alpha = 0.5
beta = 0.5
aux = torch.ceil(torch.empty(size=(m, n), dtype=type_C, device="cuda").uniform_(scope_min, scope_max))
bias = torch.ceil(torch.empty(size=(m, 1), dtype=type_C, device="cuda").uniform_(scope_min, scope_max))
tensor_F = torch.zeros_like(tensor_D)
examples_tensors = {
"accum": FakeTensor(element=torch.float32, shape=(m, n), layout_tag=cutlass.LayoutType.RowMajor),
"alpha": alpha,
"C": tensor_C,
"beta": beta,
"aux": aux,
"bias": bias,
"D": tensor_D,
"F": tensor_F
}
# Trace the epilogue visitor
epilogue_visitor = cutlass.epilogue.trace(example_epilogue, examples_tensors)In [ ]:
visitor_args = {
"alpha": alpha, "C": tensor_C, "beta": beta,
"aux": aux, "bias": bias, "D": tensor_D, "F": tensor_F
}
plan.epilogue_visitor = epilogue_visitor
plan.run(
tensor_A, tensor_B, tensor_C, tensor_D,
visitor_args=visitor_args, print_module=print_module)In [ ]:
class TorchReference(torch.nn.Module):
def forward(self, A, B, alpha, C, beta, aux, bias):
accum = torch.matmul(A, B)
return example_epilogue(accum, alpha, C, beta, aux, bias)
torch_reference = TorchReference()
tensor_D_ref, tensor_F_ref = torch_reference(tensor_A, tensor_B, alpha, tensor_C, beta, aux, bias)
assert torch.equal(tensor_D, tensor_D_ref)
assert torch.equal(tensor_F, tensor_F_ref)In [ ]:
warmup_iterations = 10
profile_iterations = 50
# Profile CUTLASS fused kernel
duration = CUDAEventProfiler(
plan, warmup_iterations, profile_iterations,
tensor_A, tensor_B, tensor_C, tensor_D,
visitor_args=visitor_args)()
print(f"CUTLASS duration: {duration:.2f} ms")