Add decode benchmark comparing ONNX Attention CUDA with contrib GQA#29684
Add decode benchmark comparing ONNX Attention CUDA with contrib GQA#29684namgyu-youn wants to merge 2 commits into
Conversation
…QueryAttention Reproducible benchmark recipe requested by the TODO in microsoft#28352: five single-stream decode arms at matched config (GQA on its XQA / Flash / cuDNN SDPA kernel tiers, ONNX Attention with past/present inputs, and ONNX Attention opset-24 external cache via in-place TensorScatter + nonpad_kv_seqlen), with pinned kernel dispatch, a cross-arm output parity check (--sanity), an NVTX-annotated fixed-config mode for Nsight Systems captures (--profile), and GPU/driver/wheel provenance recorded in every log. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
Measured results and per-kernel attribution from this script (RTX PRO 6000, fp16/bf16 sweep + nsys captures): #28352 (comment) |
bb62ba0 to
475fc0d
Compare
There was a problem hiding this comment.
Pull request overview
Adds a standalone Python benchmark script under onnxruntime/test/python/transformers/ to reproduce and compare single-token decode latency across five matched “arms”: contrib GroupQueryAttention (XQA/Flash/cuDNN tiers) vs ONNX Attention (past/present path and opset-24 TensorScatter external-cache path). This supports the “Baseline Benchmark Recipe” TODO from issue #28352 by making the measurement setup reproducible and logging key provenance.
Changes:
- Introduces
benchmark_onnx_attention_vs_gqa.pythat programmatically builds ONNX Attention graphs (opset 23 past/present, opset 24 TensorScatter external cache) and benchmarks them against contrib GQA sessions. - Adds
--sanityparity mode and--profileNVTX-annotated mode, plus CSV logging and environment pinning for backend selection. - Prints GPU/driver/ORT build provenance to make published results attributable and repeatable.
| args = parser.parse_args() | ||
|
|
||
| if not torch.cuda.is_available() or "CUDAExecutionProvider" not in onnxruntime.get_available_providers(): | ||
| sys.exit("This benchmark requires a CUDA device and an onnxruntime build with the CUDA EP.") |
Review synthesis (multi-model review team)Benchmark-only file (650 lines, no ORT source changes). No Critical issues, no blockers. Integration is clean — the imported APIs ( Major (fair-comparison integrity — recommend addressing)
Minor
Nits
PraiseUnusually thorough docstrings; clean GPU-dependent checks (kernel-dispatch verification, on-device parity) were not run — no CUDA-built |
Description
Adds
onnxruntime/test/python/transformers/benchmark_onnx_attention_vs_gqa.py: a single-stream decode benchmark comparing ONNXAttention(CUDA EP) with contribGroupQueryAttention, as requested by the "Baseline Benchmark Recipe" TODO in #28352.Five arms at matched config (S_q=1, causal, no RoPE/mask/softcap; Llama-3-8B shape by default): GQA on its XQA / Flash / cuDNN SDPA kernel tiers, ONNX Attention with past/present inputs, and ONNX Attention opset-24 external cache (in-place
TensorScatter+nonpad_kv_seqlen). Includes a--sanitycross-arm output-parity check, a--profileNVTX mode for Nsight Systems captures, and GPU/driver/wheel provenance in every log.Motivation and Context
The decode-latency figures in #28352 came from informal profiling with no reproducible context; this script is the recipe to reproduce them. Benchmark-only change — no ORT source modifications, not collected by CI.
Verified on RTX PRO 6000 (SM120): all arms produce identical outputs on identical inputs (max |diff| ≤ 8e-6 fp16); fp16/bf16 sweeps repeatable within ±2 µs. Measured results will be posted on #28352.
Developed with AI assistance (Claude Code); measurements taken on real hardware and reviewed by the author.