Skip to content

[Example] Optimize Tilus Hopper matmuls to beat cuBLAS - #159

Merged
yaoyaoding merged 6 commits into
NVIDIA:mainfrom
WilliamZhang20:hopper-faster
Aug 13, 2026
Merged

[Example] Optimize Tilus Hopper matmuls to beat cuBLAS#159
yaoyaoding merged 6 commits into
NVIDIA:mainfrom
WilliamZhang20:hopper-faster

Conversation

@WilliamZhang20

@WilliamZhang20 WilliamZhang20 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Workload: FP16 8192 x 8192 x 8192 GEMM on H100 80 GB HBM3 SXM.

Version Latency (ms) TFLOP/s vs cuBLAS (%)
v0 3.345 328.7 43.5
v1 2.026 542.7 71.9
v2 2.173 506.0 67.0
v3 1.905 577.1 76.4
v4 1.680 654.5 86.7
v5 1.607 684.0 90.6
v6 1.351 813.9 107.8
cuBLAS 1.456 755.0 100.0

@copy-pr-bot

copy-pr-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@WilliamZhang20 WilliamZhang20 changed the title Optimize Tilus Hopper matmuls to beat cuBLAS [Examples] Optimize Tilus Hopper matmuls to beat cuBLAS Aug 11, 2026
@WilliamZhang20 WilliamZhang20 changed the title [Examples] Optimize Tilus Hopper matmuls to beat cuBLAS [Example] Optimize Tilus Hopper matmuls to beat cuBLAS Aug 11, 2026

@yaoyaoding yaoyaoding left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @WilliamZhang20 ! It's cool.

Could you double check whether the performance change after reverting the change to mbarrier_alloc_ctx.py?

Comment thread examples/hopper_matmul/matmul_v5.py Outdated
Comment thread python/tilus/backends/contexts/mbarrier_alloc_ctx.py Outdated
@yaoyaoding

Copy link
Copy Markdown
Member

/ok to test cd59da3

@yaoyaoding

Copy link
Copy Markdown
Member

added #160 to fix a issue due to tvm-ffi upgrade, which breaks the ci.

need rebase to main after merging the PR.

@yaoyaoding

Copy link
Copy Markdown
Member

Hi @WilliamZhang20 , can you rebase to the main branch to include the #160 fix? thanks!

WilliamZhang20 and others added 6 commits August 11, 2026 17:31
Signed-off-by: William Zhang <wzhang20@yahoo.com>
Signed-off-by: William Zhang <wzhang20@yahoo.com>
Signed-off-by: William Zhang <wzhang20@yahoo.com>
This reverts commit 6e8bbbe.

Tutorial docs are deferred to a separate branch/PR to keep this one scoped
to the Hopper matmul kernels.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: William Zhang <wzhang20@yahoo.com>
v4 was pinned to num_stages=2 on the theory that a deliberately shallow
pipeline would place it between v3 and v5. Measured in a paired benchmark it
was 0.1% *slower* than v3, so the two consumer warp groups bought nothing:
the consumer is synchronous (wait_group(0) after every commit), and with two
stages the producer can be at most one tile ahead, so every consumer drain
becomes a producer stall shortly after.

Use three stages, and enable the 4-wide tile raster the kernel already
implements. On an H100 at 8192^3 fp16, median of three fresh processes:

  v3 1.93 ms -> v4 1.73 ms -> v5 1.62 ms -> v6 1.36 ms

monotonic in 3/3 runs and under NCU. v4 moves 572 -> 637 TFLOP/s, tensor
pipe utilization 68 -> 81%, DRAM throughput 35 -> 27%.

swizzle_size=4 was picked from a 7-config sweep: it had the tightest
run-to-run spread (1.2% vs 7.4% for swizzle 2), and matching v5 keeps v5
attributable purely to its overlapped WGMMA groups.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: William Zhang <wzhang20@yahoo.com>
Restore upstream mbarrier_alloc_ctx.py (NVIDIA#158) and fix the kernels instead.

v0-v2 called free_shared() on their staging buffers before the epilogue.
Barriers are placed after the whole function is emitted, from the allocator
static free list, so that returned a slot the TMA engine writes throughout
the loop above and a barrier could land inside a live TMA destination. The
kernel still ran and still produced mostly-correct output, but dropped NaNs
into ~0.5-1% of the result on some launches and not others. The frees
reclaimed nothing (the epilogue allocates no shared memory), so drop them.

Verified: 20 runs each of v0/v1/v2 are bit-exact with zero non-finite values,
and in the generated CUDA the barrier now sits at byte offset 16384, directly
past both 8192-byte staging buffers. No measurable performance change --
v3-v6 never called free_shared, so their codegen is identical either way.

Also collapse `with self.single_warp(): with self.single_thread():` to a
single `with self.single_thread():` in v4, v5 and v6 (8 sites). Both narrow
to thread 0 of the enclosing group, so the outer scope was a no-op.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: William Zhang <wzhang20@yahoo.com>
@WilliamZhang20

Copy link
Copy Markdown
Contributor Author

rebased

@yaoyaoding

Copy link
Copy Markdown
Member

/ok to test a69d42c

@yaoyaoding

Copy link
Copy Markdown
Member

thank you!

@yaoyaoding
yaoyaoding merged commit d8fc440 into NVIDIA:main Aug 13, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants