Skip to content

Build and test with CUDA 13.3.0#1409

Merged
rapids-bot[bot] merged 5 commits into
NVIDIA:mainfrom
bdice:cuda-13.3.0
Jun 12, 2026
Merged

Build and test with CUDA 13.3.0#1409
rapids-bot[bot] merged 5 commits into
NVIDIA:mainfrom
bdice:cuda-13.3.0

Conversation

@bdice

@bdice bdice commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Contributes to rapidsai/build-planning#286

  • uses CUDA 13.3.0 to build and test
  • updates to CUDA 13.3.0 devcontainers

Notes for Reviewers

This switches GitHub Actions workflows to the cuda-13.3.0 branch from here: rapidsai/shared-workflows#574

A future round of PRs will revert that back to main, once all of RAPIDS is migrated.

@bdice bdice added non-breaking Introduces a non-breaking change improvement Improves an existing functionality labels Jun 9, 2026
@copy-pr-bot

copy-pr-bot Bot commented Jun 9, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@bdice bdice changed the title WIP: Build and test with CUDA 13.3.0 Build and test with CUDA 13.3.0 Jun 9, 2026
@bdice bdice marked this pull request as ready for review June 10, 2026 17:35
@bdice bdice requested review from a team as code owners June 10, 2026 17:35
@bdice bdice requested review from jameslamb and rgsl888prabhu June 10, 2026 17:35
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a2af9366-0c16-44fa-809c-f167b231070f

📥 Commits

Reviewing files that changed from the base of the PR and between a6023e8 and ea27117.

📒 Files selected for processing (2)
  • cpp/src/routing/ges/lexicographic_search/brute_force_lexico.cu
  • cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu
🚧 Files skipped from review as they are similar to previous changes (2)
  • cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu
  • cpp/src/routing/ges/lexicographic_search/brute_force_lexico.cu

📝 Walkthrough

Walkthrough

This PR updates CI/workflows and dependency/environment configs to CUDA 13.3, introduces cuSPARSE 12.7/12.8+ runtime-dispatch for SpMVOp symbols (dlsym + runtime probe), and adjusts lexicographic-search sentinel initializers.

Changes

CUDA 13.3 Version Upgrade

Layer / File(s) Summary
Dependency configuration and environment definitions
dependencies.yaml, conda/environments/all_cuda-133_arch-*.yaml, CONTRIBUTING.md
The top-level CUDA matrix, conda dependency mapping, and wheel/toolkit selectors change from 13.2 to 13.3. Conda environment files are renamed from all_cuda-132_* to all_cuda-133_* and their CUDA pins updated; CONTRIBUTING.md references updated.
Build and image publishing workflows
.github/workflows/build.yaml, .github/workflows/build_test_publish_images.yaml
Multiple uses: references for conda/wheel/docs build/publish jobs are pinned to rapidsai/shared-workflows@cuda-13.3.0; the image-publish workflow default cuda_ver now includes 13.3.0.
PR, test, and alert workflows
.github/workflows/pr.yaml, .github/workflows/test.yaml, .github/workflows/trigger-breaking-change-alert.yaml
PR builder, changed-files, checks, conda build/test, wheel build/test, docs-build, and breaking-change-alert jobs now call shared workflows pinned to cuda-13.3.0 instead of tracking main.

cuSPARSE SpMVOp runtime dispatch

Layer / File(s) Summary
Header: feature macros and guard migration
cpp/src/pdlp/cusparse_view.hpp
Add CUOPT_CUSPARSE_VER_12_7_UP and CUOPT_CUSPARSE_VER_12_8_UP based on CUSPARSE_VERSION, replace CUDA_VER_13_2_UP guards with cuSPARSE-version guards, and update SpMVOp-related member/declaration gating and docs.
Implementation: dynamic signatures and runtime probe
cpp/src/pdlp/cusparse_view.cu
Introduce separate dlsym signatures for cuSPARSE 12.7 vs 12.8+, add a runtime probe via cusparseGetProperty, dispatch buffer-size and descriptor creation/run to the appropriate signature at runtime, and update is_cusparse_runtime_spmvop_supported() and create_spmv_op_plans() accordingly.

Routing lexicographic sentinel fix

Layer / File(s) Summary
Sentinel type adjustments
cpp/src/routing/ges/lexicographic_search/*
Initialize sentinel max values with std::numeric_limits<uint32_t>::max() (rather than deriving from global_min_p_’s value_type) and update an SPDX year range.

🎯 4 (Complex) | ⏱️ ~45 minutes

  • chris-maes
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately summarizes the main change: updating the project to build and test with CUDA 13.3.0, which is the primary focus across workflow files, conda environments, and dependencies.
Description check ✅ Passed The description is directly related to the changeset, explaining the context (issue #286), the main change (switching to CUDA 13.3.0), and providing helpful notes about the shared workflows dependency and future reversion plans.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@bdice

bdice commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

This project needs some nontrivial C++ changes to support CUDA 13.3. I'll push those shortly.

@bdice bdice requested a review from a team as a code owner June 11, 2026 19:43
@bdice bdice requested review from Kh4ster and chris-maes June 11, 2026 19:43

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cpp/src/pdlp/cusparse_view.cu`:
- Around line 1431-1443: is_cusparse_runtime_spmvop_supported() currently only
checks cusparseSpMVOp and can enable SpMVOp plans even when other required
symbols are missing; update this function to probe the full set of entry points
before returning true by checking
dynamic_load_runtime::function<...>("symbol").has_value() for each required
symbol (at least cusparseSpMVOp_bufferSize, cusparseSpMVOp_createDescr,
cusparseSpMVOp_createPlan, cusparseSpMVOp_destroyDescr,
cusparseSpMVOp_destroyPlan in addition to cusparseSpMVOp), and only return true
if all probes succeed; also ensure callers/wrappers referenced
(cusparse_spmvop_buffer_size,
cusparse_spmvop_descr_wrapper_t::dlsym_create/dlsym_destroy,
cusparse_spmvop_plan_wrapper_t::dlsym_create/dlsym_destroy) will not dereference
functions unless has_value() was confirmed by this probe.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 5c5edb31-52bb-4a82-ae54-e282591b0a7d

📥 Commits

Reviewing files that changed from the base of the PR and between 7b5635a and 2b98991.

📒 Files selected for processing (4)
  • cpp/src/pdlp/cusparse_view.cu
  • cpp/src/pdlp/cusparse_view.hpp
  • cpp/src/routing/ges/lexicographic_search/brute_force_lexico.cu
  • cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu

Comment on lines +1431 to +1443
#if CUOPT_CUSPARSE_VER_12_7_UP
#if !CUOPT_CUSPARSE_VER_12_8_UP
// Headers older than cuSPARSE 12.8 (CUDA Toolkit 13.3) cannot name the newer SpMVOp
// descriptor types, so do not call the older 12.7 signature against a 12.8+ runtime.
if (is_cusparse_runtime_12_8_or_newer()) { return false; }
#endif // !CUOPT_CUSPARSE_VER_12_8_UP
// Probe the runtime to ensure cusparseSpMVOp is supported.
static const bool supported =
dynamic_load_runtime::function<cusparseSpMVOp_sig>("cusparseSpMVOp").has_value();
return supported;
#else
return false;
#endif
#endif // CUOPT_CUSPARSE_VER_12_7_UP

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate occurrences
rg -n "is_cusparse_runtime_spmvop_supported|create_spmv_op_plans|cusparseSpMVOp_bufferSize|cusparseSpMVOp_createDescr|cusparseSpMVOp_createPlan|cusparseSpMVOp_destroyDescr|cusparseSpMVOp_destroyPlan|dlsym_create" cpp/src/pdlp/cusparse_view.cu

# Show surrounding code for the probe and gating
sed -n '1400,1520p' cpp/src/pdlp/cusparse_view.cu

# Show where create_spmv_op_plans uses the SpMVOp helpers
rg -n "create_spmv_op_plans" -n cpp/src/pdlp/cusparse_view.cu
python3 - <<'PY'
import re
path="cpp/src/pdlp/cusparse_view.cu"
with open(path,'r',encoding='utf-8') as f:
    lines=f.readlines()
for i,l in enumerate(lines,1):
    if "create_spmv_op_plans" in l:
        start=max(1,i-40); end=min(len(lines), i+140)
        print("\n--- around line",i,"---")
        print("".join(f"{j:5d}: {lines[j-1]}" for j in range(start,end+1)))
PY

Repository: NVIDIA/cuopt

Length of output: 15226


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate occurrences
rg -n "is_cusparse_runtime_spmvop_supported|create_spmv_op_plans|cusparseSpMVOp_bufferSize|cusparseSpMVOp_createDescr|cusparseSpMVOp_createPlan|cusparseSpMVOp_destroyDescr|cusparseSpMVOp_destroyPlan|dlsym_create" cpp/src/pdlp/cusparse_view.cu

# Show surrounding code for the probe and gating
sed -n '1400,1520p' cpp/src/pdlp/cusparse_view.cu

# Show where create_spmv_op_plans uses the SpMVOp helpers
rg -n "create_spmv_op_plans" -n cpp/src/pdlp/cusparse_view.cu
python3 - <<'PY'
import re
path="cpp/src/pdlp/cusparse_view.cu"
with open(path,'r',encoding='utf-8') as f:
    lines=f.readlines()
for i,l in enumerate(lines,1):
    if "create_spmv_op_plans" in l:
        start=max(1,i-40); end=min(len(lines), i+140)
        print("\n--- around line",i,"---")
        for j in range(start,end+1):
            print(f"{j:5d}: {lines[j-1]}", end='')
PY

Repository: NVIDIA/cuopt

Length of output: 15225


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "is_cusparse_runtime_spmvop_supported|create_spmv_op_plans|cusparseSpMVOp_bufferSize|cusparseSpMVOp_createDescr|cusparseSpMVOp_createPlan|cusparseSpMVOp_destroyDescr|cusparseSpMVOp_destroyPlan|dlsym_create|has_value\(\)" cpp/src/pdlp/cusparse_view.cu | head -n 200

sed -n '1410,1495p' cpp/src/pdlp/cusparse_view.cu

# narrow: extract blocks defining cusparse_spmvop_* wrappers and their dlsym_create/destroy
rg -n "cusparse_spmvop|spmvop_plan_wrapper_t|spmvop_descr_wrapper_t|spmvop_buffer_size" cpp/src/pdlp/cusparse_view.cu | head -n 200

# show a bit more around those wrappers if found
python3 - <<'PY'
import re
path="cpp/src/pdlp/cusparse_view.cu"
with open(path,'r',encoding='utf-8') as f:
    lines=f.readlines()

need_terms=[
"cusparseSpMVOp_bufferSize",
"cusparseSpMVOp_createDescr",
"cusparseSpMVOp_createPlan",
"cusparseSpMVOp_destroyDescr",
"cusparseSpMVOp_destroyPlan"
]
hits=[]
for i,l in enumerate(lines,1):
    if any(t in l for t in need_terms) and "function<" in l:
        hits.append(i)
print("function<...> hits:", hits[:40], "count", len(hits))
for i in hits[:20]:
    start=max(1,i-15); end=min(len(lines), i+25)
    print("\n--- around",i,"---")
    for j in range(start,end+1):
        print(f"{j:5d}: {lines[j-1]}", end='')
PY

Repository: NVIDIA/cuopt

Length of output: 23898


Probe the full SpMVOp symbol set (not just cusparseSpMVOp) before enabling SpMVOp plans

is_cusparse_runtime_spmvop_supported() only checks cusparseSpMVOp, but the SpMVOp plan setup path calls wrappers that dynamically load additional entry points and then immediately dereference (*fn) without has_value() guards (e.g., in cusparse_spmvop_buffer_size, cusparse_spmvop_descr_wrapper_t::dlsym_create/dlsym_destroy, and cusparse_spmvop_plan_wrapper_t::dlsym_create/dlsym_destroy). If any of these symbols are missing due to header/runtime skew, this can crash instead of cleanly falling back.

At minimum, also probe these before returning true:

  • cusparseSpMVOp_bufferSize
  • cusparseSpMVOp_createDescr
  • cusparseSpMVOp_createPlan
  • cusparseSpMVOp_destroyDescr
  • cusparseSpMVOp_destroyPlan
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/src/pdlp/cusparse_view.cu` around lines 1431 - 1443,
is_cusparse_runtime_spmvop_supported() currently only checks cusparseSpMVOp and
can enable SpMVOp plans even when other required symbols are missing; update
this function to probe the full set of entry points before returning true by
checking dynamic_load_runtime::function<...>("symbol").has_value() for each
required symbol (at least cusparseSpMVOp_bufferSize, cusparseSpMVOp_createDescr,
cusparseSpMVOp_createPlan, cusparseSpMVOp_destroyDescr,
cusparseSpMVOp_destroyPlan in addition to cusparseSpMVOp), and only return true
if all probes succeed; also ensure callers/wrappers referenced
(cusparse_spmvop_buffer_size,
cusparse_spmvop_descr_wrapper_t::dlsym_create/dlsym_destroy,
cusparse_spmvop_plan_wrapper_t::dlsym_create/dlsym_destroy) will not dereference
functions unless has_value() was confirmed by this probe.

#if !CUOPT_CUSPARSE_VER_12_8_UP
// Headers older than cuSPARSE 12.8 (CUDA Toolkit 13.3) cannot name the newer SpMVOp
// descriptor types, so do not call the older 12.7 signature against a 12.8+ runtime.
if (is_cusparse_runtime_12_8_or_newer()) { return false; }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly that this function will return false if compiled with CUDA 13.2 and run on 13.3? And true if compiled with 13.3 and run on 13.2?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's my understanding as well. Should we log here that SpMVOp is disabled to avoid performance surprises?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we won't distribute binaries compiled on cuda 13.2 so it seems like a rare case to hit.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it is rare

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I understand correctly that this function will return false if compiled with CUDA 13.2 and run on 13.3? And true if compiled with 13.3 and run on 13.2?
Yes, that is correct.

In theory since we are using dlsym I think we could leave it all up to runtime information, and let builds from 13.2 use features from 13.3 (since we have already hardcoded the signature of the newer library...) but that felt a bit strange to me and I didn't want to propose that as a tested, supported case.

Comment thread cpp/src/routing/ges/lexicographic_search/brute_force_lexico.cu Outdated
Comment thread cpp/src/routing/ges/lexicographic_search/lexicographic_search.cu Outdated
Co-authored-by: Miles Lubin <miles.lubin@gmail.com>
@Bubullzz

Copy link
Copy Markdown
Contributor

What do we think about simply removing support for SpMVOp in cusparse 12.7 and only support it in 12.8 ? The material implications this have will be that the ~15% speedup will be lost on cuda 13.2 but gained back on cuda 13.3

This would make this versionning juggle inexistent and less error prone.

@mlubin

mlubin commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

The material implications this have will be that the ~15% speedup will be lost on cuda 13.2 but gained back on cuda 13.3

IMO it's worth a bit of logic for the 15% speedup on cuda 13.2 runtimes.

@Bubullzz

Copy link
Copy Markdown
Contributor

It seems very dangerous and crumblesome, only for an edge case that might never happen. Our customers that need the fastest, bleeding edge Cuopt will be using 13.3 anyways, right ?

@mlubin

mlubin commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Our customers that need the fastest, bleeding edge Cuopt will be using 13.3 anyways, right ?

Some NVIDIA environments including brev still have containers with 12.9, so you may be assuming too much :)

@Bubullzz

Copy link
Copy Markdown
Contributor

Then this also means having a CI ensuring 13.2 does not break, in addition to 13.3.

@mlubin

mlubin commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

I don't think CI coverage is necessary but some manual testing is called for. @bdice is there any way we could test running the 13.3 compiled version on a 13.2 runtime? If not now then blocking before this code is released.

@mlubin

mlubin commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

/merge

@rapids-bot rapids-bot Bot merged commit 4b25ed7 into NVIDIA:main Jun 12, 2026
190 of 192 checks passed
@bdice

bdice commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

@mlubin Thanks for the review and help with merging. If you ever do need explicit jobs for 13.2 to be added to your CI matrix, you can do something like this: https://gist.github.com/bdice/ea5b000be16ac4a8b3e19d984048840f

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants