Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 22 additions & 56 deletions benchmarks/bench_tgv_gemm.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
Tests the autotuner integration with TGV BF16 GEMM kernels.
"""

import time
import csv
import torch
import torch.nn.functional as F
from flashinfer.testing.utils import bench_gpu_time_with_cudagraph

from flashinfer import tgv_gemm_sm100, autotune

Expand Down Expand Up @@ -80,25 +80,13 @@ def test_tgv_gemm_bf16_sm100_perf():

torch.cuda.synchronize()

cublas_graph = torch.cuda.CUDAGraph()

# Start graph capture
with torch.cuda.graph(cublas_graph):
for _ in range(100):
_ = F.linear(A, B.T, bias)

# Warmup the graph
for _ in range(3):
cublas_graph.replay()

torch.cuda.synchronize()

# Benchmark using CUDA graph
start_time = time.time()
cublas_graph.replay()
torch.cuda.synchronize()
end_time = time.time()
cublas_avg_time = (end_time - start_time) / 100
cublas_times = bench_gpu_time_with_cudagraph(
lambda: F.linear(A, B.T, bias),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The previous implementation captured 100 iterations within the CUDA graph to amortize launch overhead. The bench_gpu_time_with_cudagraph function defaults to num_iters_within_graph=10. To maintain consistency with the previous benchmarking methodology and ensure better amortization of kernel launch overhead, it's recommended to explicitly set num_iters_within_graph=100.

Suggested change
cublas_times = bench_gpu_time_with_cudagraph(
lambda: F.linear(A, B.T, bias),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
)
cublas_times = bench_gpu_time_with_cudagraph(
lambda: F.linear(A, B.T, bias),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
num_iters_within_graph=100,
)

cublas_avg_time = sum(cublas_times) / len(cublas_times) / 1000
print(
f"CUBLAS average time: {cublas_avg_time * 1000:.6f} ms, {flops / cublas_avg_time:.3f} TFLOPS"
)
Expand All @@ -110,48 +98,26 @@ def test_tgv_gemm_bf16_sm100_perf():

torch.cuda.synchronize()

tgv_graph = torch.cuda.CUDAGraph()

# Start graph capture
with torch.cuda.graph(tgv_graph):
for _ in range(100):
_ = tgv_gemm_sm100(A, B, bias)

# Warmup the graph
tgv_graph.replay()

torch.cuda.synchronize()

# Benchmark using CUDA graph
start_time = time.time()
tgv_graph.replay()
torch.cuda.synchronize()
end_time = time.time()

tgv_avg_time = (end_time - start_time) / 100
tgv_times = bench_gpu_time_with_cudagraph(
lambda: tgv_gemm_sm100(A, B, bias),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The previous implementation captured 100 iterations within the CUDA graph to amortize launch overhead. The bench_gpu_time_with_cudagraph function defaults to num_iters_within_graph=10. To maintain consistency with the previous benchmarking methodology and ensure better amortization of kernel launch overhead, it's recommended to explicitly set num_iters_within_graph=100.

Suggested change
tgv_times = bench_gpu_time_with_cudagraph(
lambda: tgv_gemm_sm100(A, B, bias),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
)
tgv_times = bench_gpu_time_with_cudagraph(
lambda: tgv_gemm_sm100(A, B, bias),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
num_iters_within_graph=100,
)

tgv_avg_time = sum(tgv_times) / len(tgv_times) / 1000
print(
f"TGV average time: {tgv_avg_time * 1000:.6f} ms, {flops / tgv_avg_time:.3f} TFLOPS, speedup: {cublas_avg_time / tgv_avg_time:.2f}x"
)

# Test with PDL
print("\nTesting with PDL...")
pdl_graph = torch.cuda.CUDAGraph()
with torch.cuda.graph(pdl_graph):
for _ in range(100):
_ = tgv_gemm_sm100(A, B, bias, pdl=True)

# Warmup the graph
pdl_graph.replay()

torch.cuda.synchronize()

# Benchmark using CUDA graph
start_time = time.time()
pdl_graph.replay()
torch.cuda.synchronize()
end_time = time.time()

pdl_avg_time = (end_time - start_time) / 100
pdl_times = bench_gpu_time_with_cudagraph(
lambda: tgv_gemm_sm100(A, B, bias, pdl=True),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The previous implementation captured 100 iterations within the CUDA graph to amortize launch overhead. The bench_gpu_time_with_cudagraph function defaults to num_iters_within_graph=10. To maintain consistency with the previous benchmarking methodology and ensure better amortization of kernel launch overhead, it's recommended to explicitly set num_iters_within_graph=100.

Suggested change
pdl_times = bench_gpu_time_with_cudagraph(
lambda: tgv_gemm_sm100(A, B, bias, pdl=True),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
)
pdl_times = bench_gpu_time_with_cudagraph(
lambda: tgv_gemm_sm100(A, B, bias, pdl=True),
dry_run_time_ms=100,
repeat_time_ms=500,
cold_l2_cache=False,
num_iters_within_graph=100,
)

pdl_avg_time = sum(pdl_times) / len(pdl_times) / 1000
print(
f"PDL average time: {pdl_avg_time * 1000:.6f} ms, {flops / pdl_avg_time:.3f} TFLOPS, speedup: {cublas_avg_time / pdl_avg_time:.2f}x"
)
Expand Down