Skip to content

Implement prefetching#9723

Open
gonidelis wants to merge 4 commits into
NVIDIA:mainfrom
gonidelis:prefetch_alt_design
Open

Implement prefetching#9723
gonidelis wants to merge 4 commits into
NVIDIA:mainfrom
gonidelis:prefetch_alt_design

Conversation

@gonidelis

Copy link
Copy Markdown
Member

fixes #9616 and #9698 by taking a completely different approach.

Introduces prefetching as a standalone facility: a detail::LoadPrefetch enum + detail::prefetch_tile() free function. Also shows MVP wiring of prefetching into DeviceReduce::ReduceByKey as a tuning-policy knob (ReduceByKeyPolicy::load_prefetch).

Prefecthing should not be part of BlockLoad as a template parameter. Prefetch hints only pay off with lead time. Emitting inside Load() fires the hint instructions immediately before the loads of the same addresses. Firing the same hints earlier, in the agent's schedule (before reduce_by_key's look-back machinery), wins up to −14% per CT workload.

@copy-pr-bot

copy-pr-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

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.

@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Progress in CCCL Jul 7, 2026
@gonidelis

Copy link
Copy Markdown
Member Author

See: #3126 (comment) that justifies this PR

gonidelis added 2 commits July 8, 2026 00:06
* Use 32-bit multiplication for the tile byte count (truncated anyway)
* Guard the entire bulk_l2 branch with NV_IF_TARGET(NV_PROVIDES_SM_90) instead of only the asm statement
* Handle LoadPrefetch::none inside prefetch_tile so call sites need no enablement check
* Move the Prefetch template parameter before the defaulted PrefetchStride so common call sites don't restate the stride
@gonidelis gonidelis marked this pull request as ready for review July 8, 2026 07:31
@gonidelis gonidelis requested review from a team as code owners July 8, 2026 07:31
@cccl-authenticator-app cccl-authenticator-app Bot moved this from In Progress to In Review in CCCL Jul 8, 2026
@gonidelis gonidelis requested a review from bernhardmgruber July 8, 2026 07:31
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added a new tuning option for reduce-by-key operations to help improve performance on supported GPUs.
    • Prefetch behavior can now be adjusted automatically through tuning settings for more flexible optimization.
  • Bug Fixes

    • Verified reduce-by-key results remain correct across all supported prefetch settings.
    • Improved handling for large and irregular input sizes without changing output behavior.

Walkthrough

This PR adds a LoadPrefetch enum and prefetch_tile device function to CUB's detail utilities, issuing PTX-level L1/L2/bulk_l2 prefetch hints. The ReduceByKeyPolicy gains a load_prefetch field wired through dispatch and the agent's ConsumeRange, plus a benchmark tuning knob and a new correctness test.

Changes

Reduce-by-key prefetch support

Layer / File(s) Summary
Prefetch helper primitives
cub/cub/detail/prefetch.cuh
New header defines LoadPrefetch enum, can_prefetch_from trait, and prefetch_tile emitting PTX prefetch/bulk-prefetch instructions.
Policy field and dispatch wiring
cub/cub/device/dispatch/tuning/tuning_reduce_by_key.cuh, cub/cub/device/dispatch/dispatch_reduce_by_key.cuh
ReduceByKeyPolicy gains load_prefetch (compared and printed), and dispatch code passes it into AgentReduceByKeyPolicyT instantiations.
Agent prefetch application
cub/cub/agent/agent_reduce_by_key.cuh
Adds LoadPrefetchLevel/LOAD_PREFETCH to the internal agent policy and issues prefetch_tile hints for key/value tiles inside ConsumeRange before the look-back stall.
Benchmark tuning and correctness test
cub/benchmarks/bench/reduce/by_key.cu, cub/test/catch2_test_device_reduce_by_key_env.cu
Benchmark adds TUNE_LOAD_PREFETCH wired into the policy selector; new test validates DeviceReduce::ReduceByKey output across all LoadPrefetch levels.

Assessment against linked issues

Objective Addressed Explanation
Integrate prefetch into BlockLoad/reduce-by-key agent (#9616)
Use a cuda::ptx::prefetch() wrapper specifically (#9616) PR implements prefetch via inline PTX asm in a custom prefetch_tile function rather than a cuda::ptx::prefetch() library wrapper, since the issue notes that wrapper "will become available."

Suggested reviewers: fbusato, bernhardmgruber


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

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 54e03265-c405-4ed7-9a6a-2dda8d2ab5e1

📥 Commits

Reviewing files that changed from the base of the PR and between 48ff8d1 and 010f57a.

📒 Files selected for processing (6)
  • cub/benchmarks/bench/reduce/by_key.cu
  • cub/cub/agent/agent_reduce_by_key.cuh
  • cub/cub/detail/prefetch.cuh
  • cub/cub/device/dispatch/dispatch_reduce_by_key.cuh
  • cub/cub/device/dispatch/tuning/tuning_reduce_by_key.cuh
  • cub/test/catch2_test_device_reduce_by_key_env.cu

Comment on lines +746 to +772
// Fire prefetch hints before the decoupled look-back stall inside ConsumeTile, so the
// stall hides the L2 fetch latency and the tile's data has arrived by the time it is loaded.
// prefetch_tile is a no-op for LoadPrefetch::none, so no enablement check is needed here.
// The wrapped iterators apply the policy's LOAD_MODIFIER to the user's raw pointers; unlike a
// user-supplied CacheModifiedInputIterator, this internal wrapper expresses no intent to bypass
// caches, so unwrapping it for the prefetch hint is legitimate.
const int items_to_prefetch = static_cast<int>(::cuda::std::min(num_remaining, static_cast<OffsetT>(TILE_ITEMS)));
if constexpr (::cuda::std::is_pointer_v<KeysInputIteratorT>)
{
detail::prefetch_tile<BLOCK_THREADS, AgentReduceByKeyPolicyT::LOAD_PREFETCH>(
threadIdx.x, (d_keys_in + tile_offset).ptr, items_to_prefetch);
}
else
{
detail::prefetch_tile<BLOCK_THREADS, AgentReduceByKeyPolicyT::LOAD_PREFETCH>(
threadIdx.x, d_keys_in + tile_offset, items_to_prefetch);
}
if constexpr (::cuda::std::is_pointer_v<ValuesInputIteratorT>)
{
detail::prefetch_tile<BLOCK_THREADS, AgentReduceByKeyPolicyT::LOAD_PREFETCH>(
threadIdx.x, (d_values_in + tile_offset).ptr, items_to_prefetch);
}
else
{
detail::prefetch_tile<BLOCK_THREADS, AgentReduceByKeyPolicyT::LOAD_PREFETCH>(
threadIdx.x, d_values_in + tile_offset, items_to_prefetch);
}

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the relevant area in cub/cub/agent/agent_reduce_by_key.cuh
file="cub/cub/agent/agent_reduce_by_key.cuh"
wc -l "$file"
sed -n '700,820p' "$file"

# Find prefetch_tile definitions/usages
rg -n "prefetch_tile<|prefetch_tile\s*\(" cub/cub -S

# Inspect likely definition file(s) if found
fd -a "prefetch" cub/cub

Repository: NVIDIA/cccl

Length of output: 4238


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the implementation of detail::prefetch_tile if located by search.
rg -n "template <.*prefetch_tile|prefetch_tile\(" cub -S --glob '!**/build/**'

Repository: NVIDIA/cccl

Length of output: 395


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Narrow to the specific header/namespace that defines detail::prefetch_tile.
rg -n "namespace detail|prefetch_tile" cub/cub -S --glob '*.cuh' --glob '*.cu' --glob '*.h' --glob '*.hpp'

Repository: NVIDIA/cccl

Length of output: 35907


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show the exact surrounding control flow in agent_reduce_by_key.cuh.
file="cub/cub/agent/agent_reduce_by_key.cuh"
sed -n '740,810p' "$file"

# Locate detail::prefetch_tile implementation and its handling of item counts.
rg -n "prefetch_tile" cub/cub -S --glob '*.cuh' --glob '*.cu' --glob '*.h' --glob '*.hpp' -A 25 -B 10

Repository: NVIDIA/cccl

Length of output: 17098


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the actual definition of detail::prefetch_tile.
rg -n "detail::prefetch_tile|prefetch_tile" . -S --glob '*.cuh' --glob '*.cu' --glob '*.h' --glob '*.hpp' --glob '*.cc' --glob '*.cpp' -A 30 -B 10

Repository: NVIDIA/cccl

Length of output: 16467


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect how tiles/blocks are launched and whether num_remaining can be non-positive.
rg -n "max_dim_x|num_tiles|num_remaining|ConsumeRange|tile_offset" cub/cub/agent/agent_reduce_by_key.cuh -A 20 -B 20

Repository: NVIDIA/cccl

Length of output: 11660


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '88,134p' cub/cub/detail/prefetch.cuh

Repository: NVIDIA/cccl

Length of output: 2512


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check other call sites to see whether negative item counts are expected anywhere else.
rg -n "prefetch_tile<.*\(|prefetch_tile\(" cub/cub -S --glob '*.cuh' --glob '*.cu' --glob '*.h' --glob '*.hpp' -A 8 -B 8

Repository: NVIDIA/cccl

Length of output: 7888


important: gate the prefetch hints on num_remaining > 0. prefetch_tile casts the count to unsigned, so a block that lands past the end turns a negative num_remaining into a huge byte request and can issue a runaway prefetch before the existing ConsumeTile guard skips the tile.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

😬 CI Workflow Results

🟥 Finished in 2h 35m: Pass: 94%/287 | Total: 11d 15h | Max: 2h 34m | Hits: 18%/1027667

See results here.

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

Labels

None yet

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

Integrate cuda::ptx::prefetch() to BlockLoad prefetch

1 participant