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,77 @@
|
||||
.. _libcudacxx-extended-api-utility-in-range:
|
||||
|
||||
``in_range``
|
||||
============
|
||||
|
||||
Defined in the ``<cuda/utility>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <typename T>
|
||||
[[nodiscard]] __host__ __device__ constexpr
|
||||
bool in_range(T value, T start, T end) noexcept;
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
Checks whether a value ``value`` is within the range ``[start, end]``, inclusive.
|
||||
|
||||
**Template Parameters**
|
||||
|
||||
- ``T``: the type of the value and the range bounds.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``value``: the value to check if it's within the range.
|
||||
- ``start``: the lower bound of the range.
|
||||
- ``end``: the upper bound of the range.
|
||||
|
||||
**Return Value**
|
||||
|
||||
- ``true`` if ``value`` is in the range ``[start, end]``, ``false`` otherwise.
|
||||
|
||||
**Constraints**
|
||||
|
||||
- ``T`` must be an integer or floating point type.
|
||||
|
||||
**Preconditions**
|
||||
|
||||
- ``end`` must be greater than or equal to ``start``.
|
||||
|
||||
.. note::
|
||||
|
||||
For floating-point types, ``NaN`` is considered a valid value. The function returns ``false`` if any input is ``NaN``.
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- The function is optimized when ``value`` is an unsigned integer type. The optimization is useful when ``start`` and ``end`` are known at compile-time, or when ``in_range`` is used multiple times with the same range.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/utility>
|
||||
#include <cuda/std/cassert>
|
||||
|
||||
__global__ void in_range_kernel() {
|
||||
// unsigned integers
|
||||
assert(cuda::in_range(5u, 1u, 10u)); // 5 is in the range [1, 10]
|
||||
assert(!cuda::in_range(15u, 1u, 10u)); // 15 is NOT in the range [1, 10]
|
||||
assert(cuda::in_range(1u, 1u, 10u)); // 1 is in the range [1, 10]
|
||||
assert(cuda::in_range(10u, 1u, 10u)); // 10 is in the range [1, 10]
|
||||
assert(cuda::in_range(10u, 10u, 10u)); // 10 is in the range [10, 10]
|
||||
|
||||
// signed integers
|
||||
assert(cuda::in_range(-5, -10, 0)); // -5 is in the range [-10, 0]
|
||||
assert(!cuda::in_range(5, -10, 0)); // 5 is NOT in the range [-10, 0]
|
||||
}
|
||||
|
||||
int main() {
|
||||
in_range_kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
`See the example in Compiler Explorer 🔗 <https://godbolt.org/z/WjG4rWT3G>`_
|
||||
@@ -0,0 +1,92 @@
|
||||
.. _libcudacxx-extended-api-utility-static-for:
|
||||
|
||||
``static_for``
|
||||
==============
|
||||
|
||||
Defined in ``<cuda/utility>`` header.
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
namespace cuda {
|
||||
|
||||
template <auto Size, typename Operator, typename... TArgs>
|
||||
__host__ __device__ constexpr
|
||||
void static_for(Operator op, TArgs&&... args) noexcept(/*see-below*/); // (1)
|
||||
|
||||
template <auto Start, decltype(Start) End, decltype(Start) Step = 1, typename Operator, typename... TArgs>
|
||||
__host__ __device__ constexpr
|
||||
void static_for(Operator op, TArgs&&... args) noexcept(/*see-below*/); // (2)
|
||||
|
||||
template <typename T, T Size, typename Operator, typename... TArgs>
|
||||
__host__ __device__ constexpr
|
||||
void static_for(Operator op, TArgs&&... args) noexcept(/*see-below*/); // (3)
|
||||
|
||||
template <typename T, T Start, T End, T Step = 1, typename Operator, typename... TArgs>
|
||||
__host__ __device__ constexpr
|
||||
void static_for(Operator op, TArgs&&... args) noexcept(/*see-below*/); // (4)
|
||||
|
||||
} // namespace cuda
|
||||
|
||||
| The functionality provides a ``for`` loop with compile-time indices.
|
||||
| ``static_for`` is available in two forms:
|
||||
|
||||
- Executes ``op`` for each value in the range ``[0, Size)`` (1, 3).
|
||||
- Executes ``op`` for each value in the range ``[Start, End)`` with step ``Step`` (2, 4).
|
||||
|
||||
| The function is ``noexcept`` if all invocations of ``op`` with ``integral_constant</*index-type*/, /*index-value*/>`` and the ``args...`` are *non-throwing*. Only visited indices participate in the ``noexcept`` evaluation.
|
||||
|
||||
**Parameters**
|
||||
|
||||
- ``Size``: the number of iterations (1, 3).
|
||||
- ``Start``, ``End``, ``Step``: the start, end, and step of the range. Note that ``End`` and ``Step`` are converted to the type of ``Start`` (2, 4).
|
||||
- ``T``: type of the loop index (3, 4).
|
||||
- ``op``: the function to execute.
|
||||
- ``args``: additional arguments to pass to ``op``.
|
||||
|
||||
``op`` is a callable object that accepts an ``integral_constant`` of the same type of ``Size`` or ``Start``.
|
||||
|
||||
**Performance considerations**
|
||||
|
||||
- The functions are useful as metaprogramming utility and when a loop requires full unrolling, independently of the compiler's constrains, optimization level, and heuristics. In addition, the index is a compile-time constant, which can be used in a constant expression and further optimize the code.
|
||||
|
||||
- Conversely, ``static_for`` is more expensive to compile compared to ``#pragma unroll``. Additionally, the preprocessor directive interacts with the compiler, which tunes the loop unrolling based on register usage, binary size, and instruction cache.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code:: cuda
|
||||
|
||||
#include <cuda/utility>
|
||||
#include <cstdio>
|
||||
|
||||
__global__ void kernel() {
|
||||
cuda::static_for<5>([](auto i){ static_assert(i >= 0 && i < 5); });
|
||||
|
||||
cuda::static_for<5>([](auto i){ printf("%d, ", i()); }); // 0, 1, 2, 3, 4,
|
||||
printf("\n");
|
||||
|
||||
cuda::static_for<short, 5>([](auto i){ printf("%d, ", i()); }); // 0, 1, 2, 3, 4,
|
||||
printf("\n");
|
||||
|
||||
cuda::static_for<-5, 7, 3>([](auto i){ printf("%d, ", i()); }); // -5, -2, 1, 4,
|
||||
printf("\n");
|
||||
|
||||
cuda::static_for<5>([](auto i){
|
||||
if constexpr (i > 0) {
|
||||
cuda::static_for<i()>([](auto j){ printf("%d, ", j()); });
|
||||
printf("\n");
|
||||
}
|
||||
});
|
||||
// 0,
|
||||
// 0, 1,
|
||||
// 0, 1, 2,
|
||||
// 0, 1, 2, 3,
|
||||
cuda::static_for<5>([](auto i, int a, int b, int c){}, 1, 2, 3); // 1, 2, 3 optional arguments
|
||||
}
|
||||
|
||||
int main() {
|
||||
kernel<<<1, 1>>>();
|
||||
cudaDeviceSynchronize();
|
||||
}
|
||||
|
||||
`See it on Godbolt 🔗 <https://godbolt.org/z/1GWc4dqKj>`_
|
||||
Reference in New Issue
Block a user