[libcu++] Use cccl runtime in thrust tests pt 4#9778
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughCUDA testing utilities now provide pinned host buffers, deterministic samples, and buffer assertions. Count, equal, generate, and tabulate tests use CCCL streams and buffers, device-callable functors, ChangesCUDA test runtime migration
Suggested labels: Suggested reviewers: Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 53bb8cb5-345d-4a46-b561-6e3b7fee645e
📒 Files selected for processing (5)
thrust/testing/cuda/cccl_runtime_test_helper.cuhthrust/testing/cuda/count.cuthrust/testing/cuda/equal.cuthrust/testing/cuda/generate.cuthrust/testing/cuda/tabulate.cu
| template <typename T> | ||
| [[nodiscard]] _CCCL_HOST_API inline auto make_host_buffer(cuda::stream_ref stream, cuda::std::size_t size) | ||
| { | ||
| using resource_t = cuda::mr::synchronous_resource_adapter<cuda::mr::legacy_pinned_memory_resource>; | ||
| resource_t resource{cuda::mr::legacy_pinned_memory_resource{cuda::device_ref{0}}}; | ||
| return cuda::make_buffer<T>(stream, resource, size, cuda::no_init); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the helper and related test call sites.
git ls-files thrust/testing/cuda/cccl_runtime_test_helper.cuh thrust/testing/cuda | sed 's#^`#FILE` #'
echo
wc -l thrust/testing/cuda/cccl_runtime_test_helper.cuh
echo
cat -n thrust/testing/cuda/cccl_runtime_test_helper.cuh | sed -n '1,220p'
echo
echo "---- call sites ----"
rg -n "make_host_buffer|random_samples_buffer|current_test_device|legacy_pinned_memory_resource|stream_ref" thrust/testing/cuda -S
echo
echo "---- docs / declarations ----"
rg -n "legacy_pinned_memory_resource|synchronous_resource_adapter|make_buffer<|no_init" libcudacxx thrust -SRepository: NVIDIA/cccl
Length of output: 50367
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Focus on the helper docs and how these tests bind streams/devices.
echo "---- legacy_pinned_memory_resource docs ----"
sed -n '1,180p' libcudacxx/include/cuda/__memory_resource/legacy_pinned_memory_resource.h
echo
echo "---- synchronous_resource_adapter docs ----"
sed -n '1,220p' libcudacxx/include/cuda/__memory_resource/synchronous_resource_adapter.h
echo
echo "---- stream creation / device binding in thrust testing cuda ----"
rg -n "make_stream|stream_ref|current_test_device\(\)|device_ref\{|set_device|device\)" thrust/testing/cuda/*.cu thrust/testing/cuda/*.cuh -SRepository: NVIDIA/cccl
Length of output: 29273
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "---- specific callers of random_samples_buffer / make_host_buffer ----"
sed -n '1,140p' thrust/testing/cuda/count.cu
echo
sed -n '1,180p' thrust/testing/cuda/equal.cu
echo
sed -n '1,180p' thrust/testing/cuda/generate.cu
echo
sed -n '1,140p' thrust/testing/cuda/tabulate.cu
echo
sed -n '1,160p' thrust/testing/cuda/set_union.cuRepository: NVIDIA/cccl
Length of output: 16289
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,120p' libcudacxx/test/libcudacxx/cuda/ccclrt/algorithm/common.cuh
echo
rg -n "make_host_buffer\\(|random_samples_buffer\\(" thrust/testing/cuda libcudacxx/test -SRepository: NVIDIA/cccl
Length of output: 3535
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the stream constructor that takes a device.
sed -n '1,120p' libcudacxx/include/cuda/__stream/stream.hRepository: NVIDIA/cccl
Length of output: 4192
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,120p' libcudacxx/test/libcudacxx/cuda/ccclrt/algorithm/common.cuhRepository: NVIDIA/cccl
Length of output: 3223
🏁 Script executed:
#!/bin/bash
set -euo pipefail
cat -n libcudacxx/test/libcudacxx/cuda/ccclrt/algorithm/common.cuh | sed -n '1,120p'
echo
cat -n libcudacxx/include/cuda/__stream/stream.h | sed -n '1,120p'Repository: NVIDIA/cccl
Length of output: 8730
important: thrust/testing/cuda/cccl_runtime_test_helper.cuh:48-57 thread cuda::device_ref through make_host_buffer() and random_samples_buffer() instead of hard-coding cuda::device_ref{0}. These helpers are used with streams and device buffers bound to current_test_device(), so non-zero-device runs can tie pinned host memory to the wrong device.
Source: MCP tools
| auto result = make_host_buffer<T>(stream, size); | ||
| stream.sync(); | ||
|
|
||
| const auto generator = unittest::generate_random_sample<RandomT>{}; | ||
| for (cuda::std::size_t i = 0; i < size; ++i) | ||
| { | ||
| result[i] = static_cast<T>(generator(static_cast<unsigned int>(first + i))); |
There was a problem hiding this comment.
🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the target file and locate the helper types it uses.
git ls-files thrust/testing/cuda/cccl_runtime_test_helper.cuh
printf '\n--- file outline ---\n'
ast-grep outline thrust/testing/cuda/cccl_runtime_test_helper.cuh --view expanded || true
printf '\n--- relevant lines ---\n'
cat -n thrust/testing/cuda/cccl_runtime_test_helper.cuh | sed -n '1,220p'
printf '\n--- search for make_host_buffer and buffer accessors ---\n'
rg -n "make_host_buffer|get_unsynchronized|unsynchronized|operator\\[" thrust/testing -g'*.cuh' -g'*.cu' -g'*.cpp' -g'*.h' || trueRepository: NVIDIA/cccl
Length of output: 5418
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Focus on the helper implementation and any nearby buffer type definitions/usages.
cat -n thrust/testing/cuda/cccl_runtime_test_helper.cuh | sed -n '1,180p'
printf '\n--- search exact accessor names in repo ---\n'
rg -n "get_unsynchronized|unsynchronized" thrust libcudacxx cub c python -g'*.h' -g'*.hpp' -g'*.hh' -g'*.cuh' -g'*.cu' -g'*.cpp' || trueRepository: NVIDIA/cccl
Length of output: 9785
🌐 Web query:
CCCL libcudacxx runtime buffer get_unsynchronized operator[] synchronized accessor stream.sync
💡 Result:
In the NVIDIA CUDA Core Compute Libraries (CCCL), specifically within libcudacxx's runtime components, the buffer API provides typed, stream-ordered storage [1][2]. Key components regarding your query: get_unsynchronized The get_unsynchronized(const size_type n) method provides access to the n-th element of the buffer without performing any synchronization with the underlying CUDA stream [3]. Because it is "unsynchronized," the user is responsible for ensuring that the data is ready for access (e.g., via previous stream operations) before calling this method [3]. It is typically used when the caller has already accounted for necessary ordering or synchronization dependencies [3]. operator[] In many container-like abstractions within libcudacxx, operator[] is often mapped to or implemented alongside get_unsynchronized (or similar accessors) to provide convenient element access [3]. Users should consult the specific buffer class implementation in their version of CCCL, as this interface has evolved from earlier experimental versions (previously cudax::buffer) to the current cuda::buffer in libcudacxx [3]. synchronized accessor (stream.sync) The cuda::stream_ref (or cuda::stream) provides a sync() method, which performs a blocking synchronization of the wrapped CUDA stream, ensuring that all previously submitted work is complete [4][5]. When working with buffers, stream synchronization is managed explicitly [6]. For example: - The buffer itself does not automatically synchronize on element access [3]. - To ensure safe access to data processed by the GPU, one must call stream.sync() on the stream associated with that buffer's operations before accessing the data [4][3]. - Recent changes in the CCCL library have emphasized removing implicit synchronization from fundamental primitives (like set_stream) to give users better control over performance and synchronization overhead [6]. If you are using memory resources that are not natively stream-ordered, cuda::mr::synchronous_resource_adapter can be used to adapt them; this adapter will perform the necessary stream synchronization internally during allocation or deallocation if the underlying resource lacks stream-ordered support [7][8].
Citations:
- 1: https://nvidia.github.io/cccl/unstable/libcudacxx/runtime/buffer.html
- 2: https://nvidia.github.io/cccl/unstable/libcudacxx/runtime.html
- 3: ericniebler@5dd8bdb
- 4: https://nvidia.github.io/cccl/unstable/libcudacxx/runtime/stream.html
- 5: https://nvidia.github.io/cccl/unstable/libcudacxx/api/classcuda_1_1stream__ref.html
- 6: [CUDAX] Remove synchronization from set_stream and add a stream argument to destroy in async_buffer #5697
- 7: https://nvidia.github.io/cccl/unstable/libcudacxx/extended_api/memory_resource/resource_utilities.html
- 8: https://gevtushenko.github.io/cccl/libcudacxx/api/structsynchronous__resource__adapter.html
important: After stream.sync(), use result.get_unsynchronized(i) in the loop; result[i] takes the synchronized path and adds an unnecessary sync per element.
Source: MCP tools
😬 CI Workflow Results🟥 Finished in 2h 20m: Pass: 85%/70 | Total: 2d 18h | Max: 2h 09m | Hits: 37%/432898See results here. |
Another change to use cccl-runtime in Thrust testing #2800