Add GPU multi-head attention benchmark (NNlib vs LuxLib vs NNkernels) - #721
Open
CarloLucibello wants to merge 1 commit into
Open
Add GPU multi-head attention benchmark (NNlib vs LuxLib vs NNkernels)#721CarloLucibello wants to merge 1 commit into
CarloLucibello wants to merge 1 commit into
Conversation
Benchmarks scaled dot-product attention across NNlib's materialized `dot_product_attention`, LuxLib's `scaled_dot_product_attention`, and NNkernels' fused `flash_attention`, over sizes from tiny up to a Llama3-8B attention layer, timing both forward and the full Zygote gradient. CLI-driven (--dtypes/--impls/--causal/--sizes) so individual combinations can be measured without rerunning the suite. Includes results on an RTX 5090 under CUDA.jl 5.11 and 6.2. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a standalone GPU benchmark (
benchmark/cuda_attention/) comparing three implementations of the same scaled dot-product (multi-head) attention, across sizes from tiny up to a single Llama3-8B attention layer, timing both the forward and the full Zygote gradient (fwd+bwd).dot_product_attentionsoftmax→batched_mulscaled_dot_product_attentionflash_attentionAll three compute identical math (scale
1/√E); the script builds all three from one source tensor since each wants a differentq,k,vlayout.Usage
It's CLI-driven, so a single dtype/impl combination can be measured without rerunning the whole suite:
Timing is
minimumofCUDA.@sync(op)overBenchmarkTools.run(...; seconds, evals=1)—evals=1is per-sample (many samples within the budget), one clean synced GPU execution each, matchingcuda_softmax/bench_softmax.jl.Test machine
results_rtx5090_cuda511.txt)Results — RTX 5090 (Blackwell, sm_120), CUDA.jl 6.2 / cuDNN 6.2
n/s= path can't run that config;OOM= out of GPU memory;<impl>/fl= time relative to flash (>1 → flash faster). Times in ms, lower is better. Configs: last three are a Llama3-8B layer (E=128, H=32) at growing context.Float16
Forward
Full gradient (fwd+bwd)
BFloat16 — runs on the materialized paths only
NNlib/LuxLib work under CUDA 6.2 (they were
n/son 5.11 — cuDNN had no bf16 softmax). Flash isn/s: NNkernels'_flash_attentiondispatches only onT<:Union{Float16,Float32}at the source level, independent of CUDA version.Float32
Forward
Full gradient (fwd+bwd)
(Causal variants are in the README / raw output; causal roughly halves flash's work and slightly slows the materialized path.)
Summary
Float16sizes (3–17× faster at tiny/small), then loses fromgpt2-ishup: at Llama sizes it's ~5–6× slower on the forward and ~50–100× slower on the gradient. ForFloat32it's slower at every size. Two causes, one confirmed in source: NNkernels only takes the WMMA tensor-core path whensizeof(T)==2(soFloat32always uses the scalarmma!), and evenFloat16(which does use WMMA) trails cuDNN here — its sm_70/80-erawmmaintrinsics aren't tuned for Blackwell sm_120. On the Ampere/Ada cards NNkernels' CI targets this likely looks different.L=8192— the materialized(8192,8192,32)score tensor has 2³¹ elements, overflowing cuDNN's int32 softmax descriptor (n/s), and OOMs in Float32-causal.CUDA.jl 6.2 vs 5.11
llama3 L=4kFP32 gradient 31.9 → 24.6 ms).CUDA = "5", and even with that relaxed itsNNkernelsCUDAExthitsUndefVarErrorat runtime because CUDA.jl 6.0 renamedCU_DEVICE_ATTRIBUTE_MAX_SHARED_MEMORY_PER_BLOCK(dropped theCU_prefix). The flash columns above required a locally-dev-ed NNkernels with a compat bump + that one-line API fix (documented in the README). Worth an upstream NNkernels issue/PR.Both raw logs (
results_rtx5090_cuda511.txt,results_rtx5090_cuda62.txt) and full per-causal tables are included in the folder.🤖 Generated with Claude Code