Skip to content

CUDA: fix CCCL version guard breaking on major version rollover - #29453

Merged
JohannesGaessler merged 3 commits into
ggml-org:masterfrom
hey-gm:fix-cccl-version-guard
Oct 8, 2026
Merged

JohannesGaessler merged 3 commits into
ggml-org:masterfrom
hey-gm:fix-cccl-version-guard

Conversation

@hey-gm

@hey-gm hey-gm commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Summary

ggml/src/ggml-cuda/argsort.cu gates STRIDED_ITERATOR_AVAILABLE on a
CCCL version check that compares the major and minor components
independently:

#if (CCCL_MAJOR_VERSION >= 3 && CCCL_MINOR_VERSION >= 1)

The minor component resets to 0 whenever a new major series is cut. On
CCCL 4.x the condition therefore evaluates as 4 >= 3 && 0 >= 1, which
is false. The macro goes undefined and argsort silently falls back to
the init_offsets path. The build still succeeds and nothing warns, so
this lands as a quiet performance regression rather than a build break.

Root cause

Comparing version components separately is only correct within the
current major series. It implicitly assumes the minor component keeps
increasing, which stops being true at every major-version boundary.

CCCL already publishes the version as a single packed integer in
MMMmmmpp form, which is what its own version header defines:

#define CCCL_VERSION 3004003
#define CCCL_MAJOR_VERSION (CCCL_VERSION / 1000000)
#define CCCL_MINOR_VERSION (((CCCL_VERSION / 1000) % 1000))
#define CCCL_PATCH_VERSION (CCCL_VERSION % 1000)

so 3.4.3 is 3004003, and "at least 3.1" is a plain >= 3001000. That
leaves a single comparison with no component arithmetic to get wrong.

The fix

-#    if (CCCL_MAJOR_VERSION >= 3 && CCCL_MINOR_VERSION >= 1)
+    // CCCL_VERSION is packed MMMmmmpp: 3.4.3 -> 3004003
+#    if (CCCL_VERSION >= 3001000)

Testing

RTX 4070 (sm_89), CUDA 13.4.92, CCCL 3.4.3, Ubuntu 26.04.

  • cmake --build build --config Release - exit 0
  • test-backend-ops test -o ARGSORT -b CUDA0 - 98/98 passed, CUDA0 OK

The new guard was checked against a hand-written "version >= 3.1"
reference across 2.9.9, 3.0.0, 3.1.0, 3.1.99, 3.2.0, 3.4.3, 3.9.9,
3.99.99, 4.0.0, 4.2.7 and 5.0.0, with no divergences. The previous
guard disagreed at 4.0.0 and 5.0.0.

Worth noting that a green test-backend-ops run does not by itself show
the guard is still taken, because the fallback path passes those tests
as well. Preprocessing the real translation unit confirms the
strided-iterator branch is the one being compiled in: counting_iterator
is present and init_offsets is not.

Note

ggml/src/ggml-cuda/top-k.cu carries the same defect with a >= 3.2
threshold. It is left untouched here to keep this change reviewable on
its own; a follow-up PR for it would be welcome.

The guard compared the major and minor components independently:

    CCCL_MAJOR_VERSION >= 3 && CCCL_MINOR_VERSION >= 1

Minor resets to 0 whenever a new major series is cut, so on CCCL 4.x
this evaluates as 4 >= 3 && 0 >= 1, i.e. false. STRIDED_ITERATOR_AVAILABLE
stops being defined and argsort silently falls back to the
init_offsets path. Nothing warns and the build still succeeds, so the
regression is a quiet performance loss rather than a compile error.

CCCL already exposes the version as a single packed integer in
MMMmmmpp form, which is what its own version header uses:

    CCCL_VERSION = MAJOR * 1000000 + MINOR * 1000 + PATCH

so 3.4.3 is 3004003 and ">= 3.1" is a plain ">= 3001000". One
comparison, with no component arithmetic left to get wrong.

Checked against a hand-written "version >= 3.1" reference over 2.9.9,
3.0.0, 3.1.0, 3.1.99, 3.2.0, 3.4.3, 3.9.9, 3.99.99, 4.0.0, 4.2.7 and
5.0.0: no divergences. The old guard disagreed at 4.0.0 and 5.0.0.

Verified on RTX 4070 (sm_89), CUDA 13.4, CCCL 3.4.3:

  - cmake --build build --config Release: exit 0
  - test-backend-ops test -o ARGSORT -b CUDA0: 98/98 passed, CUDA0 OK

Note that a passing regression test does not on its own prove the guard
is still taken, since the fallback path passes too. Preprocessing the
real translation unit confirms the strided-iterator branch is the one
compiled in: counting_iterator is present, init_offsets is not.

Signed-off-by: Heitor <heitorgm@outlook.com>
Copilot AI lite review requested due to automatic review settings September 26, 2026 03:13
@hey-gm
hey-gm requested a review from a team as a code owner September 26, 2026 03:13
@ggml-gh-bot

ggml-gh-bot Bot commented Sep 26, 2026

Copy link
Copy Markdown

Hi @hey-gm, thanks for your contribution!

Per our contribution guidelines, the automated PR checker found the following issue(s) that need your attention:

  • PR Template not respected: Please respect the template when creating a new pull request. Make sure to fill out all required sections.

Please note that maintainers reserve the right to make final decisions on PRs. If you believe there is a mistake, please comment below.

@ggml-gh-bot ggml-gh-bot Bot added the draft PR will be changed to draft by github-actions bot label Sep 26, 2026

Copilot AI left a comment

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.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

Review effort: Lite
Findings: 1 Low severity

Open (1)
What changed in this PR

Updates the CUDA argsort CCCL version guard to avoid a silent performance regression when CCCL rolls over to a new major version (where the minor resets to 0).

Changes:

  • Replace separate CCCL_MAJOR_VERSION/CCCL_MINOR_VERSION comparisons with a single packed CCCL_VERSION comparison for the STRIDED_ITERATOR_AVAILABLE gate.
  • Add a brief comment documenting CCCL’s packed version format.
File Description
ggml/​src/​ggml-cuda/​argsort.cu Fixes CCCL version gating logic so the strided-iterator path remains enabled across major version rollovers.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ggml/src/ggml-cuda/argsort.cu Outdated
@github-actions
github-actions Bot marked this pull request as draft September 26, 2026 03:33
@github-actions github-actions Bot added ggml changes relating to the ggml tensor library for machine learning CUDA Related to the CUDA backend and removed draft PR will be changed to draft by github-actions bot labels Sep 26, 2026

@ORippler ORippler left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks!

Comment thread ggml/src/ggml-cuda/argsort.cu Outdated
@ORippler
ORippler marked this pull request as ready for review October 8, 2026 07:08
Comment thread ggml/src/ggml-cuda/argsort.cu Outdated
@ORippler ORippler added the merge ready A maintainer can use this label to indicate that they consider the changes final and ready to merge. label Oct 8, 2026
@JohannesGaessler
JohannesGaessler merged commit 1167d3f into ggml-org:master Oct 8, 2026
15 of 18 checks passed
feal87 added a commit to feal87/myllama.cpp that referenced this pull request Oct 8, 2026
Upstream brings CUDA top-k/argsort/mmq fixes (PR ggml-org#28713, ggml-org#29953, ggml-org#30147,
ggml-org#29453), a DFlash output-head fix (ggml-org#30111) and a UI fix (ggml-org#29668).

Conflicts and resolution:
- top-k.cu / argsort.cu: upstream reworked the top-k selection and the same
  radix path the fork added. Take upstream's shape-based dispatch and int64_t
  fixes, keep the fork workspace cap in the shared ggml_cuda_chunk_nrows
  (GGML_CUDA_ARGSORT_CHUNK_MB) and the fork benchmark-only GGML_CUDA_TOPK_IMPL
  selector used by bench-topk.py.
- mmq.cu: upstream PR ggml-org#29953 fixes the same mul_mat_id padding over-read the
  fork patched in 1386ec2, but sizes the padding from the chosen J tile in
  both branches. Take upstream's version.
- test-backend-ops.cpp: keep the fork GGML_TOPK_BENCH shapes and add upstream's
  chunk-spanning cases.

Assisted-by: pi (deepseek-flash)
asf0 pushed a commit to asf0/strix-llama.cpp that referenced this pull request Oct 12, 2026
The 39 upstream commits after halo-box/llama.cpp's final sync. Same rules as
the previous merge: strix's side wins where the two collide, upstream's
non-conflicting changes stay, and fixes are ported into strix's code.

- server: upstream's final ggml-org#26004 (context checkpoints across slot
  save/restore) replaces strix's earlier port of it, keeping strix's on-device
  restore flags; test_slot_save.py follows upstream.
- cuda: strix's top-k (HIP radix), gated delta net and argsort kernels kept
  whole; upstream's CCCL major-version guard fix (ggml-org#29453) applied to strix's
  argsort. MMQ: upstream's out-of-bounds fix and host-side tile choice
  (ggml-org#29953) with strix's RDNA3.5 tile overrides on top; strix's fused MMQ paths
  pad src1 for the largest tile instead of the removed get_J_max. strix's
  128-column rms_norm fast path and two mmvf calls updated to upstream's new
  signatures (ggml-org#28175, warp_size).
- vulkan: strix's flash_attn_cm2.comp and topk_nary_search.comp kept whole
  (upstream's sparse cm2 FA ggml-org#30003 stays out with the rest of sparse FA).
- llama-context: strix's MTP draft vocabulary next to upstream's MoE cache.
- graph: upstream's single recurrent-state gather (ggml-org#29856) is restored and
  combined with strix's in-place gated delta net: in-place capable consumers
  keep the full gather and get their state view next to the consumer whether
  or not the rows are in place, so in-place and gathered ubatches build the
  same graph; this fixes the realloc aborts under GGML_SCHED_DEBUG_REALLOC in
  both upstream's shared-seq test and strix's seq cp graph reuse test.
- ggml-backend: alloc_buffer_n planning no longer flushes on zero-size
  tensors, which left views of a tensor larger than max_size uninitialized
  (caught by strix's test_view_init_after_max_size_split).
- SYNC.md: this fork now syncs with ggml-org/llama.cpp directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thelittlefireman pushed a commit to thelittlefireman/llama.cpp that referenced this pull request Oct 12, 2026
…-org#29453)

* CUDA: fix CCCL version guard breaking on major version rollover

The guard compared the major and minor components independently:

    CCCL_MAJOR_VERSION >= 3 && CCCL_MINOR_VERSION >= 1

Minor resets to 0 whenever a new major series is cut, so on CCCL 4.x
this evaluates as 4 >= 3 && 0 >= 1, i.e. false. STRIDED_ITERATOR_AVAILABLE
stops being defined and argsort silently falls back to the
init_offsets path. Nothing warns and the build still succeeds, so the
regression is a quiet performance loss rather than a compile error.

CCCL already exposes the version as a single packed integer in
MMMmmmpp form, which is what its own version header uses:

    CCCL_VERSION = MAJOR * 1000000 + MINOR * 1000 + PATCH

so 3.4.3 is 3004003 and ">= 3.1" is a plain ">= 3001000". One
comparison, with no component arithmetic left to get wrong.

Checked against a hand-written "version >= 3.1" reference over 2.9.9,
3.0.0, 3.1.0, 3.1.99, 3.2.0, 3.4.3, 3.9.9, 3.99.99, 4.0.0, 4.2.7 and
5.0.0: no divergences. The old guard disagreed at 4.0.0 and 5.0.0.

Verified on RTX 4070 (sm_89), CUDA 13.4, CCCL 3.4.3:

  - cmake --build build --config Release: exit 0
  - test-backend-ops test -o ARGSORT -b CUDA0: 98/98 passed, CUDA0 OK

Note that a passing regression test does not on its own prove the guard
is still taken, since the fallback path passes too. Preprocessing the
real translation unit confirms the strided-iterator branch is the one
compiled in: counting_iterator is present, init_offsets is not.

Signed-off-by: Heitor <heitorgm@outlook.com>

* Update ggml/src/ggml-cuda/argsort.cu

* Apply suggestion from @ORippler

---------

Signed-off-by: Heitor <heitorgm@outlook.com>
Co-authored-by: Oliver Simons <osimons@nvidia.com>
@BrewTestBot BrewTestBot mentioned this pull request Oct 15, 2026
1 task done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CUDA Related to the CUDA backend ggml changes relating to the ggml tensor library for machine learning merge ready A maintainer can use this label to indicate that they consider the changes final and ready to merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants