Skip to content

[C2H] Add buffer copy helpers and stream-aware offset generators - #12263

Merged
oleksandr-pavlyk merged 8 commits into
NVIDIA:mainfrom
oleksandr-pavlyk:c2h-utilities-and-tests
Nov 2, 2026
Merged

oleksandr-pavlyk merged 8 commits into
NVIDIA:mainfrom
oleksandr-pavlyk:c2h-utilities-and-tests

Conversation

@oleksandr-pavlyk

@oleksandr-pavlyk oleksandr-pavlyk commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Add synchronized host copies, scalar reads, buffer matchers, and a legacy default-stream helper. Extend uniform offset generation to explicit streams with validated sizes and consistent logical buffer sizes.

Initialize custom-type generator storage before whole-object copies and expand tests for buffer utilities, generators, and stream handling.

Description

This PR provides focused subset of changes from #11374 .

closes #11346

Checklist

  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

Add synchronized host copies, scalar reads, buffer matchers, and a legacy
default-stream helper. Extend uniform offset generation to explicit streams
with validated sizes and consistent logical buffer sizes.

Initialize custom-type generator storage before whole-object copies and
expand tests for buffer utilities, generators, and stream handling.
@oleksandr-pavlyk
oleksandr-pavlyk requested review from a team as code owners October 26, 2026 18:23
@github-project-automation github-project-automation Bot moved this to Todo in CCCL Oct 26, 2026
@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Review in CCCL Oct 26, 2026
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 713d911
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: 5c02de3b-fde5-46e6-b351-214c46d3883a
Commits

Reviewing files that changed from the base of the PR and between c05158c and 94c8418.

Files selected for processing: 1
  • c2h/include/c2h/buffer_utils.cuh

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Summary

Summary by CodeRabbit

  • New Features
    • Added stream-aware uniform offset generation, with utilities for creating device buffers or paired device and host buffers.
    • Added helpers to copy device data to the host, read a single device value, and compare device buffers with host ranges.
    • Added host-buffer creation with a specified fill value and access to a default stream reference.
  • Bug Fixes
    • Buffer comparisons now require matching sizes as well as matching values.
    • Invalid offset counts and undersized output buffers are rejected with an error.
    • Stream-aware operations reject streams associated with a different device.

C2H gains checked, stream-aware uniform-offset generation and buffer helpers. The changes also add device-to-host copy, single-value read, and device-buffer comparison APIs, with tests for their behavior.

Changes: C2H buffer workflows

Layer / File(s) Summary
Uniform offset generation
c2h/include/c2h/generator_common.h, c2h/generators_uniform_offsets.cu, c2h/include/c2h/vector_generators.h, c2h/include/c2h/detail/generators.cuh, c2h/generators_gen_values.cu, c2h/include/c2h/buffer_generators.cuh, cub/test/catch2_test_c2h_buffers.cu
Uniform-offset sizing checks negative and overflowing counts. Generation supports a cuda::stream_ref, and helper APIs create device-only or paired host/device offset buffers. The random-value helper definition is moved into the detail header.
Buffer construction and generation
c2h/include/c2h/buffer_generators.cuh, c2h/include/c2h/checked_memory_resource.cuh, cub/test/catch2_test_c2h_buffers.cu
Buffer generators accept a configurable device-buffer type. Custom-type buffers are zeroed before initialization, and host-buffer creation gains a fill-value overload. Tests cover generated buffers and custom-type values.
Stream-aware copying and matching
c2h/include/c2h/device_and_stream.h, c2h/include/c2h/buffer_utils.cuh, c2h/include/c2h/catch2_test_helper.h, cub/test/catch2_test_c2h_buffers.cu
New helpers copy device ranges to host, read one device value, and compare device buffers with host ranges. The vector matcher now also requires equal sizes.

Assessment against linked issues

Objective Addressed Explanation
Make DECLARE_LAUNCH_WRAPPER and DECLARE_TMPL_LAUNCH_WRAPPER callables accept stream-like objects, and provide launch(stream, action, ...) [#11346] ❌ No stream-aware launch wrappers or direct launch API are added.

Out-of-scope changes

Code Change Explanation
Stream-aware uniform-offset generation and offset-buffer helpers (c2h/generators_uniform_offsets.cu:33-138, c2h/include/c2h/generator_common.h:6-50, c2h/include/c2h/buffer_generators.cuh:162-197) These changes add generator and buffer APIs, not the launch wrappers or direct launch API requested by the linked issue.
Device-buffer copy, read, and comparison helpers (c2h/include/c2h/buffer_utils.cuh:26-145) These utilities do not implement the linked issue’s launch-helper requirements.

Possibly related issues

  • NVIDIA/cccl#11990 — The PR adds C2H buffer copy, comparison, and offset-generation helpers related to the issue’s C2H helper functionality.
  • NVIDIA/cccl#9310 — The PR adds reusable C2H buffer comparison, copy, and offset-generation components.

Suggested reviewers: davebayer

Change: Feature

Merge Risk: Minimal · up to 94c84

The reviewed changes do not retain an established merge-blocking risk.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

🧹 Nitpick comments: 2
cub/test/catch2_test_c2h_buffers.cu: 1

191-192: Trivial · Maintainability & Code Quality · Quick win

suggestion: Remove the deduction guide and spell out the template arguments for check_device_offsets.

Line 210 initializes check_device_offsets through the deduction guide on Lines 191-192. The repository guideline forbids relying on deduction guides for initialization. Use explicit template arguments instead.

const check_device_offsets<cuda::std::int32_t, 5> verify_device_offsets{expected_size, expected_capacity, expected};

Then delete the deduction guide on Lines 191-192.

As per coding guidelines: "Do not rely on deduction guides for initialization; use explicit template arguments instead."

Also applies to: 210-210

Source: Coding guidelines

c2h/include/c2h/buffer_utils.cuh: 1

60-62: Trivial · Maintainability & Code Quality · Low value

suggestion: Document the new public helpers in the Doxygen format that the repository guideline requires.

copy_to_host and read_single use plain // comments. The same applies to default_stream_ref and gen_uniform_offsets_device_buffer. This PR also converts the existing @brief/@pre comments in checked_memory_resource.cuh and buffer_generators.cuh to plain comments. The guideline requires //! @brief, a //! @param[in/out/in,out] entry for every parameter, and //! @return for non-void functions. If plain comments are intentional for C2H test utilities, confirm that the guideline does not apply here.

As per coding guidelines: "Documented functions must include //! @brief, //! @param[in/out/in,out] for every parameter, and //! @return for non-void functions."

Also applies to: 90-92

Source: Coding guidelines


Review info
Run configuration
  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 2857325
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: a20d45ab-d60a-4a91-940f-1ffb4e906ce2
Commits

Reviewing files that changed from the base of the PR and between 2857325 and 3f3ed47.

Files selected for processing: 12
  • c2h/generators_gen_values.cu
  • c2h/generators_uniform_offsets.cu
  • c2h/include/c2h/buffer_generators.cuh
  • c2h/include/c2h/buffer_utils.cuh
  • c2h/include/c2h/catch2_test_helper.h
  • c2h/include/c2h/checked_memory_resource.cuh
  • c2h/include/c2h/detail/current_device.cuh
  • c2h/include/c2h/detail/generators.cuh
  • c2h/include/c2h/device_and_stream.h
  • c2h/include/c2h/generator_common.h
  • c2h/include/c2h/vector_generators.h
  • cub/test/catch2_test_c2h_buffers.cu
Files with no reviewable changes: 1
  • c2h/generators_gen_values.cu

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

@github-actions

This comment has been minimized.

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

Nitpick comments: 1
cub/test/catch2_test_c2h_buffers.cu: 1

272-272: Trivial · Maintainability & Code Quality · Quick win

suggestion: Specify the check_device_offsets template arguments.

This initialization relies on the deduction guide at Line 253. Use check_device_offsets<cuda::std::int32_t, 5> here. Remove the guide if it has no other uses. As per coding guidelines, “Do not rely on deduction guides for initialization; use explicit template arguments instead.”

Source: Coding guidelines


Review info
Run configuration
  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: a7d665e
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: dcbb563a-f4c6-48c1-a521-7c37cf074dd4
Commits

Reviewing files that changed from the base of the PR and between 3f3ed47 and 479d013.

Files selected for processing: 2
  • c2h/include/c2h/catch2_test_helper.h
  • cub/test/catch2_test_c2h_buffers.cu

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

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

Nitpick comments: 1
cub/test/catch2_test_c2h_buffers.cu: 1

590-593: Trivial · Functional Correctness · Quick win

suggestion: Compare the custom buffers byte-wise.

operator== checks only key and val. Both correct buffers have the same policy byte and zero padding because both are zero-filled, and gen writes only custom_type_state_t. A byte-level comparison is valid and detects missing generator-owned initialization.

Suggested fix
   const auto custom_buffers =
     c2h::gen_buffers<custom_type>(stream, c2h::seed_t{9012}, num_items, custom_expected, custom_expected);
   REQUIRE_THAT(custom_buffers.d_items, c2h::Equals(stream, h_custom));
+  REQUIRE_THAT(c2h::detail::to_vec(custom_buffers.d_items),
+               c2h::detail::BitwiseEqualsRange(c2h::detail::to_vec(h_custom)));

Review info
Run configuration
  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 53cf409
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: 619662e4-fdc3-41a4-975d-51f4ec8590f2
Commits

Reviewing files that changed from the base of the PR and between a29d8c4 and c71f5a2.

Files selected for processing: 1
  • cub/test/catch2_test_c2h_buffers.cu

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

@github-actions

This comment has been minimized.

Comment thread c2h/include/c2h/buffer_generators.cuh Resolved
Comment thread c2h/include/c2h/buffer_utils.cuh Resolved
Comment thread c2h/include/c2h/buffer_utils.cuh Resolved
Comment thread c2h/include/c2h/buffer_utils.cuh Resolved
Comment thread c2h/include/c2h/buffer_utils.cuh Resolved
@github-actions

This comment has been minimized.

Comment thread c2h/include/c2h/buffer_generators.cuh Resolved
Comment thread c2h/include/c2h/buffer_utils.cuh Resolved
Comment thread c2h/include/c2h/buffer_utils.cuh Resolved
Comment thread c2h/include/c2h/buffer_utils.cuh Resolved
Comment thread c2h/include/c2h/buffer_utils.cuh Resolved
Comment on lines +105 to +144
template <typename HostItems>
struct device_buffer_equals_matcher : Catch::Matchers::MatcherGenericBase
{
using T = typename HostItems::value_type;

device_buffer_equals_matcher(cuda::stream_ref stream, const HostItems& expected)
: stream{stream}
, expected{expected}
{}

bool match(const cuda::device_buffer<T>& actual) const
{
const auto device = actual.size() != 0 ? detail::pointer_device(actual.data()) : c2h::current_device();
auto actual_host = c2h::make_host_buffer<T>(stream, device, actual.size(), cuda::no_init);
c2h::copy_to_host(stream, actual, actual_host);

comparison_result = detail::compare_host_ranges(actual_host, expected);
return comparison_result.actual_size == comparison_result.expected_size && comparison_result.total_mismatches == 0;
}

protected:
std::string describe() const override
{
std::stringstream ss;
detail::print_comparison(comparison_result, ss);
return ss.str();
}

private:
cuda::stream_ref stream;
const HostItems& expected;
mutable detail::vector_compare_result_t<T> comparison_result{};
};
} // namespace detail

template <typename HostItems>
[[nodiscard]] auto Equals(cuda::stream_ref stream, const HostItems& expected)
{
return detail::device_buffer_equals_matcher<HostItems>{stream, expected};
}

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.

Q: Why do I need to pass a stream to Equals and device_buffer_equals_matcher? Can't we extract the involved streams from HostItems (if there is one)?

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.

HostItems can be a std::vector or another host range without an associated stream. Even when it has one, that stream need not be the stream producing the device buffer’s contents. The explicit stream identifies which work the comparison must wait for before reading the device data.

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.

Why can't we just:

 bool match(const cuda::device_buffer<T>& actual) const {
    actual.stream().wait();
    ..

and

template <typename HostItems>
[[nodiscard]] auto Equals(const HostItems& expected) {
  if constexpr (has_stream(expected))
    expected.stream().wait();
  return detail::device_buffer_equals_matcher<HostItems>{expected};
}

This way we ensured the content for both buffers has been finished.

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.

But computation need not be enqueued on the allocation stream so actual.stream().wait() may not be the right stream to use.

Reverted comments change which litters the changeset per
review feedback. added tests for new signature of read_single.

New signature allows read_single to implement
`read_at(stream, buffer, index)` easily.

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

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

Major · important: Order the source read on the supplied stream. · buffer_utils.cuh:74

c2h/include/c2h/buffer_utils.cuh:74
Major · Functional Correctness · Quick win

important: Order the source read on the supplied stream.

The new read_single span overload reaches this copy. On CUDA 13, cuda::copy_bytes defaults to source_access_order::any, which permits a source read before earlier writes on stream. The later stream.sync() cannot correct a stale read. Set src_access_order to cuda::source_access_order::stream. (raw.githubusercontent.com)


Review info
Run configuration
  • Source mode: Auto
  • Repository: NVIDIA/cccl
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 713d911
  • Layers: Repository YAML
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: a892f4f4-64c9-4452-94e3-7fe9649414a8
Commits

Reviewing files that changed from the base of the PR and between 879e1b4 and ca77c57.

Files selected for processing: 4
  • c2h/include/c2h/buffer_generators.cuh
  • c2h/include/c2h/buffer_utils.cuh
  • c2h/include/c2h/checked_memory_resource.cuh
  • cub/test/catch2_test_c2h_buffers.cu
Files skipped from review as they are similar to previous changes: 2
  • c2h/include/c2h/checked_memory_resource.cuh
  • c2h/include/c2h/buffer_generators.cuh

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

This ensures that `reinterpret_cast<value_t *>` starts
lifetime of the value_t object.
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

🥳 CI Workflow Results

🟩 Finished in 2h 47m: Pass: 100%/187 | Total: 3d 09h | Max: 1h 48m | Hits: 99%/214029

See results here.

@miscco miscco 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.

Looks good

@oleksandr-pavlyk
oleksandr-pavlyk merged commit 99ae81e into NVIDIA:main Nov 2, 2026
207 checks passed
@github-project-automation github-project-automation Bot moved this from In Review to Done in CCCL Nov 2, 2026
@oleksandr-pavlyk
oleksandr-pavlyk deleted the c2h-utilities-and-tests branch November 2, 2026 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Task] Make entities defined by DECLARE_LAUNCH_WRAPPER stream aware

3 participants