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:
@@ -0,0 +1,93 @@
|
||||
.. _libcudacxx-extended-api-warp-lane-mask:
|
||||
|
||||
``cuda::device::lane_mask``
|
||||
===========================
|
||||
|
||||
Defined in ``<cuda/warp>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/std/cstdint>
|
||||
|
||||
namespace cuda::device
|
||||
{
|
||||
|
||||
class lane_mask
|
||||
{
|
||||
// constructors
|
||||
__device__ explicit constexpr lane_mask(cuda::std::uint32_t v = 0) noexcept;
|
||||
|
||||
// member functions
|
||||
[[nodiscard]] __device__ constexpr cuda::std::uint32_t value() const noexcept;
|
||||
|
||||
// conversion operators
|
||||
__device__ explicit constexpr operator cuda::std::uint32_t() const noexcept;
|
||||
|
||||
// static member functions
|
||||
[[nodiscard]] __device__ static constexpr lane_mask none() noexcept;
|
||||
[[nodiscard]] __device__ static constexpr lane_mask all() noexcept;
|
||||
[[nodiscard]] __device__ static lane_mask all_active() noexcept;
|
||||
[[nodiscard]] __device__ static lane_mask this_lane() noexcept;
|
||||
[[nodiscard]] __device__ static lane_mask all_less() noexcept;
|
||||
[[nodiscard]] __device__ static lane_mask all_less_equal() noexcept;
|
||||
[[nodiscard]] __device__ static lane_mask all_greater() noexcept;
|
||||
[[nodiscard]] __device__ static lane_mask all_greater_equal() noexcept;
|
||||
[[nodiscard]] __device__ static lane_mask all_not_equal() noexcept;
|
||||
|
||||
// bitwise assignment operators
|
||||
__device__ constexpr lane_mask& operator&=(lane_mask mask) noexcept;
|
||||
__device__ constexpr lane_mask& operator|=(lane_mask mask) noexcept;
|
||||
__device__ constexpr lane_mask& operator^=(lane_mask mask) noexcept;
|
||||
__device__ constexpr lane_mask& operator<<=(int shift) noexcept;
|
||||
__device__ constexpr lane_mask& operator>>=(int shift) noexcept;
|
||||
|
||||
// bitwise operators
|
||||
[[nodiscard]] __device__ friend constexpr lane_mask operator~(lane_mask mask) noexcept;
|
||||
[[nodiscard]] __device__ friend constexpr lane_mask operator&(lane_mask lhs, lane_mask rhs) noexcept;
|
||||
[[nodiscard]] __device__ friend constexpr lane_mask operator|(lane_mask lhs, lane_mask rhs) noexcept;
|
||||
[[nodiscard]] __device__ friend constexpr lane_mask operator^(lane_mask lhs, lane_mask rhs) noexcept;
|
||||
[[nodiscard]] __device__ friend constexpr lane_mask operator<<(lane_mask mask, int shift) noexcept;
|
||||
[[nodiscard]] __device__ friend constexpr lane_mask operator>>(lane_mask mask, int shift) noexcept;
|
||||
|
||||
// comparison operators
|
||||
[[nodiscard]] __device__ friend constexpr bool operator==(lane_mask lhs, lane_mask rhs) noexcept;
|
||||
[[nodiscard]] __device__ friend constexpr bool operator!=(lane_mask lhs, lane_mask rhs) noexcept;
|
||||
};
|
||||
|
||||
} // namespace cuda::device
|
||||
|
||||
``cuda::device::lane_mask`` is a class that represents a mask of lanes in a warp. It is a fancy wrapper around a single 32-bit unsigned integer value that allows for bitwise operations and comparisons, making it easier and safer to work with lane masks in CUDA device code.
|
||||
|
||||
The class provides several ``static`` member functions to create common lane masks:
|
||||
|
||||
- ``none()`` and ``all()`` are equivalent to ``lane_mask{0x0}`` and ``lane_mask{0xFFFFFFFF}``, respectively
|
||||
- ``all_active()`` returns a mask with all currently active lanes in the warp, equivalent to the result ``__activemask()``, and finally
|
||||
- ``this_lane()`` and other functions like ``all_greater()`` or ``all_less_equal()`` return masks depending on the current lane index. They are implemented using the PTX special registers.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``shift`` is in the range ``[0, 32)``.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/std/cassert>
|
||||
#include <cuda/std/type_traits>
|
||||
#include <cuda/warp>
|
||||
|
||||
__global__ void lane_mask_kernel() {
|
||||
// import lane_mask symbol to current scope
|
||||
using cuda::device::lane_mask;
|
||||
// this_lane() is equivalent to ~(all_less() | all_greater())
|
||||
assert(lane_mask::this_lane() == ~(lane_mask::all_less() | lane_mask::all_greater()));
|
||||
}
|
||||
|
||||
int main() {
|
||||
lane_mask_kernel<<<1, 32>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/W7hExs16v>`_
|
||||
@@ -0,0 +1,87 @@
|
||||
.. _libcudacxx-extended-api-warp-warp-match-all:
|
||||
|
||||
``cuda::device::warp_match_all``
|
||||
================================
|
||||
|
||||
Defined in ``<cuda/warp>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda::device {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __device__ bool
|
||||
warp_match_all(const T& data, lane_mask = lane_mask::all());
|
||||
|
||||
} // namespace cuda::device
|
||||
|
||||
The functionality provides a generalized and safe alternative to CUDA warp match all intrinsic ``__match_all_sync``.
|
||||
The function allows bitwise comparison of any data size, including raw arrays, pointers, and structs.
|
||||
|
||||
.. note::
|
||||
|
||||
The underlying CUDA intrinsic does not provide memory ordering.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``data``: data to compare.
|
||||
- ``lane_mask``: mask of the active lanes.
|
||||
|
||||
**Return value**
|
||||
|
||||
- ``true`` if all lanes in the ``lane_mask`` have the same value for ``data``. ``false`` otherwise.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` shall be trivially copyable, see :ref:`cuda::is_trivially_copyable <libcudacxx-extended-api-type_traits-is_trivially_copyable>`.
|
||||
- ``T`` shall be bitwise comparable, see :ref:`cuda::is_bitwise_comparable <libcudacxx-extended-api-type_traits-is_bitwise_comparable>`, except when ``__builtin_clear_padding`` is supported. In the latter case, ``T`` can have padding bits.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- The functionality is only supported on ``SM >= 70``.
|
||||
- ``lane_mask`` must be non-zero.
|
||||
|
||||
**Undefined Behavior**
|
||||
|
||||
- ``lane_mask`` must represent a subset of the active lanes.
|
||||
- All non-exited lanes specified by ``lane_mask`` must execute the function with the same ``lane_mask`` value.
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- The function calls the PTX instruction ``match.sync`` :math:`ceil\left(\frac{sizeof(data)}{4}\right)` times.
|
||||
- The function is faster when called with a mask representing all active lanes in a warp (default value of the second parameter ``lane_mask``).
|
||||
- The function uses ``__ballot_sync`` when ``T`` is ``bool``.
|
||||
|
||||
**References**
|
||||
|
||||
- `CUDA match_all Intrinsics <https://docs.nvidia.com/cuda/cuda-programming-guide/05-appendices/cpp-language-extensions.html#warp-match-functions>`_
|
||||
- `PTX match.sync instruction <https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-match-sync>`_
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/std/array>
|
||||
#include <cuda/std/cassert>
|
||||
#include <cuda/warp>
|
||||
|
||||
struct MyStruct {
|
||||
double x; // 8 bytes
|
||||
int y; // 4 bytes
|
||||
}; // 4 bytes of padding
|
||||
|
||||
__global__ void warp_match_kernel() {
|
||||
assert(cuda::device::warp_match_all(2));
|
||||
assert(cuda::device::warp_match_all(2, cuda::device::lane_mask::all()));
|
||||
assert(cuda::device::warp_match_all(MyStruct{1.0, 3})); // compile error, except when __builtin_clear_padding is supported
|
||||
assert(!cuda::device::warp_match_all(threadIdx.x));
|
||||
}
|
||||
|
||||
int main() {
|
||||
warp_match_kernel<<<1, 32>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/x1sWbx14r>`_
|
||||
@@ -0,0 +1,99 @@
|
||||
.. _libcudacxx-extended-api-warp-warp-match-any:
|
||||
|
||||
``cuda::device::warp_match_any``
|
||||
================================
|
||||
|
||||
Defined in ``<cuda/warp>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda::device {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __device__ lane_mask
|
||||
warp_match_any(const T& data, lane_mask = lane_mask::all());
|
||||
|
||||
} // namespace cuda::device
|
||||
|
||||
The functionality provides a generalized and safe alternative to CUDA warp match any intrinsic ``__match_any_sync``.
|
||||
The function allows bitwise comparison of any data size, including raw arrays, pointers, and structs.
|
||||
|
||||
.. note::
|
||||
|
||||
The underlying CUDA intrinsic does not provide memory ordering.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``data``: data to compare.
|
||||
- ``lane_mask``: mask of the active lanes.
|
||||
|
||||
**Return value**
|
||||
|
||||
- A ``lane_mask`` representing the non-exited lanes in ``lane_mask`` that have the same bitwise value for ``data`` as the calling lane.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` shall be trivially copyable, see :ref:`cuda::is_trivially_copyable <libcudacxx-extended-api-type_traits-is_trivially_copyable>`.
|
||||
- When ``__builtin_clear_padding`` is not supported, ``T`` shall have no padding bits, that is, ``T``'s value representation shall be identical to its object representation.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- The functionality is only supported on ``SM >= 70``.
|
||||
- ``lane_mask`` must be non-zero.
|
||||
|
||||
**Undefined Behavior**
|
||||
|
||||
- ``lane_mask`` must represent a subset of the active lanes.
|
||||
- All non-exited lanes specified by ``lane_mask`` must execute the function with the same ``lane_mask`` value.
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- The function calls the PTX instruction ``match.sync`` :math:`ceil\left(\frac{sizeof(data)}{4}\right)` times.
|
||||
- The function is faster when called with a mask representing all active lanes in a warp (default value of the second parameter ``lane_mask``).
|
||||
- The function uses ``__ballot_sync`` when ``T`` is ``bool``.
|
||||
|
||||
**References**
|
||||
|
||||
- `CUDA match_any Intrinsics <https://docs.nvidia.com/cuda/cuda-programming-guide/05-appendices/cpp-language-extensions.html#warp-match-functions>`_
|
||||
- `PTX match.sync instruction <https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#parallel-synchronization-and-communication-instructions-match-sync>`_
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/std/array>
|
||||
#include <cuda/std/cassert>
|
||||
#include <cuda/warp>
|
||||
|
||||
struct MyStruct {
|
||||
double x; // 8 bytes
|
||||
int y; // 4 bytes
|
||||
}; // 4 bytes of padding
|
||||
|
||||
__global__ void warp_match_kernel() {
|
||||
{
|
||||
auto mask = cuda::device::warp_match_any(threadIdx.x / 4);
|
||||
auto expected = cuda::device::lane_mask{0b1111 << ((threadIdx.x / 4) * 4)};
|
||||
assert(mask == expected);
|
||||
}
|
||||
{
|
||||
auto mask = cuda::device::warp_match_any(2);
|
||||
auto expected = cuda::device::lane_mask{0xFFFFFFFF};
|
||||
assert(mask == expected);
|
||||
}
|
||||
{
|
||||
// compile error, except when __builtin_clear_padding is supported
|
||||
auto mask = cuda::device::warp_match_any(MyStruct{1.0, 3});
|
||||
auto expected = cuda::device::lane_mask{0xFFFFFFFF};
|
||||
assert(mask == expected);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
warp_match_kernel<<<1, 32>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/Ys1McG8nv>`_
|
||||
192
cccl_upstream/docs/libcudacxx/extended_api/warp/warp_shuffle.rst
Normal file
192
cccl_upstream/docs/libcudacxx/extended_api/warp/warp_shuffle.rst
Normal file
@@ -0,0 +1,192 @@
|
||||
.. _libcudacxx-extended-api-warp-warp-shuffle:
|
||||
|
||||
``cuda::device::warp_shuffle_idx/up/down/xor``
|
||||
==============================================
|
||||
|
||||
Defined in ``<cuda/warp>`` header.
|
||||
|
||||
``warp_shuffle_idx``:
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda::device {
|
||||
|
||||
template <int Width = 32, typename T>
|
||||
[[nodiscard]] __device__ warp_shuffle_result<T>
|
||||
warp_shuffle_idx(const T& data,
|
||||
int src_lane,
|
||||
uint32_t lane_mask = 0xFFFFFFFF,
|
||||
cuda::std::integral_constant<int, Width> = {})
|
||||
|
||||
template <int Width = 32, typename T>
|
||||
[[nodiscard]] __device__ warp_shuffle_result<T>
|
||||
warp_shuffle_idx(const T& data,
|
||||
int src_lane,
|
||||
cuda::std::integral_constant<int, Width>) // lane_mask is 0xFFFFFFFF
|
||||
|
||||
} // namespace cuda::device
|
||||
|
||||
``warp_shuffle_up``:
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda::device {
|
||||
|
||||
template <int Width = 32, typename T>
|
||||
[[nodiscard]] __device__ warp_shuffle_result<T>
|
||||
warp_shuffle_up(const T& data,
|
||||
int delta,
|
||||
uint32_t lane_mask = 0xFFFFFFFF,
|
||||
cuda::std::integral_constant<int, Width> = {})
|
||||
|
||||
template <int Width = 32, typename T>
|
||||
[[nodiscard]] __device__ warp_shuffle_result<T>
|
||||
warp_shuffle_up(const T& data,
|
||||
int delta,
|
||||
cuda::std::integral_constant<int, Width>) // lane_mask is 0xFFFFFFFF
|
||||
|
||||
} // namespace cuda::device
|
||||
|
||||
``warp_shuffle_down``:
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda::device {
|
||||
|
||||
template <int Width = 32, typename T>
|
||||
[[nodiscard]] __device__ warp_shuffle_result<T>
|
||||
warp_shuffle_down(const T& data,
|
||||
int delta,
|
||||
uint32_t lane_mask = 0xFFFFFFFF,
|
||||
cuda::std::integral_constant<int, Width> = {})
|
||||
|
||||
template <int Width = 32, typename T>
|
||||
[[nodiscard]] __device__ warp_shuffle_result<T>
|
||||
warp_shuffle_down(const T& data,
|
||||
int delta,
|
||||
cuda::std::integral_constant<int, Width>) // lane_mask is 0xFFFFFFFF
|
||||
|
||||
} // namespace cuda::device
|
||||
|
||||
``warp_shuffle_xor``:
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda::device {
|
||||
|
||||
template <int Width = 32, typename T>
|
||||
[[nodiscard]] __device__ warp_shuffle_result<T>
|
||||
warp_shuffle_xor(const T& data,
|
||||
int xor_mask,
|
||||
uint32_t lane_mask = 0xFFFFFFFF,
|
||||
cuda::std::integral_constant<int, Width> = {})
|
||||
|
||||
template <int Width = 32, typename T>
|
||||
[[nodiscard]] __device__ warp_shuffle_result<T>
|
||||
warp_shuffle_xor(const T& data,
|
||||
int xor_mask,
|
||||
cuda::std::integral_constant<int, Width>) // lane_mask is 0xFFFFFFFF
|
||||
|
||||
} // namespace cuda::device
|
||||
|
||||
Result type:
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda::device {
|
||||
|
||||
template <typename T>
|
||||
struct warp_shuffle_result {
|
||||
T data;
|
||||
bool pred;
|
||||
|
||||
__device__ operator T() const { return data; }
|
||||
};
|
||||
|
||||
} // namespace cuda::device
|
||||
|
||||
The functionality provides a generalized and safe alternative to CUDA warp shuffle intrinsics.
|
||||
The functions allow to exchange data of any data size, including raw arrays, pointers, and structs.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``data``: data to exchange.
|
||||
- ``src_lane``: source lane.
|
||||
- ``delta``: offset from the source lane.
|
||||
- ``xor_mask``: XOR mask to apply to the source lane.
|
||||
|
||||
**Return value**
|
||||
|
||||
``warp_shuffle_result``:
|
||||
|
||||
- ``data``: data of the destination lane.
|
||||
- ``pred``: ``true`` if the destination lane is within the source lane window. ``false`` otherwise.
|
||||
|
||||
**Constrains**
|
||||
|
||||
- ``Width`` must be a power of two in the range [1, 32]
|
||||
- ``T``: all ``T`` are allowed except if ``T`` is a pointer, in which case it must be a ``void`` pointer to avoid bug-prone code
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- The destination lane must be a member of the ``lane_mask``.
|
||||
- ``delta`` and ``xor_mask`` must be less than ``Width``. Modulo behavior is allowed for ``src_lane``.
|
||||
- ``lane_mask`` must be non-zero.
|
||||
|
||||
**Undefined Behavior**
|
||||
|
||||
- ``lane_mask`` must represent a subset of the active lanes, undefined behavior otherwise.
|
||||
- All lanes must have the same value for ``lane_mask``, ``delta`` and ``xor_mask``
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- The function calls the PTX instruction ``shfl.sync`` :math:`ceil\left(\frac{sizeof(data)}{4}\right)` times.
|
||||
|
||||
**References**
|
||||
|
||||
- `CUDA Warp Shuffle Intrinsics <https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#warp-shuffle>`_
|
||||
- `PTX Shfl.sync instruction <https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#data-movement-and-conversion-instructions-shfl-sync>`_
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/std/array>
|
||||
#include <cuda/std/type_traits>
|
||||
#include <cuda/warp>
|
||||
#include <cstdio>
|
||||
|
||||
struct MyStruct {
|
||||
double x;
|
||||
int y;
|
||||
};
|
||||
|
||||
__global__ void warp_shuffle_kernel() {
|
||||
cuda::std::integral_constant<int, 16> half_warp;
|
||||
auto laneid = cuda::ptx::get_sreg_laneid();
|
||||
int raw_array[] = {threadIdx.x, threadIdx.x + 1, threadIdx.x + 2};
|
||||
cuda::std::array<int, 3> array = {threadIdx.x, threadIdx.x + 1, threadIdx.x + 2};
|
||||
MyStruct my_structs{static_cast<double>(threadIdx.x), threadIdx.x + 1};
|
||||
if (laneid < 16) {
|
||||
// lanes [0, 15] get an array with values {5, 6, 7}
|
||||
auto ret = cuda::device::warp_shuffle_idx(raw_array, 5, 0xFFFF, half_warp);
|
||||
printf("lane %2d: [%d, %d, %d]\n", laneid, ret.data[0], ret.data[1], ret.data[2]);
|
||||
|
||||
// lanes [1, 15] get an array with values {threadIdx.x - 1, threadIdx.x, threadIdx.x + 1}
|
||||
// lane 0 keeps the original values
|
||||
auto array_ret = cuda::device::warp_shuffle_up(array, 1, half_warp).data;
|
||||
printf("lane %2d: [%d, %d, %d]\n", laneid, array[0], array[1], array_ret[2]);
|
||||
}
|
||||
// lanes [0, 13] get my_structs with values {threadIdx.x + 2, threadIdx.x + 3} and pred=true
|
||||
auto ret = cuda::device::warp_shuffle_down<16>(my_structs, 2);
|
||||
printf("lane %2d: {%f, %d}, pred %d\n", laneid, ret.data.x, ret.data.y, ret.pred);
|
||||
}
|
||||
|
||||
int main() {
|
||||
warp_shuffle_kernel<<<1, 32>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/soWTaG6Eb>`_
|
||||
Reference in New Issue
Block a user