Repository navigation
Guard cuDNN 9.8 single-query grouped SDPA with large heads - #34213
Draft
Selena Yang (selenayang888) wants to merge 1 commit into
Draft
Selena Yang (selenayang888) wants to merge 1 commit into
Selena Yang (selenayang888) wants to merge 1 commit into
Conversation
This was referenced Nov 13, 2026
This branch has not been deployed
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.
Summary
Previous PR: #34212 (Iteration 1: Add opt-in wide INT4 M1 GEMV with uint8 zero points). The source changes touch disjoint files, so this PR targets
main; its accumulated numbers were measured with every previous PR applied.Series: B0 baseline → #34212 wide GEMV → #34213 cuDNN guard (this PR) → #34214 XQA idle CTAs → #34215 chunked prefill.
Companion: ORT #33728 supplies the wide INT8 kernel included in every accumulated configuration from iteration 1 on.
Performance: Qwen3.5-2B
Accumulated package/runtime results, not isolated gains from this PR. Baseline = B0: rt-base (ORT main 2bf400a), all switches off, decoder capture off. Optimized = #34212 + #34213 (with #33728's INT8 kernel): rt-it1b, wide INT4 + wide INT8 switches on, decoder capture on. Change = Optimized decode relative to Baseline (first table) or llama.cpp (second table). The increment over the previous PR and isolated controls follow each GPU's tables; prefill is reported separately.
A100-SXM4-80GB
Baseline:
a100-review-B0; optimized:a100-review-it1bw48cap.Same optimized series versus llama.cpp
a100-review-llama(identical input IDs, same rounds):it1w48→it1bw48cap): decode +28.71% to +29.93%, TTFT +0.08% to +2.00%; decode regressions at tokens: none.B0→it1boff): decode +0.59% to +1.15%, TTFT -0.44% to -0.01%; decode regressions at tokens: none.H200
Baseline:
h200-review-B0; optimized:h200-review-it1bw48cap.Same optimized series versus llama.cpp
h200-review-llama(identical input IDs, same rounds):it1w48→it1bw48cap): decode +35.01% to +37.25%, TTFT +0.00% to +2.08%; decode regressions at tokens: none.B0→it1boff): decode -0.06% to +1.07%, TTFT -0.51% to +0.00%; decode regressions at tokens: 2048.Shared-host medians are descriptive, not statistical significance; negative rows are kept. Small increments must be remeasured on an isolated rebased PR head.
Controls And Configuration
Optimized: rt-it1b with both wide switches=1 and decoder capture on (GenAI enable_cuda_graph=1 on the decoder only; package unchanged). Capture enters the accumulated configuration here because this guard makes H200 captured output match uncaptured (40/50 to 50/50 bit-exact); its speedup comes from the existing GenAI option, not this PR's code. Default-path control: rt-it1b with all switches and capture off. cuDNN 9.8.0 is pinned on both hosts. Timing prompts have >=128 tokens and do not exercise the S=1 first-prompt defect; this is a correctness PR, not a speedup claim.
Published Qwen3.5-2B VLM package v4: 172 INT4 and 15 INT8 MatMulNBits projections, block128/uint8 zero points. FP16 KV, FPA1, context 8192, batch 1, eight CPU threads pinned to 32-39. A100 physical GPU 2; H200 physical GPU 1. llama.cpp uses Q4_K_M, CUDA graphs, flash attention and FP16 KV. Quantization/quality are not asserted equivalent.
Fresh unique-source workload: token prefixes 128/512/2048/4096/7680 of benchmark_src/16384-cache-capacity-diagnostics.txt (text SHA256 3496ea55dead1c0ca9cd72aa6b1ff4bfcfca4433262a228d193a33885d33c49d). Actual token counts/hashes come from the model tokenizer, not the manifest's historical API counts. Both engines consume identical input IDs. Exactly 128 generated tokens; fresh generator, no prefix reuse, tokenization and generator creation excluded. Two warmups + five measurements x three rotating rounds; medians of 15 measured requests per row. TTFT is synchronized native GenAI, not HTTP. Decode uses 127 first-to-last intervals. This is a new workload; do not combine it with historical repeated-seed rows.
Known Limitations
The accumulated decode increase at this step comes from decoder capture, not from the guard; the guard is the H200 correctness prerequisite for capture. Timing prompts start at 128 tokens and do not reproduce the S=1 first-prompt defect. The operator regression has not run against this private no-pybind build; retained characterization does not replace a failing-before/passing-after test. The unrelated A100 captured cached-S=8 mismatch remains unresolved.
The staged runtime binaries are frozen experiments, not benchmarks of a newly split/rebased PR head. B0 is source-built ORT baseline 2bf400a, not the published wheel or Foundry service. Full revision/build pinning, corresponding llama.cpp per-benchmark quality, CPU performance, padded/multimodal coverage and agreed RAM/VRAM budgets remain outstanding. Shared-host median ratios are descriptive; no statistical-significance, cross-GPU scaling or service-level win is claimed.
Review required: retain draft status and default-off numerical optimizations. Do not promote from these timings alone; resolve the iteration-specific failures and every WORK.md gate below.
Existing Work And Duplication
Open ORT #34111 changes cuDNN auto-selection for unshared KV buffers, and open #33424 falls back when the cuDNN graph cannot be built; both are different conditions from this cuDNN<9.9 S=1 grouped-head wrong-output guard but touch the same selection path. Merged #34164 changed cached-plan/capture handling in the same file; this branch is rebased onto it and the guard applies unchanged. The bounded search is not exhaustive duplicate clearance. cuDNN 9.9 already fixes S_q=1 issues; this guard protects older supported libraries.
Iteration-Specific Actions
Extract only the version gate and regression test. Keep it independent of the wide-kernel PR, justify the default behavior change as a correctness fix, and attach reproducer results for affected and unaffected libraries.
Quality Results
Use the same evaluation inputs/protocol and compute 100 * max(0, 1 - candidate_score / llama_score); require strictly less than 1 for each benchmark. This report does not transfer scores from other exports or models.