| 66 | |
| 67 | |
| 68 | def benchmark(M=BENCH_SIZE, N=BENCH_SIZE, K=BENCH_SIZE, |
| 69 | warmup=10, iters=100): |
| 70 | lib = ctypes.CDLL(SO_PATH) |
| 71 | lib.benchmark_kernel.argtypes = ([ctypes.c_void_p] * 3 |
| 72 | + [ctypes.c_int] * 5) |
| 73 | lib.benchmark_kernel.restype = ctypes.c_float |
| 74 | |
| 75 | A = torch.randn(M, K, dtype=torch.bfloat16, device="cuda") |
| 76 | B = torch.randn(N, K, dtype=torch.bfloat16, device="cuda") |
| 77 | D = torch.empty(M, N, dtype=torch.bfloat16, device="cuda") |
| 78 | |
| 79 | ms = lib.benchmark_kernel(A.data_ptr(), B.data_ptr(), D.data_ptr(), |
| 80 | M, N, K, warmup, iters) |
| 81 | tflops = 2 * M * N * K / (ms * 1e-3) / 1e12 |
| 82 | |
| 83 | for _ in range(warmup): |
| 84 | torch.matmul(A, B.t()) |
| 85 | torch.cuda.synchronize() |
| 86 | start = torch.cuda.Event(enable_timing=True) |
| 87 | end = torch.cuda.Event(enable_timing=True) |
| 88 | start.record() |
| 89 | for _ in range(iters): |
| 90 | torch.matmul(A, B.t()) |
| 91 | end.record() |
| 92 | torch.cuda.synchronize() |
| 93 | torch_ms = start.elapsed_time(end) / iters |
| 94 | torch_tflops = 2 * M * N * K / (torch_ms * 1e-3) / 1e12 |
| 95 | |
| 96 | print(f"Benchmark ({M}x{N}x{K}):") |
| 97 | print(f" Ours: {ms:.3f} ms, {tflops:.1f} TFLOPS") |
| 98 | print(f" Torch: {torch_ms:.3f} ms, {torch_tflops:.1f} TFLOPS") |
| 99 | print(f" Ratio: {tflops / torch_tflops:.3f}x") |
| 100 | return ms, tflops, torch_ms, torch_tflops |
| 101 | |
| 102 | |
| 103 | if __name__ == "__main__": |