feat(cccl): integrate missing CCCL directories — python/, ci/, .agent/, docs/, test/

Sparse-checkout from NVIDIA/cccl main branch to complete cccl_upstream:

Added:
- python/cuda_cccl/ (226 files) — Python bindings for device-level algorithms
  Critical for muh toolchain: cuda.compute.reduce_into, scan, radix_sort, etc.
  Includes 204 .py files with full test coverage for all 27 algorithms
- ci/ (163 files) — Build/test infrastructure
  build_cub.sh, test_cub.sh, build_and_test_targets.sh, matrix.yaml
  Directly maps to our [INFRA-CI] and [INFRA-BUILD] items
- .agent/skills/ (7 files) — NVIDIA's own agent skills for CCCL
  cccl-style/SKILL.md, cccl-test/SKILL.md, sass-diff/SKILL.md
- docs/ (491 files) — Official CCCL documentation
  CI references, CMake guides, Python compute docs, libcudacxx PTX docs
- test/ (12 files) — Top-level integration tests (cuda_smoke, stdpar)
- Root configs: .clang-format, .clang-tidy, CONTRIBUTING.md, pyproject.toml
- CLAUDE.md symlink → AGENTS.md (NVIDIA's standard)

cccl_upstream now mirrors full NVIDIA/cccl structure:
  Before: 42M (cub + thrust + libcudacxx + cudax + c + examples + benchmarks)
  After:  53M (+python +ci +docs +.agent +test +configs)

This completes the CCCL base needed for:
- [muh-bench] items: ci/util/build_and_test_targets.sh for targeted builds
- [CCCL-verify] items: python/cuda_cccl/tests/ as reference implementations
- [CCCL-test] items: ci/test_cub.sh, ci/test_thrust.sh
- Agent workflow: .agent/skills/ for consistent style and test patterns
This commit is contained in:
muh-bot
2026-08-07 02:34:33 +00:00
parent 3f97dca7ad
commit 2a7ca101d7
908 changed files with 121615 additions and 0 deletions

View File

@@ -0,0 +1,81 @@
.. _cccl-runtime-algorithm:
Algorithm
==========
The ``runtime`` part of the ``cuda/algorithm`` header provides stream-ordered, byte-wise primitives that operate on
:cpp:class:`cuda::std::span` and :cpp:class:`cuda::std::mdspan`-compatible types. They require a
:cpp:class:`cuda::stream_ref` to enqueue work.
:cpp:func:`cuda::copy_bytes`
-------------------------------
.. _cccl-runtime-algorithm-copy_bytes:
Launch a byte-wise copy from source to destination on the provided stream.
- Signature: :cpp:func:`cuda::copy_bytes`
- Overloads accept :cpp:class:`cuda::std::span`-convertible contiguous ranges or
:cpp:class:`cuda::std::mdspan`-convertible multi-dimensional views.
- Elements must be trivially copyable
- :cpp:class:`cuda::std::mdspan`-convertible types must convert to an mdspan that is exhaustive
- The optional ``config`` argument is a :cpp:struct:`cuda::copy_configuration` that controls source access order and
managed-memory location hints
Availability: CCCL 3.1.0 / CUDA 13.1
.. code:: cpp
#include <cuda/algorithm>
#include <cuda/stream>
#include <cuda/std/algorithm>
#include <cuda/std/span>
void copy_example(cuda::stream_ref s, cuda::std::span<const int> src, cuda::std::span<int> dst) {
// copy_bytes copies up to src.size_bytes(); dst can be larger.
auto n = cuda::std::min(src.size(), dst.size());
auto src_prefix = src.first(n / 2);
auto dst_prefix = dst.first(n / 2);
auto src_suffix = src.subspan(n / 2);
auto dst_suffix = dst.subspan(n / 2);
// Default behavior: enqueue a stream-ordered byte-wise copy on stream s.
cuda::copy_bytes(s, src_prefix, dst_prefix);
// Advanced behavior: customize source access order for this copy.
auto config = cuda::copy_configuration{
.src_access_order = cuda::source_access_order::during_api_call,
};
cuda::copy_bytes(s, src_suffix, dst_suffix, config);
}
:cpp:func:`cuda::fill_bytes`
-------------------------------
.. _cccl-runtime-algorithm-fill_bytes:
Launch a byte-wise fill of the destination on the provided stream.
- Overloads accept :cpp:class:`cuda::std::span`-convertible or :cpp:class:`cuda::std::mdspan`-convertible destinations.
- Elements must be trivially copyable
- :cpp:class:`cuda::std::mdspan`-convertible types must convert to an mdspan that is exhaustive
Availability: CCCL 3.1.0 / CUDA 13.1
.. code:: cpp
#include <cuda/algorithm>
#include <cuda/stream>
#include <cuda/std/algorithm>
#include <cuda/std/span>
void fill_example(cuda::stream_ref s, cuda::std::span<unsigned char> dst) {
// Reserve 16-byte red zones at both ends and clear the payload in between.
auto guard = cuda::std::min(static_cast<decltype(dst.size())>(16), dst.size() / 2);
auto head = dst.first(guard);
auto body = dst.subspan(guard, dst.size() - 2 * guard);
auto tail = dst.last(guard);
cuda::fill_bytes(s, head, 0xCD); // debug guard pattern
cuda::fill_bytes(s, body, 0x00); // initialize payload
cuda::fill_bytes(s, tail, 0xCD); // debug guard pattern
}

View File

@@ -0,0 +1,230 @@
.. _cccl-runtime-buffer:
.. |cuda_make_buffer| replace:: ``cuda::make_buffer``
.. _cuda_make_buffer: ../api/namespacecuda_1a8d909070d4cf758e776659b91e473a6f.html
Buffer
======
The buffer API provides a typed container allocated from memory resources. It handles stream-ordered allocation, initialization, and deallocation of memory.
:cpp:class:`cuda::buffer`
---------------------------
.. _cccl-runtime-buffer-buffer:
:cpp:class:`cuda::buffer` is a container that manages typed storage allocated from a given
:ref:`memory resource <libcudacxx-extended-api-memory-resources-resource>` in stream order using a provided
:ref:`stream_ref <cccl-runtime-stream-stream-ref>`. The elements are initialized during construction, which may require
a kernel launch. The stream provided during construction is stored and later used for deallocation of the buffer,
either explicitly or when the buffer destructor is called.
Buffer owns a copy of the memory resource, which means it must be copy-constructible. If a resource is not copy-constructible, like memory pool objects, :ref:`shared_resource <libcudacxx-extended-api-memory-resources-shared-resource>` can be used to attach shared ownership to a resource type.
In addition to being typed, :cpp:class:`cuda::buffer` also takes a set of
:ref:`properties <libcudacxx-extended-api-memory-resources-properties>` to ensure that memory accessibility and other
constraints are checked at compile time.
While the buffer operates in stream order, it can also be constructed with a :ref:`synchronous_resource <libcudacxx-extended-api-memory-resources-synchronous-resource>`, in which case it will automatically use the :ref:`synchronous_resource_adapter <libcudacxx-extended-api-memory-resources-synchronous-adapter>` to wrap the provided resource.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/buffer>
#include <cuda/devices>
#include <cuda/memory_pool>
#include <cuda/stream>
void use_buffer(cuda::stream_ref stream) {
// Create a device buffer
auto mr = cuda::device_default_memory_pool(cuda::devices[0]);
auto buf = cuda::make_buffer<float>(
stream,
mr,
1024, // size
0.0f // value
);
// Use buffer...
// Buffer is automatically deallocated when destroyed
}
Type Aliases
------------
.. _cccl-runtime-buffer-type-aliases:
Convenience type aliases are provided for common buffer types:
- :cpp:any:`cuda::device_buffer` - Buffer with ``device_accessible`` property
- :cpp:any:`cuda::host_buffer` - Buffer with ``host_accessible`` property
Example:
.. code:: cpp
#include <cuda/buffer>
#include <cuda/devices>
#include <cuda/memory_resource>
#include <cuda/stream>
void use_buffers(cuda::stream_ref stream) {
auto device_mr = cuda::device_default_memory_pool(cuda::devices[0]);
auto host_mr = cuda::pinned_default_memory_pool();
cuda::device_buffer<int> dev_buf{stream, device_mr, 1000};
cuda::host_buffer<int> host_buf{stream, host_mr, 1000};
}
Construction
------------
.. _cccl-runtime-buffer-construction:
Buffers can be constructed in several ways, depending on how you want to initialize the memory:
- Empty buffer: ``buffer(stream, resource)``
- With size (uninitialized): ``buffer(stream, resource, size, no_init)``
- From iterator range: ``buffer(stream, resource, first, last)``
- From initializer list: ``buffer(stream, resource, {val1, val2, ...})``
- From range: ``buffer(stream, resource, range)``
In each case the memory is allocated and initialized in stream order on the provided stream.
Example:
.. code:: cpp
#include <cuda/buffer>
#include <cuda/devices>
#include <cuda/memory_resource>
#include <vector>
void construct_buffers(cuda::stream_ref stream) {
auto mr = cuda::device_default_memory_pool(cuda::devices[0]);
// Empty buffer
cuda::device_buffer<int> buf1{stream, mr};
// Uninitialized buffer
cuda::device_buffer<int> buf2{stream, mr, 1000, cuda::no_init};
// Initialized with value
cuda::device_buffer<int> buf3{stream, mr, 1000, 42};
// From iterator range
std::vector<int> vec{1, 2, 3, 4, 5};
cuda::device_buffer<int> buf4{stream, mr, vec.begin(), vec.end()};
// From initializer list
cuda::device_buffer<int> buf5{stream, mr, {1, 2, 3, 4, 5}};
}
Stored Stream Management and Deallocation
-----------------------------------------
.. _cccl-runtime-buffer-stream-management:
Buffers store a reference to the stream they were constructed with, and can have that stream queried or changed:
- ``stream()`` - Get the associated stream
- ``set_stream(new_stream)`` - Change the associated stream (synchronizes with old stream)
When the buffer is destroyed, the memory is deallocated using the stored stream. The behavior is undefined if the stream
referenced by the buffer is destroyed before the buffer. Buffers can also be explicitly destroyed with ``destroy()`` or
``destroy(stream_ref)``, which will deallocate the memory using the provided stream.
Example:
.. code:: cpp
#include <cuda/buffer>
#include <cuda/devices>
#include <cuda/memory_resource>
#include <cuda/stream>
void manage_stream_and_deallocate() {
cuda::stream stream1{cuda::devices[0]};
cuda::stream stream2{cuda::devices[0]};
auto mr = cuda::device_default_memory_pool(cuda::devices[0]);
// Allocate on stream1
cuda::device_buffer<int> buf{stream1, mr, 1024, cuda::no_init};
// Switch to stream2 (synchronizes with stream1)
buf.set_stream(stream2);
// Explicit deallocation on the stored stream (stream2)
buf.destroy();
// Alternative would be to call buf.destroy(stream2)
}
|cuda_make_buffer|_
------------------------------------------------------------------------------------------------
.. _cccl-runtime-buffer-make-buffer:
|cuda_make_buffer|_ is a factory function that
creates buffers with automatic property deduction from the memory resource. It supports the same construction patterns
as the buffer constructors, in addition to an overload that sets all elements of the buffer to the same value.
Example:
.. code:: cpp
#include <cuda/buffer>
#include <cuda/devices>
#include <cuda/memory_resource>
void make_buffers(cuda::stream_ref stream) {
auto mr = cuda::device_default_memory_pool(cuda::devices[0]);
// Properties are automatically deduced from the memory resource
// and all elements are set to 42.0f
auto buf = cuda::make_buffer<float>(stream, mr, 1024, 42.0f);
}
Iterators and Access
--------------------
.. _cccl-runtime-buffer-iterators:
Buffers provide standard container-like iterators and access methods:
- ``begin()`` / ``end()`` - Iterator access
- ``cbegin()`` / ``cend()`` - Const iterator access
- ``rbegin()`` / ``rend()`` - Reverse iterator access
- ``data()`` - Pointer to underlying data
- ``size()`` - Number of elements
- ``empty()`` - Check if buffer is empty
- ``get_unsynchronized(n)`` - Access element without synchronization, instead of using ``operator[]``
Example:
.. code:: cpp
#include <cuda/buffer>
#include <cuda/devices>
#include <cuda/memory_resource>
#include <cuda/std/cstddef>
#include <algorithm>
void iterate_buffer(cuda::stream_ref stream) {
auto mr = cuda::pinned_default_memory_pool();
cuda::host_buffer<int> buf{stream, mr, {1, 2, 3, 4, 5}};
// Unsynchronized element access by index
for (cuda::std::size_t i = 0; i < buf.size(); ++i) {
buf.get_unsynchronized(i) += 1;
}
// Use with algorithms
auto it = std::find(buf.begin(), buf.end(), 3);
}
Memory Resource Access
----------------------
.. _cccl-runtime-buffer-memory-resource:
Buffers provide access to their underlying memory resource:
- ``memory_resource()`` - Get a const reference to the memory resource

View File

@@ -0,0 +1,131 @@
.. _cccl-runtime-cudart-interactions:
CUDA Runtime interactions
=========================
Some runtime objects have a non-owning ``_ref`` counterpart (for example, :cpp:struct:`cuda::stream` and
:cpp:class:`cuda::stream_ref`). Prefer the
owning type for lifetime management, and use the ``_ref`` type for code that would otherwise accept a C++ reference but
needs to interoperate with existing CUDA Runtime code.
CCCL runtime types that wrap CUDA Runtime handles support interoperating with CUDA Runtime handles via ``get()``,
constructors that accept native handles, ``release()``, and ``from_native_handle`` helpers. This makes it straightforward
to bridge between cccl-runtime APIs and existing CUDA Runtime code without losing ownership clarity.
Use ``get()`` on both owning and non-owning types. Constructors from native handles are intended for ``_ref`` wrappers,
while ``release()`` and ``from_native_handle`` are for owning objects that transfer or assume ownership.
Example: handle interop patterns
--------------------------------
.. code:: cpp
#include <cuda/stream>
void use_handle_interop(cuda::device_ref device, cudaStream_t raw_stream) {
// _ref from native handle (non-owning).
cuda::stream_ref borrowed{raw_stream};
// Universal handle access.
assert(borrowed.get() == raw_stream);
// Owning from native handle (assumes ownership).
auto owned = cuda::stream::from_native_handle(raw_stream);
assert(owned.get() == raw_stream);
// Release ownership back to CUDA Runtime.
cudaStream_t released = owned.release();
assert(released == raw_stream);
}
Error handling
--------------
CCCL Runtime APIs use C++ exceptions for error handling. Failures from runtime abstractions are reported by throwing an
exception, so normal code can be written without manually checking and propagating a status code after each operation.
This differs from the traditional CUDA Runtime API, where operations generally return ``cudaError_t`` values that the
caller must check against ``cudaSuccess`` and propagate or handle. When using CUDA Runtime calls directly, continue to
check their return values; when using CCCL Runtime wrappers, handle failures with normal C++ exception handling.
At a CUDA Runtime-style boundary, catch ``cuda::cuda_error`` and return its stored status.
.. code:: cpp
#include <cuda/stream>
cudaError_t use_stream(cuda::stream_ref stream) noexcept {
try {
// stream usage
stream.sync();
return cudaSuccess;
} catch (const cuda::cuda_error& err) {
return err.status();
}
}
Device selection
----------------
The Runtime API emphasizes explicit device selection. Most entry points take a :cpp:class:`cuda::device_ref` or a
device-bound resource (such as :cpp:struct:`cuda::stream`) rather than relying on implicit global state like
``cudaSetDevice``. This
makes device ownership and lifetime clearer, especially in multi-GPU code.
The current device can still be set via the CUDA Runtime, but cccl-runtime APIs ignore that global state and require an
explicit device argument. cccl-runtime also does not provide APIs that read or mutate the current device, by design.
.. _cccl-runtime-cudart-default-stream:
Default stream interop
----------------------
The CUDA default (NULL) stream is not exposed as a first-class runtime object because it is tied to implicit per-device
state and encourages hidden dependencies. Instead, it can be wrapped into :cpp:class:`cuda::stream_ref` when needed for
interop.
.. note::
When wrapping the NULL stream, the current device must be set explicitly first. CUDA binds the NULL stream to the
active device, so the wrapper must be created after selecting the correct device.
Example: wrapping the default stream
------------------------------------
.. code:: cpp
#include <cuda/stream>
void use_default_stream(int device_id) {
cudaSetDevice(device_id);
cuda::stream_ref default_stream{cudaStreamPerThread};
// Use default_stream with cccl-runtime APIs.
}
The above applies to Driver API interop cases as well, where the current context must be managed by the user rather than
the current device setting.
.. _cccl-runtime-cudart-non-blocking-streams:
Non-blocking stream creation
----------------------------
Constructing a new :cpp:struct:`cuda::stream` always creates a stream with CUDA Runtime non-blocking behavior. This is
the behavior of CCCL Runtime-created streams; wrapping or taking ownership of an existing ``cudaStream_t`` preserves the
behavior of that handle.
In the CUDA Runtime API, the blocking/non-blocking stream creation flag controls synchronization with the CUDA default
(NULL) stream. Because CCCL Runtime treats the default stream as an interop case rather than a first-class object,
as described in :ref:`default stream interop <cccl-runtime-cudart-default-stream>`, :cpp:struct:`cuda::stream` does not
expose a blocking/non-blocking construction option.
New Runtime code should express ordering between explicit streams directly, for example by making one
:cpp:class:`cuda::stream_ref` wait on another. Code that needs legacy CUDA Runtime implicit stream semantics should wrap
the relevant CUDA Runtime stream handle in :cpp:class:`cuda::stream_ref` (or take ownership with
``cuda::stream::from_native_handle``); operations submitted through the wrapper use the same native handle and preserve
that handle's CUDA Runtime semantics, including any default-stream synchronization semantics.

View File

@@ -0,0 +1,106 @@
.. _cccl-runtime-device:
Devices
========
:cpp:class:`cuda::device_ref`
-------------------------------
.. _cccl-runtime-device-device-ref:
:cpp:class:`cuda::device_ref` is a lightweight, non-owning handle to a CUDA device ordinal. It allows to query
information about a device and serves as an argument to other runtime APIs which are tied to a specific device.
It offers:
- ``get()``: native device ordinal
- ``name()``: device name
- ``init()``: initialize the device context
- ``peers()``: list peers for which peer access can be enabled
- ``has_peer_access_to(cuda::device_ref)``: query if peer access can be enabled to the given device
- ``attribute(attr)`` / ``attribute<::cudaDeviceAttr>()``: attribute queries
Availability: CCCL 3.1.0 / CUDA 13.1
:cpp:var:`cuda::devices`
----------------------------
.. _cccl-runtime-device-devices:
:cpp:var:`cuda::devices` is a random-access view of all available CUDA devices in the form of
:cpp:class:`cuda::device_ref` objects. It
provides indexing, size, and iteration for use
in range-based loops.
Availability: CCCL 3.1.0 / CUDA 13.1
Example:
.. code:: cpp
#include <cuda/devices>
#include <iostream>
void print_devices() {
for (auto& dev : cuda::devices) {
std::cout << "Device " << dev.get() << ": " << dev.name() << '\n';
}
}
Device attributes
-----------------
.. _cccl-runtime-device-attributes:
``cuda::device_attributes`` provides strongly-typed attribute query objects usable with
:cpp:func:`cuda::device_ref::attribute`. Selected examples:
- ``compute_capability``
- ``multiprocessor_count``
- ``concurrent_managed_access``
- ``clock_rate``
- ``numa_id``
Availability: CCCL 3.1.0 / CUDA 13.1
Example:
.. code:: cpp
#include <cuda/devices>
int get_max_blocks_on_device(cuda::device_ref dev) {
return cuda::device_attributes::multiprocessor_count(dev) * cuda::device_attributes::blocks_per_multiprocessor(dev);
}
:cpp:any:`cuda::arch_traits`
--------------------------------
.. _cccl-runtime-device-arch-traits:
Per-architecture trait accessors providing limits and capabilities common to all devices of an architecture.
Compared to ``cuda::device_attributes``, :cpp:any:`cuda::arch_traits` provide a compile-time accessible
structure that describes common characteristics of all devices of an architecture, while attributes are run-time
queries of a single characteristic of a specific device.
- :cpp:any:`cuda::arch_traits` and :cpp:any:`cuda::arch_traits_for` (compile-time and run-time forms).
- Returns a :cpp:struct:`cuda::arch_traits_t` with fields like
``max_threads_per_block``, ``max_shared_memory_per_block``, ``cluster_supported`` and other capability flags.
- Traits for the current architecture can be accessed with :cpp:func:`cuda::device::current_arch_traits`
Availability: CCCL 3.1.0 / CUDA 13.1
Example:
.. code:: cpp
#include <cuda/devices>
template <cuda::arch_id Arch>
__device__ void fn() {
auto traits = cuda::arch_traits<Arch>();
if constexpr (traits.cluster_supported) {
// cluster specific code
} else {
// non-cluster code
}
}
__global__ void kernel() {
fn<cuda::arch_id::sm_90>();
}

View File

@@ -0,0 +1,81 @@
.. _cccl-runtime-event:
Events
======
Event is a snapshot of execution state of a stream. It can be used to synchronize work submitted to a stream up to a certain point, establish dependency between streams or measure time passed between two events.
:cpp:class:`cuda::event_ref`
--------------------------------------------------
.. _cccl-runtime-event-event-ref:
:cpp:class:`cuda::event_ref` is a non-owning wrapper around a ``cudaEvent_t``. It prevents unsafe implicit constructions from
``nullptr`` or integer literals and provides convenient helpers:
- ``record(cuda::stream_ref)``: record the event on a stream
- ``sync()``: wait for the recorded work to complete
- ``is_done()``: non-blocking completion query
- comparison operators against other :cpp:class:`cuda::event_ref` or ``cudaEvent_t``
Availability: CCCL 3.1.0 / CUDA 13.1
Example:
.. code:: cpp
#include <cuda/stream>
void record_on_stream(cuda::stream_ref stream, cudaEvent_t raw_handle) {
cuda::event_ref e{raw_handle};
e.record(stream);
}
:cpp:class:`cuda::event`
--------------------------------------------
.. _cccl-runtime-event-event:
:cpp:class:`cuda::event` is an owning wrapper around a ``cudaEvent_t`` (with timing disabled). It inherits from
:cpp:class:`cuda::event_ref` and provides all of its functionality. It also creates and destroys the native event, can be moved (but
not copied), and can release ownership via ``release()``. Construction can target a specific :cpp:class:`cuda::device_ref`
or record immediately on a :cpp:class:`cuda::stream_ref`.
Availability: CCCL 3.1.0 / CUDA 13.1
.. code:: cpp
#include <cuda/stream>
#include <cuda/devices>
#include <cuda/std/optional>
cuda::std::optional<cuda::event> query_and_record_on_stream(cuda::stream_ref stream) {
if (stream.is_done()) {
return cuda::std::nullopt;
} else {
return cuda::event{stream};
}
}
.. _cccl-runtime-event-timed-event:
:cpp:class:`cuda::timed_event`
-----------------------------------------------------
:cpp:class:`cuda::timed_event` is an owning wrapper for a timed ``cudaEvent_t``. It inherits from :cpp:class:`cuda::event` and provides
all of its functionality.
It also supports elapsed-time queries between two events via ``operator-``, returning
:cpp:class:`cuda::std::chrono::nanoseconds`.
Availability: CCCL 3.1.0 / CUDA 13.1
.. code:: cpp
#include <cuda/stream>
#include <cuda/std/chrono>
template <typename F>
cuda::std::chrono::nanoseconds measure_execution_time(cuda::stream_ref stream, F&& f) {
cuda::timed_event start{stream};
f(stream);
cuda::timed_event end{stream};
return end - start;
}

View File

@@ -0,0 +1,208 @@
.. _cccl-runtime-hierarchy:
.. |cuda_hierarchy| replace:: ``cuda::hierarchy``
.. _cuda_hierarchy: ../api/classcuda_1_1hierarchy.html
.. |cuda_make_hierarchy| replace:: ``cuda::make_hierarchy``
.. _cuda_make_hierarchy: ../api/namespacecuda_1a67bb05480718296ce6aff78859538637.html
.. |cuda_make_config| replace:: ``cuda::make_config``
.. _cuda_make_config: ../api/namespacecuda_1aa7b277627ddc60563f1818ae8e05ba2d.html
.. |cuda_grid_dims| replace:: ``cuda::grid_dims``
.. _cuda_grid_dims: ../api/namespacecuda_1a9b019989bfafbeec225ccfa07718216d.html
.. |cuda_cluster_dims| replace:: ``cuda::cluster_dims``
.. _cuda_cluster_dims: ../api/namespacecuda_1ad240665066f4a89a04af40e66e131ab7.html
.. |cuda_block_dims| replace:: ``cuda::block_dims``
.. _cuda_block_dims: ../api/namespacecuda_1a1649d0f7fed34582e19dba72f8c1b3d2.html
.. |cuda_warp| replace:: ``cuda::warp``
.. _cuda_warp: ../api/namespacecuda_1a25cebd54f74dcdc131654cb3977a1842.html
.. |cuda_gpu_thread| replace:: ``cuda::gpu_thread``
.. _cuda_gpu_thread: ../api/namespacecuda_1a1c4664dbad423f7bd37472020576c17c.html
.. |cuda_hierarchy_add_level| replace:: ``cuda::hierarchy_add_level``
.. _cuda_hierarchy_add_level: ../api/namespacecuda_1a2c197f19590504c7fccb5b0a9e8f361a.html
.. |cuda_get_launch_dimensions| replace:: ``cuda::get_launch_dimensions``
.. _cuda_get_launch_dimensions: ../api/namespacecuda_1a43e600724a8fbba0b8797014aa0246e9.html
Hierarchy
=========
The hierarchy API provides abstractions for representing and querying levels in the CUDA thread hierarchy (grid, cluster,
block, warp, and thread levels). It enables compile-time and runtime queries of thread dimensions and counts across
different hierarchy levels.
|cuda_hierarchy|_
---------------------------------------------------------------------
.. _cccl-runtime-hierarchy-hierarchy:
|cuda_hierarchy|_ is a type representing a hierarchy of CUDA threads. It combines hierarchy level descriptors
to represent dimensions of a (possibly partial) hierarchy. It supports accessing individual levels and queries
combining dimensions of multiple levels.
A hierarchy should be created using |cuda_make_hierarchy|_ rather than being constructed directly. The
hierarchy type can be used by itself, but its main purpose is to be part of a kernel launch configuration described
here: :ref:`Launch <cccl-runtime-launch>`. In that case, instead of calling |cuda_make_hierarchy|_, the same arguments
can be passed to |cuda_make_config|_.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/hierarchy>
auto h = cuda::make_hierarchy(
cuda::grid_dims(256),
cuda::block_dims<8, 8, 8>()
);
// Access level dimensions
assert(h.level(cuda::grid).dims.x == 256);
// Query counts across levels
static_assert(cuda::gpu_thread.count(cuda::block, h) == 8 * 8 * 8);
|cuda_make_hierarchy|_
----------------------------------------------------------------------------------------------------
.. _cccl-runtime-hierarchy-make-hierarchy:
|cuda_make_hierarchy|_ creates a hierarchy from passed hierarchy level descriptors. Levels can be passed in
ascending or descending order, and the function will automatically order them correctly.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/hierarchy>
// Levels can be passed in any order
auto h1 = cuda::make_hierarchy(
cuda::grid_dims(256),
cuda::cluster_dims<4>(),
cuda::block_dims<8, 8, 8>()
);
auto h2 = cuda::make_hierarchy(
cuda::block_dims<8, 8, 8>(),
cuda::cluster_dims<4>(),
cuda::grid_dims(256)
);
// Both create equivalent hierarchies
static_assert(cuda::std::is_same_v<decltype(h1), decltype(h2)>);
Hierarchy Level Descriptors
----------------------------
.. _cccl-runtime-hierarchy-level-descriptors:
The hierarchy API provides level descriptor functions for grid, cluster, and block levels.
Each level supports both compile-time and runtime dimensions:
- |cuda_grid_dims|_ (compile-time and runtime overload forms)
- |cuda_cluster_dims|_ (compile-time and runtime overload forms)
- |cuda_block_dims|_ (compile-time and runtime overload forms)
Warp and thread levels are implicit and are queried via level objects (e.g., |cuda_warp|_,
|cuda_gpu_thread|_).
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/hierarchy>
auto h = cuda::make_hierarchy(
cuda::grid_dims(256, 128), // Runtime grid dimensions
cuda::cluster_dims<4>(), // Compile-time cluster dimensions
cuda::block_dims<32, 16>() // Compile-time block dimensions
);
Hierarchy Queries
-----------------
.. _cccl-runtime-hierarchy-queries:
Hierarchies support various query operations via level objects (``cuda::grid``, ``cuda::cluster``,
``cuda::block``, |cuda_warp|_, |cuda_gpu_thread|_):
- ``unit.count(level, hierarchy)`` - Count units within a level (e.g., threads per block)
- ``unit.rank(level, hierarchy)`` - Get the rank (linear index) of a unit within a level (device only)
- ``unit.dims(level, hierarchy)`` - Get dimensions of units within a level
- ``hierarchy.level<Level>()`` - Get the level descriptor for a specific level
- ``hierarchy.fragment<Unit, Level>()`` - Extract a fragment of the hierarchy
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/hierarchy>
auto h = cuda::make_hierarchy(
cuda::grid_dims(256),
cuda::block_dims<8, 8, 8>()
);
// Get block-level descriptor
auto block_desc = h.level(cuda::block);
assert(block_desc.dims.x == 8);
// Count threads per block
static_assert(cuda::gpu_thread.count(cuda::block, h) == 512);
// Get fragment (block to grid)
auto fragment = h.fragment(cuda::block, cuda::grid);
|cuda_hierarchy_add_level|_
---------------------------------------------------------------------------------------------------------
.. _cccl-runtime-hierarchy-add-level:
|cuda_hierarchy_add_level|_ returns a new hierarchy that is a copy of the supplied hierarchy with a new level
added. The function automatically determines whether to add the level at the top or bottom based on the existing
levels.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/hierarchy>
auto partial = cuda::make_hierarchy<cuda::block_level>(
cuda::grid_dims(256),
cuda::cluster_dims<4>()
);
auto complete = cuda::hierarchy_add_level(
partial,
cuda::block_dims<8, 8, 8>()
);
|cuda_get_launch_dimensions|_
-----------------------------------------------------------------------------------------------------------
.. _cccl-runtime-hierarchy-launch-dimensions:
|cuda_get_launch_dimensions|_ returns a tuple of ``hierarchy_query_result`` objects containing dimensions from
the hierarchy that can be used to launch kernels. The returned tuple has three elements if cluster_level is present
(grid, cluster, block dimensions), or two elements otherwise (grid, block dimensions).
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/hierarchy>
auto h = cuda::make_hierarchy(
cuda::grid_dims(256),
cuda::cluster_dims<4>(),
cuda::block_dims<8, 8, 8>()
);
auto [grid_dims, cluster_dims, block_dims] = cuda::get_launch_dimensions(h);
// Can be used with cudaLaunchKernel or similar APIs

View File

@@ -0,0 +1,290 @@
.. _cccl-runtime-launch:
.. |cuda_launch| replace:: ``cuda::launch``
.. _cuda_launch: ../api/namespacecuda_1afd43c8d92fdb84879aed04f3e2ea25d2.html
.. |cuda_kernel_config| replace:: ``cuda::kernel_config``
.. _cuda_kernel_config: ../api/structcuda_1_1kernel__config.html
.. |cuda_make_config| replace:: ``cuda::make_config``
.. _cuda_make_config: ../api/namespacecuda_1aa7b277627ddc60563f1818ae8e05ba2d.html
.. |cuda_cooperative_launch| replace:: ``cuda::cooperative_launch``
.. _cuda_cooperative_launch: ../api/structcuda_1_1cooperative__launch.html
.. |cuda_dynamic_shared_memory| replace:: ``cuda::dynamic_shared_memory``
.. _cuda_dynamic_shared_memory: ../api/namespacecuda_1a737c80f87e6e727a865cd05b82ec2405.html
.. |cuda_launch_priority| replace:: ``cuda::launch_priority``
.. _cuda_launch_priority: ../api/structcuda_1_1launch__priority.html
.. |cuda_host_launch| replace:: ``cuda::host_launch``
.. _cuda_host_launch: ../api/namespacecuda_1a5af4f59c915edb056f346b904197ff3d.html
Launch
======
The launch API provides abstractions for launching CUDA kernels with a given configuration. It supports kernel functions and device callable objects, cooperative launches, dynamic shared memory, and other launch options.
|cuda_launch|_
--------------------------------------------------------------------------------------------
.. _cccl-runtime-launch-launch:
|cuda_launch|_ launches a kernel function or a device callable object on the specified stream with a given
configuration. The kernel can accept the configuration as its first argument to enable some device-side functionality,
but it is not required. If the kernel does accept the configuration as its first argument, |cuda_launch|_
will automatically pass it into the kernel without the need to pass the configuration as an argument twice.
*Note:* Configuration won't be passed automatically into the kernel if it is an extended device lambda, it needs to be passed as the second launch function argument and as the first kernel argument.
The benefit of using a callable object with a device call operator (later called a kernel functor) is that it can have its
template arguments deduced from the arguments, while a kernel function needs to be explicitly instantiated. It also
allows attaching a default configuration that is later combined with the configuration passed to the launch.
Availability: CCCL 3.2.0 / CUDA 13.2
Example with kernel function:
.. code:: cpp
#include <cuda/launch>
#include <cstdio>
template <typename Configuration>
__global__ void kernel(Configuration conf, unsigned int thread_to_print) {
if (cuda::gpu_thread.rank(cuda::grid, conf) == thread_to_print) {
printf("Hello from the GPU\n");
}
}
void launch_kernel(cuda::stream_ref stream) {
auto config = cuda::make_config(cuda::block_dims<128>(), cuda::grid_dims(4), cuda::cooperative_launch{});
// Here the template needs to be explicitly instantiated, unlike in the kernel functor example where it can be deduced
cuda::launch(stream, config, kernel<decltype(config)>, 42);
}
Example with kernel functor:
.. code:: cpp
#include <cuda/launch>
#include <cstdio>
struct kernel {
template <typename Configuration>
__device__ void operator()(Configuration conf, unsigned int thread_to_print) {
if (cuda::gpu_thread.rank(cuda::grid, conf) == thread_to_print) {
printf("Hello from the GPU\n");
}
}
};
void launch_kernel(cuda::stream_ref stream) {
auto config = cuda::make_config(cuda::block_dims<128>(), cuda::grid_dims(4), cuda::cooperative_launch{});
// It's enough to pass the configuration object once and launch will automatically pass it into the kernel
cuda::launch(stream, config, kernel{}, 42);
}
Example with extended device lambda:
.. code:: cpp
#include <cuda/launch>
#include <cstdio>
void launch_kernel(cuda::stream_ref stream) {
auto config = cuda::make_config(cuda::block_dims<128>(), cuda::grid_dims(4), cuda::cooperative_launch{});
auto lambda = [](cuda::config conf, unsigned int thread_to_print) {
if (cuda::gpu_thread.rank(cuda::grid, conf) == thread_to_print) {
printf("Hello from the GPU\n");
}
};
// Note that the configuration needs to be passed twice, unlike in other examples
cuda::launch(stream, config, lambda, config, 42);
}
|cuda_kernel_config|_
-------------------------------------------------------------------------------
.. _cccl-runtime-launch-kernel-config:
|cuda_kernel_config|_ represents a kernel launch configuration combining hierarchy dimensions and launch
options. It should be created using |cuda_make_config|_ rather than being constructed directly.
A |cuda_kernel_config|_ provides:
- ``hierarchy()`` - Access to the hierarchy dimensions
- ``options()`` - Access to launch options
- ``combine(other_config)`` - Combine with another configuration
- ``combine_with_default(kernel)`` - Combine with default options from a kernel of a kernel functor accessed via
``kernel.default_config()``, equivalent to ``combine(kernel.default_config())``
Availability: CCCL 3.2.0 / CUDA 13.2
|cuda_make_config|_
-------------------------------------------------------------------------------------------------
.. _cccl-runtime-launch-make-config:
|cuda_make_config|_ creates a kernel configuration from `hierarchy dimensions <cccl-runtime-hierarchy>` and
optional launch options. It can be called with:
- A hierarchy and options: ``make_config(hierarchy, option1, option2, ...)``
- Dimensions directly: ``make_config(grid_dims(...), block_dims<...>(), option1, option2, ...)``
In the last case, the dimensions arguments must come first, followed by options.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/launch>
#include <cooperative_groups.h>
// Create config with cooperative launch
auto config1 = cuda::make_config(cuda::grid_dims(256), cuda::cooperative_launch{});
// Create config with dynamic shared memory
auto config2 = cuda::make_config(
cuda::block_dims<128>(),
cuda::grid_dims(512),
cuda::dynamic_shared_memory<float>(1024)
);
// Combine configurations, configuration that combine was called on is prioritized.
auto config3 = config1.combine(config2);
assert(cuda::gpu_thread.count(cuda::grid, config3) == 256 * 128);
// Kernel functor can have a default configuration attached to it, that is later combined with the configuration passed to the launch.
struct kernel {
template <typename Configuration>
__global__ void operator()(Configuration conf, unsigned int thread_to_print) {
auto grid = cooperative_groups::this_grid();
grid.sync();
if (cuda::gpu_thread.rank(cuda::grid, conf) == thread_to_print) {
printf("Hello from the GPU\n");
}
}
auto default_config() const {
return cuda::make_config(cuda::block_dims<128>(), cuda::cooperative_launch{});
}
};
cuda::launch(stream, cuda::make_config(cuda::grid_dims(4)), kernel{});
Launch Options
--------------
.. _cccl-runtime-launch-options:
The launch API provides several launch options:
|cuda_cooperative_launch|_
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Enables cooperative launch, restricting the grid to a number of blocks that can simultaneously execute on the device. This enables usage of ``cooperative_groups::grid_group::sync()`` in the kernel. This is a struct that can be default-constructed.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/launch>
#include <cooperative_groups.h>
template <typename Configuration>
__global__ void kernel(Configuration conf) {
auto grid = cooperative_groups::this_grid();
grid.sync();
}
void launch(cuda::stream_ref stream) {
auto config = cuda::make_config(cuda::block_dims<128>(), cuda::grid_dims(4), cuda::cooperative_launch{});
cuda::launch(stream, config, kernel<decltype(config)>);
}
|cuda_dynamic_shared_memory|_
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Specifies dynamic shared memory configuration. It provides a type-safe way to specify shared memory content and later access it through the configuration object passed to the kernel.
- For non-array ``T`` (e.g., a struct), call |cuda_dynamic_shared_memory|_ with no size argument.
- For bounded array ``T[n]`` (e.g., ``int[10]``), call |cuda_dynamic_shared_memory|_ with no size argument.
- For unbounded array ``T[]`` (e.g., ``float[]``), pass the element count to |cuda_dynamic_shared_memory|_.
- To opt in to non-portable dynamic shared memory sizes (greater than 48 KiB per block), pass
:cpp:any:`cuda::non_portable` to |cuda_dynamic_shared_memory|_.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/launch>
template <typename Configuration>
__global__ void kernel(Configuration conf) {
auto smem = cuda::dynamic_shared_memory(conf);
// Use smem as span<T> in case of an array type or T& in case of a non-array type
}
void launch(cuda::stream_ref stream) {
auto config = cuda::make_config(
cuda::block_dims<128>(),
cuda::grid_dims(4),
cuda::dynamic_shared_memory<float[]>(1024)
);
cuda::launch(stream, config, kernel<decltype(config)>);
}
void launch_non_portable(cuda::stream_ref stream) {
auto config = cuda::make_config(
cuda::block_dims<128>(),
cuda::grid_dims(4),
cuda::dynamic_shared_memory<float[]>(32768, cuda::non_portable)
);
cuda::launch(stream, config, kernel<decltype(config)>);
}
|cuda_launch_priority|_
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Specifies the priority launch option used when scheduling the kernel launch. Overrides the priority specified in the stream.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/launch>
auto config = cuda::make_config(
cuda::block_dims<128>(),
cuda::grid_dims(4),
cuda::launch_priority{0}
);
|cuda_host_launch|_
-------------------------------------------------------------------------------------------------
.. _cccl-runtime-launch-host-launch:
|cuda_host_launch|_ launches a host callable for a stream-ordered execution. The callable can be a lambda
function, a function pointer, or a callable object.
The callable and arguments are taken by value and stored for later execution. This requires a dynamic allocation to store the callable and arguments. If the callable is a function pointer or cuda::std::reference_wrapper and there are no arguments, the dynamic allocation is avoided.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/launch>
#include <iostream>
cuda::host_launch(stream, [](int arg) {
std::cout << "Callback executed" << '\n';
std::cout << "Argument: " << arg << '\n';
}, 42);
// Passing by reference requires using cuda::std::ref without arguments to avoid dynamic allocation,
// but the callable must live long enough for the callable to execute.
int arg = 42;
auto lambda = [&arg]() {
std::cout << "Callback executed" << '\n';
std::cout << "Argument: " << arg << '\n';
};
cuda::host_launch(stream, cuda::std::ref(lambda));
stream.sync();

View File

@@ -0,0 +1,50 @@
.. _cccl-runtime-legacy-resources:
.. _libcudacxx-extended-api-memory-resources-legacy-resources:
Legacy resources
================
Legacy memory resources provide synchronous allocation interfaces backed by the CUDA Runtime's legacy allocation APIs.
They are primarily intended for compatibility with older toolkits or platforms that do not support the newer memory
pool-based resources. Prefer the modern memory resources where available.
For the full memory resource model and property system, see
:ref:`Memory Resources (Extended API) <libcudacxx-extended-api-memory-resources>`.
:cpp:class:`cuda::mr::legacy_pinned_memory_resource`
------------------------------------------------------
.. _libcudacxx-memory-resource-legacy-pinned-memory-resource:
Provides pinned (page-locked) host allocations using ``cudaMallocHost`` and ``cudaFreeHost``. This resource is
*synchronous-only* and is intended as a compatibility fallback. For CUDA 12.9 and later, prefer
:cpp:any:`cuda::pinned_memory_resource`.
.. code:: cpp
#include <cuda/memory_resource>
void use_legacy_pinned() {
cuda::mr::legacy_pinned_memory_resource resource{};
void* ptr = resource.allocate_sync(1024, 64);
// Use memory...
resource.deallocate_sync(ptr, 1024, 64);
}
:cpp:class:`cuda::mr::legacy_managed_memory_resource`
-------------------------------------------------------
.. _libcudacxx-memory-resource-legacy-managed-memory-resource:
Provides managed (unified) allocations using ``cudaMallocManaged`` and ``cudaFree``. This resource is
*synchronous-only* and accepts the CUDA attachment flags (``cudaMemAttachGlobal`` / ``cudaMemAttachHost``). Prefer
:cpp:any:`cuda::managed_memory_resource` when available.
.. code:: cpp
#include <cuda/memory_resource>
void use_legacy_managed() {
cuda::mr::legacy_managed_memory_resource resource{cudaMemAttachGlobal};
void* ptr = resource.allocate_sync(1024, 64);
// Use memory...
resource.deallocate_sync(ptr, 1024, 64);
}

View File

@@ -0,0 +1,366 @@
.. _cccl-runtime-memory-pools:
.. |cuda_memory_pool_attributes| replace:: ``cuda::memory_pool_attributes``
.. _cuda_memory_pool_attributes: ../api/memory_pool_attributes.html
Memory Pools
============
Memory pools provide efficient, stream-ordered memory allocation using CUDA's memory pool API. They support both synchronous and stream-ordered allocation/deallocation and can be configured with various memory spaces, properties and attributes.
Memory pool objects implement the :ref:`cuda::mr::resource <libcudacxx-extended-api-memory-resources-resource>`
interface with ``allocate(stream, size, alignment)`` and ``deallocate(stream, ptr, size, alignment)`` member
functions. They also provide synchronous variants with ``allocate_sync(size, alignment)`` and
``deallocate_sync(ptr, size, alignment)`` member functions. For all of them, the alignment argument is optional.
For the full memory resource model and property system, see :ref:`Memory Resources (Extended API) <libcudacxx-extended-api-memory-resources>`.
Host memory pools are supported on CUDA 12.9 and later. Managed memory pools are supported on CUDA 13.0 and later and are not supported on Windows. For those cases use :ref:`cuda::mr::legacy_pinned_memory_resource <libcudacxx-memory-resource-legacy-pinned-memory-resource>` and :ref:`cuda::mr::legacy_managed_memory_resource <libcudacxx-memory-resource-legacy-managed-memory-resource>` instead.
:cpp:struct:`cuda::device_memory_pool`
---------------------------------------
.. _cccl-runtime-memory-pools-device-memory-pool:
:cpp:struct:`cuda::device_memory_pool` allocates device memory using CUDA's stream-ordered memory pool API
(``cudaMallocFromPoolAsync`` / ``cudaFreeAsync``). When constructed, it creates and owns an underlying
``cudaMemPool_t`` with location type set to ``cudaMemLocationTypeDevice``.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/stream>
#include <cuda/devices>
void use_device_pool(cuda::stream_ref stream) {
// Create a device memory pool
cuda::device_memory_pool pool{cuda::devices[0]};
// Allocate memory in stream order
void* ptr = pool.allocate(stream, 1024, 16);
// Use memory...
// Deallocate in stream order
pool.deallocate(stream, ptr, 1024, 16);
}
:cpp:class:`cuda::device_memory_pool_ref`
-------------------------------------------
.. _cccl-runtime-memory-pools-device-memory-pool-ref:
:cpp:class:`cuda::device_memory_pool_ref` is a non-owning reference to a device memory pool. It does not own the
underlying ``cudaMemPool_t``, so the user must ensure the pool's lifetime exceeds the reference's lifetime.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/stream>
void use_pool_ref(cuda::stream_ref stream, cuda::device_memory_pool_ref pool_ref) {
void* ptr = pool_ref.allocate(stream, 1024);
// Use memory...
pool_ref.deallocate(stream, ptr, 1024);
}
:cpp:struct:`cuda::managed_memory_pool`
----------------------------------------
.. _cccl-runtime-memory-pools-managed-memory-pool:
:cpp:struct:`cuda::managed_memory_pool` allocates managed (unified) memory using CUDA's memory pool API. It creates and
owns an underlying ``cudaMemPool_t`` with allocation type set to ``cudaMemAllocationTypeManaged``. Managed memory is
accessible from both host and device.
Availability: CCCL 3.2.0 / CUDA 13.2 (requires CTK 13.0+). Not supported on Windows
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/stream>
void use_managed_pool(cuda::stream_ref stream) {
cuda::managed_memory_pool pool{};
// Allocate managed memory
void* ptr = pool.allocate(stream, 1024);
// Accessible from both host and device
// Use memory...
pool.deallocate(stream, ptr, 1024);
}
:cpp:class:`cuda::managed_memory_pool_ref`
--------------------------------------------
.. _cccl-runtime-memory-pools-managed-memory-pool-ref:
:cpp:class:`cuda::managed_memory_pool_ref` is a non-owning reference to a managed memory pool.
Availability: CCCL 3.2.0 / CUDA 13.2 (requires CTK 13.0+). Not supported on Windows
:cpp:struct:`cuda::pinned_memory_pool`
---------------------------------------
.. _cccl-runtime-memory-pools-pinned-memory-pool:
:cpp:struct:`cuda::pinned_memory_pool` allocates pinned (page-locked) host memory using CUDA's memory pool API. Pinned
memory enables faster host-to-device transfers and can be accessed from all devices. The pool can be optionally
created for a specific host NUMA node.
Availability: CCCL 3.2.0 / CUDA 13.2 (requires CTK 12.9+)
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/stream>
void use_pinned_pool(cuda::stream_ref stream) {
// Create pinned memory pool
cuda::pinned_memory_pool pool{};
// Allocate pinned memory
void* ptr = pool.allocate(stream, 1024);
// Use for fast host-device transfers...
pool.deallocate(stream, ptr, 1024);
}
// With NUMA node
void use_pinned_pool_numa(cuda::stream_ref stream, int numa_id) {
cuda::pinned_memory_pool pool{numa_id};
void* ptr = pool.allocate(stream, 1024);
// Use memory...
pool.deallocate(stream, ptr, 1024);
}
:cpp:class:`cuda::pinned_memory_pool_ref`
-------------------------------------------
.. _cccl-runtime-memory-pools-pinned-memory-pool-ref:
:cpp:class:`cuda::pinned_memory_pool_ref` is a non-owning reference to a pinned memory pool.
Availability: CCCL 3.2.0 / CUDA 13.2 (requires CTK 12.9+)
Default Memory Pools
--------------------
.. _cccl-runtime-memory-pools-default-pools:
CUDA provides default memory pools for each memory type. These pools are managed by the CUDA runtime and can be accessed through helper functions. Default pools are useful when you don't need custom pool configuration and want to use the system defaults.
:cpp:func:`cuda::device_default_memory_pool`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _cccl-runtime-memory-pools-device-default:
:cpp:func:`cuda::device_default_memory_pool` returns a non-owning reference to the default device memory pool for the
specified device. The default pool is created automatically by CUDA and is shared across all users of the device.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/devices>
#include <cuda/stream>
void use_default_device_pool(cuda::stream_ref stream) {
// Get the default device memory pool
auto pool = cuda::device_default_memory_pool(cuda::devices[0]);
// Allocate from the default pool
void* ptr = pool.allocate(stream, 1024);
// Use memory...
// Deallocate back to the pool
pool.deallocate(stream, ptr, 1024);
}
:cpp:func:`cuda::managed_default_memory_pool`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _cccl-runtime-memory-pools-managed-default:
:cpp:func:`cuda::managed_default_memory_pool` returns a non-owning reference to the default managed (unified) memory
pool.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/stream>
void use_default_managed_pool(cuda::stream_ref stream) {
// Get the default managed memory pool
auto pool = cuda::managed_default_memory_pool();
// Allocate managed memory
void* ptr = pool.allocate(stream, 1024);
// Accessible from both host and device
// Use memory...
pool.deallocate(stream, ptr, 1024);
}
:cpp:func:`cuda::pinned_default_memory_pool`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _cccl-runtime-memory-pools-pinned-default:
:cpp:func:`cuda::pinned_default_memory_pool` returns a non-owning reference to the default pinned (page-locked) host
memory pool.
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/stream>
void use_default_pinned_pool(cuda::stream_ref stream) {
// Get the default pinned memory pool
auto pool = cuda::pinned_default_memory_pool();
// Allocate pinned memory
void* ptr = pool.allocate(stream, 1024);
// Use for fast host-device transfers...
pool.deallocate(stream, ptr, 1024);
}
Notes on Default Pools
~~~~~~~~~~~~~~~~~~~~~~
- Default pools are created automatically by CUDA and shared across the application
- The pools are returned as non-owning references (``*_pool_ref`` types)
- Default pools use CUDA's default configuration and cannot be destroyed
- Multiple calls to the same getter function return references to the same pool
- Default pools are thread-safe and can be used concurrently from multiple threads
- Underlying CUDA default memory pools have 0 release threshold by default. First access to a default pool through one of the getters above will set the release threshold to the maximum value, unless previously modified by the user.
Memory Pool Properties
----------------------
.. _cccl-runtime-memory-pools-pool-properties:
:cpp:struct:`cuda::memory_pool_properties` controls memory pool creation options:
- ``initial_pool_size`` - Initial size of the pool (default: 0)
- ``release_threshold`` - Threshold at which unused memory is released (default: no limit on the reserved memory)
- ``allocation_handle_type`` - Handle type for inter-process sharing (default: none)
- ``max_pool_size`` - Maximum size of the pool (default: no limit on the pool size)
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/devices>
void create_pool_with_properties() {
cuda::memory_pool_properties props{};
props.initial_pool_size = 1024 * 1024; // 1 MB initial size
props.release_threshold = 10 * 1024 * 1024; // Release if over 10 MB
cuda::device_memory_pool pool{cuda::devices[0], props};
}
Memory Pool Attributes
----------------------
.. _cccl-runtime-memory-pools-pool-attributes:
|cuda_memory_pool_attributes|_ provides access to pool attributes for
querying and configuration:
- ``release_threshold`` - Get/set the release threshold, which controls how much memory the pool can keep reserved, both used and unused
- ``reuse_follow_event_dependencies`` - Enable/disable reuse across streams with event dependencies
- ``reuse_allow_opportunistic`` - Enable/disable opportunistic reuse
- ``reuse_allow_internal_dependencies`` - Enable/disable reuse with internal dependencies
- ``reserved_mem_current`` - Query current reserved memory (read-only)
- ``used_mem_current`` - Query current used memory (read-only)
- ``reserved_mem_high`` - Get/set high watermark for reserved memory
- ``used_mem_high`` - Get/set high watermark for used memory
The following additional read-only creation attributes are available with CUDA 13.3:
- ``allocation_type`` - Query the allocation type of the pool
- ``export_handle_types`` - Query the export handle types available for the pool
- ``location`` - Query the location of the pool as a ``cuda::memory_location``
- ``location_id`` - Query only the location id of the pool
- ``location_type`` - Query only the location type of the pool
- ``max_pool_size`` - Query the maximum size of the pool
- ``hw_decompress_enabled`` - Query whether hardware decompression is enabled for the pool
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/devices>
void configure_pool_attributes() {
cuda::device_memory_pool pool{cuda::devices[0]};
// Set release threshold
pool.set_attribute(cuda::memory_pool_attributes::release_threshold, 5 * 1024 * 1024);
// Enable opportunistic reuse
pool.set_attribute(cuda::memory_pool_attributes::reuse_allow_opportunistic, true);
// Query current usage
auto reserved = pool.attribute(cuda::memory_pool_attributes::reserved_mem_current);
auto used = pool.attribute(cuda::memory_pool_attributes::used_mem_current);
}
Pool Management
---------------
.. _cccl-runtime-memory-pools-pool-management:
Memory pools provide additional management functions:
- ``trim_to(min_bytes)`` - Release memory down to a minimum size
- ``enable/disable_access_from(devices)`` - Enable or disable access from specific devices (for peer access or access to host pinned memory)
- ``get()`` - Get the underlying ``cudaMemPool_t`` handle
- ``release()`` - Release ownership of the pool handle
Availability: CCCL 3.2.0 / CUDA 13.2
Example:
.. code:: cpp
#include <cuda/memory_resource>
#include <cuda/devices>
void manage_pool() {
cuda::pinned_memory_pool pool{};
// Enable access from all devices
pool.enable_access_from(cuda::devices);
// Trim pool to 1 MB minimum
pool.trim_to(1024 * 1024);
// Get native handle
cudaMemPool_t handle = pool.get();
}

View File

@@ -0,0 +1,70 @@
.. _cccl-runtime-stream:
Streams
========
Stream is conceptually a queue of operations for a specific device. It is passed as an argument to all asynchronous operations like kernel launch, memory copy and allocations.
:cpp:class:`cuda::stream_ref`
-------------------------------
.. _cccl-runtime-stream-stream-ref:
:cpp:class:`cuda::stream_ref` is a non-owning wrapper around a ``cudaStream_t``. It prevents unsafe implicit constructions from
``nullptr`` or integer literals and provides convenient helpers for:
- ``sync()``: wait for the recorded work to complete
- ``is_done()``: non-blocking completion query
- comparison operators against other :cpp:class:`cuda::stream_ref` or ``cudaStream_t``
Availability: CCCL 2.2.0 / CUDA 12.3
Example:
.. code:: cpp
#include <cuda/stream>
cudaStream_t stream;
cudaStreamCreate(&stream);
cuda::stream_ref ref{stream};
ref.sync(); // synchronizes the stream via cudaStreamSynchronize
assert(ref.is_done()); // verifies that the stream has finished all operations via cudaStreamQuery
// compare against other stream_ref or cudaStream_t
assert(ref == stream);
assert(ref != cuda::invalid_stream);
cudaStreamDestroy(stream);
:cpp:struct:`cuda::stream`
---------------------------
.. _cccl-runtime-stream-stream:
:cpp:struct:`cuda::stream` is an owning wrapper around a ``cudaStream_t`` that manages the lifetime of the underlying CUDA
stream.
It derives from :cpp:class:`cuda::stream_ref`, provides all of its functionality, and can be used anywhere a
:cpp:class:`cuda::stream_ref` is expected.
It can be constructed for a specific :cpp:class:`cuda::device_ref`, moved (but not copied), and converted from or to a
``cudaStream_t`` via ``from_native_handle``/``release()``.
Constructing a new :cpp:struct:`cuda::stream` always creates a non-blocking stream; see
:ref:`non-blocking stream creation <cccl-runtime-cudart-non-blocking-streams>` for CUDA Runtime interop details.
Availability: CCCL 3.1.0 / CUDA 13.1
.. code:: cpp
#include <cuda/stream>
#include <cuda/devices>
int main() {
{
// Create a stream on a specific device
cuda::stream s{cuda::devices[0]};
// Pass to a stream-ordered API
// Synchronize the stream
s.sync();
} // Stream is automatically destroyed here
}