Repository navigation
[CUDA] Pass cached SM version to cuDNN frontend Conv graphs - #33770
Merged
Tianlei Wu (tianleiwu) merged 1 commit intoOct 31, 2026
Merged
Conversation
cudnn_frontend 1.24 - 1.31 resolves the target SM version in Graph::check_support() via Context::populate_sm_version_from_device(), which calls cudaGetDeviceProperties() unless set_sm_version() was called. Conv and ConvTranspose build a new graph per node whenever the input shape changes, so models with dynamic shapes pay one cudaGetDeviceProperties() call per Conv node per shape change (about 1 ms each on an RTX 5060 / driver 580). Set the SM version from the EP's cached device properties so check_support() skips the query. The value is the same one cuDNN frontend would compute for the current device. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
No active review issues remain, although full ORT build and end-to-end performance validation are still pending.
No open issues 🎉
What changed in this PR
This PR addresses #33769 by passing the CUDA execution provider’s cached SM version to cuDNN frontend Conv and ConvTranspose graphs, avoiding repeated device-property queries during plan rebuilds. It complements plan caching by also helping workloads where every input shape is new.
Changes:
- Set each new graph’s SM version from cached
cudaDevicePropvalues. - Document why this avoids costly queries in cuDNN frontend versions 1.24–1.31.
No actionable findings were identified. Full ORT build and end-to-end performance validation remain pending.
| File | Description |
|---|---|
onnxruntime/core/providers/cuda/nn/conv.cc |
Sets the cached SM version on new Conv frontend graphs. |
onnxruntime/core/providers/cuda/nn/conv_transpose.cc |
Applies the same optimization to ConvTranspose frontend graphs. |
Review effort: Balanced
Contributor
Author
|
@microsoft-github-policy-service agree |
Tianlei Wu (tianleiwu)
approved these changes
Oct 30, 2026
Tianlei Wu (tianleiwu)
enabled auto-merge (squash)
October 30, 2026 21:05
Tianlei Wu (tianleiwu)
merged commit Oct 31, 2026
4edd78a
into
microsoft:main
107 of 111 checks passed
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
Call
Graph::set_sm_version()on each cuDNN frontend graph thatConvandConvTransposebuild inCreateCudnnFeExecutionPlan. The value comes from the EP's cachedcudaDeviceProp(GetDeviceProp()).Starting with cudnn_frontend 1.24 (pinned since ORT 1.28;
mainpins 1.27.0),Graph::check_support()callsContext::populate_sm_version_from_device(). That function callscudaGetDeviceProperties()unless an SM version was already set. Both kernels build a new graph per node whenever the input or weight shape changes, so a model with dynamic shapes pays onecudaGetDeviceProperties()call per Conv node every time the shape changes. Whentarget_sm_version > 0,populate_sm_version_from_device()returns early. The value set here is the same one cudnn_frontend would compute for the device, so plan selection does not change.FusedConvuses the legacy cuDNN API (no frontend graph) and is unaffected.contrib_ops/cuda/bert/cudnn_fmhaare left as they are. They are cached per full graph configuration (per thread), so they rebuild only for new configurations; left out of scope.cudaDeviceGetAttribute()instead ([Auto-FE] shim: call ABI-changed CUDA runtime entry points with the loaded runtime's prototype (#1563) NVIDIA/cudnn-frontend#1566).Motivation and Context
Fixes #33769
On an RTX 5060 (driver 580),
cudaGetDeviceProperties()costs about 0.9-1.0 ms per call, almost all of it sys time. Tested with a FastConformer speech encoder (77 Conv nodes) where every audio segment has a new length:When a process-level interposer returns a cached
cudaDeviceProp, the 1.27.1 timings come back and the outputs are byte-identical. This change removes those queries from Conv/ConvTranspose graph construction; I expect the same effect, but it has not been measured in an ORT build. Details and permalinks are in the linked issue.This complements #33123 (an LRU cache of Conv plans), which helps when shapes recur but not when every shape is new. If #33123 lands first, the same two lines apply to
plan->graph.Testing
.cufiles) plus core was not practical there. I rely on CI for build and test coverage.onnxruntime/test/providers/cpu/nn/conv_op_test.cc,conv_fp16_test.ccandconv_transpose_op_test.cc. I did not add a test that countscudaGetDevicePropertiescalls, because ORT's test infrastructure has no clean way to observe them. I am happy to add one if you want.cudnn_frontend_win_dynamic_loading.patchapplied, andNV_CUDNN_FRONTEND_USE_DYNAMIC_LOADINGdefined.conv_fpropgraphs with new shapes, in the same order asCreateCudnnFeExecutionPlan: validate, build_operation_graph, create_execution_plans, check_support, build_plans.LD_PRELOADinterposer: 101 calls withoutset_sm_versionand 1 call with it (the program's one-time query, standing in for the EP's cache). Time per graph went from 2.15-2.28 ms to 1.29-1.67 ms over 3 runs each.v1.28.2.🤖 Generated with Claude Code