[CUDA] Gracefully disable MatMulNBits fpA_intB fast path when it cannot serve prefill (narrow-N int4)#29692
Open
justinchuby wants to merge 1 commit into
Open
Conversation
…ot serve prefill
The fpA_intB fast path (onnxruntime_USE_FPA_INTB_GEMM=ON) serves prefill
shapes (m >= 16) exclusively through the CUTLASS weight-only GEMM, because
the fused CUDA GEMV kernel only supports small m and throws "unsupported m"
otherwise. For narrow-N int4 models the CUTLASS heuristic can fail to find a
valid GEMM tile for one or more m buckets (the profiler logs "Have not found
any valid GEMM config"), so at prefill either:
* getBestConfig() returns nullopt -> the node fails with
"No valid fpA_intB MatMulNBits tactic for M=...", or
* only the small-m CUDA GEMV kernel survived -> the GEMV dispatcher throws
"unsupported m" at fpA_intB_gemv/dispatcher.h.
Because PrePack drops the original quantized weights, there is no runtime
fallback once the fast path is committed, so the model cannot run at all.
Fix: at construction, after profiling, verify every profiled m >= 16 bucket
has a usable CUTLASS GEMM tactic. If any cannot be served, disable the fast
path (only when the model did not ship pre-prepacked weights, which have their
own contract). This skips PrePack, retains the quantized weights, and lets the
default MatMulNBits kernel run correctly instead of failing at prefill.
Validated with a from-source CUDA build (USE_FPA_INTB_GEMM=ON, SM90a) on a
Qwen2.5-0.5B int4 block_size=128 model: ORT_FPA_INTB_GEMM=1 crashed with
"unsupported m" before the fix and runs to completion with output identical to
the default kernel (ORT_FPA_INTB_GEMM=0) after it.
Fixes microsoft#29691
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: justinchuby <justinchuby@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the CUDA MatMulNBits fpA_intB fast path selection so that if CUTLASS can’t provide a valid weight-only GEMM tactic for any prefill-relevant m >= 16 bucket (common in narrow‑N int4 models), the fpA_intB path is disabled early (before PrePack) to preserve original quantized weights and allow the default MatMulNBits kernel to run instead of failing at runtime.
Changes:
- After
RunGemmProfile, probes profiled power-of-twombuckets (m >= 16) and disables the fpA_intB fast path if any bucket has no usable tactic. - Applies this disablement only when weights were not shipped as pre-prepacked (
weight_prepacked == 0), preserving the offline-prepacked contract.
Comment on lines
+154
to
+156
| for (int probe_m = 16; probe_m <= max_m; probe_m *= 2) { | ||
| auto probe = gemmProfiler_->getBestConfig(probe_m, gemmId_); | ||
| if (!probe.has_value() || probe->enableCudaKernel) { |
Contributor
|
FpA_IntB is an opt-in feature, and we shall not silently fallback to non FPA_INTB when user explicitly enable FPA_INTB. Recommend solution is like: If a CUTLASS tactic is missing for any |
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.
Description
The MatMulNBits CUDA fpA_intB fast path (
onnxruntime_USE_FPA_INTB_GEMM=ON, enabled at runtime viaORT_FPA_INTB_GEMM) serves prefill shapes (m >= 16) exclusively through the CUTLASS weight-only GEMM, because the fused CUDA GEMV kernel only supports smallmand throwsunsupported m(contrib_ops/cuda/llm/fpA_intB_gemv/dispatcher.h) otherwise.For narrow-N int4 models, the CUTLASS heuristic can fail to find a valid GEMM tile for one or more
mbuckets (the profiler logsHave not found any valid GEMM config for shape ...). At prefill this leaves the fast path with no usable tactic, so the node either:getBestConfig()returnsnullopt→ fails withNo valid fpA_intB MatMulNBits tactic for M=..., ormCUDA GEMV kernel "survived" → the GEMV dispatcher throwsunsupported m.Because
PrePackdrops the original quantized weights, there is no runtime fallback once the fast path is committed — the model cannot run at all.Reported in #29691.
Fix
At construction, after
RunGemmProfile, verify that every profiledm >= 16bucket has a usable CUTLASS GEMM tactic (getBestConfigreturns a value that is not the small-m-only CUDA GEMV kernel). If any bucket cannot be served, disable the fast path — but only when the model did not ship pre-prepacked weights (those have their own contract enforced just below). Disablinghas_fpA_intB_gemm_beforePrePackskips prepacking, so the original quantized weights are retained and the defaultMatMulNBitskernel runs correctly instead of failing at prefill.Tactics are profiled per rounded power-of-two
mbucket, so probing powers of two covers the full range. For well-shaped (large-N) models every bucket has a valid GEMM tactic, so the fast path stays enabled and behavior is unchanged.Single-file change (
contrib_ops/cuda/quantization/matmul_nbits.h). The runtimenulloptguard already present inmatmul_nbits.ccis left as-is.Validation
Built ONNX Runtime from source with
--use_cuda --cmake_extra_defines onnxruntime_USE_FPA_INTB_GEMM=ON,CMAKE_CUDA_ARCHITECTURES=90a(Hopper/H200), CUDA 12.9. Repro model: Qwen2.5-0.5B-Instruct int4,block_size=128, symmetric (3-input), narrow-N attention projections.ORT_FPA_INTB_GEMM=1(before)ORT_FPA_INTB_GEMM=1(after)ORT_FPA_INTB_GEMM=0(default)unsupported mAfter the fix,
ORT_FPA_INTB_GEMM=1produces bit-identical output to the default kernel, confirming a clean fallback.