Files
project_6/cccl_upstream/libcudacxx/include/cuda/__mdspan/strides.h
EngineX CI 56fd68e7dd [INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides:
- CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk)
- Thrust: high-level parallel algorithms (transform_reduce, sort, scan)
- libcudacxx: CUDA C++ standard library (atomics, barriers, memory)
- cudax: experimental features (memory resources, allocators)
- Tuning policies: per-SM hardware-specific algorithm parameters

Competition optimization vectors mapped to CCCL:
- Output TPS (83% weight): warp_reduce, block_reduce, device_topk
- Input TPS (14% weight): device_scan, block_load, prefetch
- Cache TPS (3% weight): prefix caching strategy patterns
- Memory (0.9 util): pooled/cached/buddy allocators

Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only)
License: Apache-2.0
2026-07-30 09:35:51 +00:00

260 lines
10 KiB
C++

//===----------------------------------------------------------------------===//
//
// Part of libcu++, the C++ Standard Library for your entire system,
// under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//
#ifndef _CUDA___MDSPAN_STRIDES_H
#define _CUDA___MDSPAN_STRIDES_H
#include <cuda/std/detail/__config>
#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
# pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
# pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
# pragma system_header
#endif // no system header
#include <cuda/__fwd/mdspan.h>
#include <cuda/std/__concepts/concept_macros.h>
#include <cuda/std/__cstddef/types.h>
#include <cuda/std/__mdspan/extents.h>
#include <cuda/std/__type_traits/is_convertible.h>
#include <cuda/std/__type_traits/is_nothrow_constructible.h>
#include <cuda/std/__type_traits/is_signed_integer.h>
#include <cuda/std/__type_traits/make_unsigned.h>
#include <cuda/std/__utility/cmp.h>
#include <cuda/std/array>
#include <cuda/std/span>
#include <cuda/std/__cccl/prologue.h>
_CCCL_BEGIN_NAMESPACE_CUDA
// ------------------------------------------------------------------
// ------------ strides ---------------------------------------------
// ------------------------------------------------------------------
//! @brief Class to describe the strides of a multi-dimensional array layout.
//!
//! Similar to extents, but for strides. Supports both static (compile-time known)
//! and dynamic (runtime) stride values. Uses dynamic_stride as the tag for dynamic values.
//!
//! @tparam _OffsetType The signed integer type for stride values (supports negative strides)
//! @tparam _Strides... The stride values, where dynamic_stride indicates a runtime value
template <class _OffsetType, ::cuda::std::ptrdiff_t... _Strides>
class strides
: private ::cuda::std::__mdspan_detail::
__maybe_static_array<_OffsetType, ::cuda::std::ptrdiff_t, dynamic_stride, _Strides...>
{
public:
using offset_type = _OffsetType;
using size_type = ::cuda::std::make_unsigned_t<offset_type>;
using rank_type = ::cuda::std::size_t;
private:
static_assert(::cuda::std::__cccl_is_signed_integer_v<_OffsetType>,
"strides::offset_type must be a signed integer type");
template <class... _From>
[[nodiscard]] _CCCL_API static constexpr bool __is_representable_as(_From... __values) noexcept
{
return (
(::cuda::std::in_range<offset_type>(__values) || static_cast<::cuda::std::ptrdiff_t>(__values) == dynamic_stride)
&& ...);
}
static_assert(__is_representable_as(_Strides...), "_Strides must be representable as offset_type");
static constexpr rank_type __rank_ = sizeof...(_Strides);
static constexpr rank_type __rank_dynamic_ =
::cuda::std::__mdspan_detail::__count_dynamic_v<::cuda::std::ptrdiff_t, dynamic_stride, _Strides...>;
template <class _OtherIndexType>
static constexpr bool __is_convertible_to_index_type =
::cuda::std::is_convertible_v<const _OtherIndexType&, offset_type>
&& ::cuda::std::is_nothrow_constructible_v<offset_type, const _OtherIndexType&>;
using _Values =
::cuda::std::__mdspan_detail::__maybe_static_array<_OffsetType, ::cuda::std::ptrdiff_t, dynamic_stride, _Strides...>;
public:
[[nodiscard]] _CCCL_API static constexpr rank_type rank() noexcept
{
return __rank_;
}
[[nodiscard]] _CCCL_API static constexpr rank_type rank_dynamic() noexcept
{
return __rank_dynamic_;
}
[[nodiscard]] _CCCL_API constexpr offset_type stride(rank_type __r) const noexcept
{
return this->__value(__r);
}
[[nodiscard]] _CCCL_API static constexpr ::cuda::std::ptrdiff_t static_stride(rank_type __r) noexcept
{
return _Values::__static_value(__r);
}
_CCCL_HIDE_FROM_ABI constexpr strides() noexcept = default;
// Construction from just dynamic or all values
_CCCL_TEMPLATE(class... _OtherIndexTypes)
_CCCL_REQUIRES((sizeof...(_OtherIndexTypes) == __rank_ || sizeof...(_OtherIndexTypes) == __rank_dynamic_)
_CCCL_AND(__is_convertible_to_index_type<_OtherIndexTypes>&&...))
_CCCL_API constexpr explicit strides(_OtherIndexTypes... __dynvals) noexcept
: _Values(static_cast<offset_type>(__dynvals)...)
{
_CCCL_ASSERT(__is_representable_as(__dynvals...), "strides ctor: arguments must be representable as offset_type");
}
_CCCL_TEMPLATE(class _OtherIndexType, ::cuda::std::size_t _Size)
_CCCL_REQUIRES((_Size == __rank_dynamic_) _CCCL_AND __is_convertible_to_index_type<_OtherIndexType>)
_CCCL_API constexpr strides(::cuda::std::span<_OtherIndexType, _Size> __strs) noexcept
: _Values(__strs)
{
for ([[maybe_unused]] const auto& __value : __strs)
{
_CCCL_ASSERT(__is_representable_as(__value), "strides ctor: arguments must be representable as offset_type");
}
}
_CCCL_TEMPLATE(class _OtherIndexType, ::cuda::std::size_t _Size)
_CCCL_REQUIRES((_Size != __rank_dynamic_) _CCCL_AND(_Size == __rank_)
_CCCL_AND __is_convertible_to_index_type<_OtherIndexType>)
_CCCL_API explicit constexpr strides(::cuda::std::span<_OtherIndexType, _Size> __strs) noexcept
: _Values(__strs)
{
for ([[maybe_unused]] const auto& __value : __strs)
{
_CCCL_ASSERT(__is_representable_as(__value), "strides ctor: arguments must be representable as offset_type");
}
}
_CCCL_TEMPLATE(class _OtherIndexType, ::cuda::std::size_t _Size)
_CCCL_REQUIRES((_Size == __rank_dynamic_) _CCCL_AND __is_convertible_to_index_type<_OtherIndexType>)
_CCCL_API constexpr strides(const ::cuda::std::array<_OtherIndexType, _Size>& __strs) noexcept
: strides(::cuda::std::span<const _OtherIndexType, _Size>(__strs))
{}
_CCCL_TEMPLATE(class _OtherIndexType, ::cuda::std::size_t _Size)
_CCCL_REQUIRES((_Size == __rank_) _CCCL_AND(_Size != __rank_dynamic_)
_CCCL_AND __is_convertible_to_index_type<_OtherIndexType>)
_CCCL_API explicit constexpr strides(const ::cuda::std::array<_OtherIndexType, _Size>& __strs) noexcept
: strides(::cuda::std::span<const _OtherIndexType, _Size>(__strs))
{}
private:
// Helper to construct from other strides
template <::cuda::std::size_t _DynCount, ::cuda::std::size_t _Idx, class _OtherStrides, class... _DynamicValues>
[[nodiscard]] _CCCL_API constexpr _Values __construct_vals_from_strides(
[[maybe_unused]] const _OtherStrides& __strs, _DynamicValues... __dynamic_values) noexcept
{
if constexpr (_Idx == __rank_)
{
static_assert(_DynCount == __rank_dynamic_, "Constructor of invalid strides passed to strides::strides");
return _Values{static_cast<offset_type>(__dynamic_values)...};
}
else if constexpr (static_stride(_Idx) == dynamic_stride)
{
return __construct_vals_from_strides<_DynCount + 1, _Idx + 1>(__strs, __dynamic_values..., __strs.stride(_Idx));
}
else
{
return __construct_vals_from_strides<_DynCount, _Idx + 1>(__strs, __dynamic_values...);
}
}
struct __strides_delegate_tag
{};
template <class _OtherIndexType, ::cuda::std::ptrdiff_t... _OtherStrides>
_CCCL_API constexpr strides(__strides_delegate_tag, const strides<_OtherIndexType, _OtherStrides...>& __other) noexcept
: _Values(__construct_vals_from_strides<0, 0>(__other))
{
if constexpr (__rank_ != 0)
{
for (::cuda::std::size_t __r = 0; __r != __rank_; __r++)
{
_CCCL_ASSERT(__is_representable_as(__other.stride(__r)), "strides construction: stride is out of range");
_CCCL_ASSERT(_Values::__static_value(__r) == dynamic_stride
|| ::cuda::std::cmp_equal(__other.stride(__r), _Values::__static_value(__r)),
"strides construction: mismatch of provided arguments with static strides.");
}
}
}
// Converting constructor from other strides specializations
template <class _OtherIndexType, ::cuda::std::ptrdiff_t... _OtherStrides>
static constexpr bool __is_explicit_conversion =
(((_Strides != dynamic_stride) && (_OtherStrides == dynamic_stride)) || ...);
template <::cuda::std::ptrdiff_t... _OtherStrides>
static constexpr bool __is_matching_strides =
((_OtherStrides == dynamic_stride || _Strides == dynamic_stride || _OtherStrides == _Strides) && ...);
public:
_CCCL_TEMPLATE(class _OtherIndexType, ::cuda::std::ptrdiff_t... _OtherStrides)
_CCCL_REQUIRES((sizeof...(_OtherStrides) == sizeof...(_Strides)) _CCCL_AND __is_matching_strides<_OtherStrides...>
_CCCL_AND(!__is_explicit_conversion<_OtherIndexType, _OtherStrides...>))
_CCCL_API constexpr strides(const strides<_OtherIndexType, _OtherStrides...>& __other) noexcept
: strides(__strides_delegate_tag{}, __other)
{}
_CCCL_TEMPLATE(class _OtherIndexType, ::cuda::std::ptrdiff_t... _OtherStrides)
_CCCL_REQUIRES((sizeof...(_OtherStrides) == sizeof...(_Strides))
_CCCL_AND __is_matching_strides<_OtherStrides...> _CCCL_AND
__is_explicit_conversion<_OtherIndexType, _OtherStrides...>)
_CCCL_API explicit constexpr strides(const strides<_OtherIndexType, _OtherStrides...>& __other) noexcept
: strides(__strides_delegate_tag{}, __other)
{}
// Comparison operator
template <class _OtherIndexType, ::cuda::std::ptrdiff_t... _OtherStrides>
[[nodiscard]] _CCCL_API friend constexpr bool
operator==(const strides& __lhs, const strides<_OtherIndexType, _OtherStrides...>& __rhs) noexcept
{
if constexpr (__rank_ != sizeof...(_OtherStrides))
{
return false;
}
else
{
bool __result = true;
for (rank_type __r = 0; __r != __rank_; __r++)
{
if (::cuda::std::cmp_not_equal(__lhs.stride(__r), __rhs.stride(__r)))
{
__result = false;
break;
}
}
return __result;
}
}
#if _CCCL_STD_VER <= 2017
template <class _OtherIndexType, ::cuda::std::ptrdiff_t... _OtherStrides>
[[nodiscard]] _CCCL_API friend constexpr bool
operator!=(const strides& __lhs, const strides<_OtherIndexType, _OtherStrides...>& __rhs) noexcept
{
return !(__lhs == __rhs);
}
#endif // _CCCL_STD_VER <= 2017
};
_CCCL_END_NAMESPACE_CUDA
#include <cuda/std/__cccl/epilogue.h>
#endif // _CUDA___MDSPAN_STRIDES_H