[CCCL] 瘦身 + 补全: 移除 cudax/python/libcudacxx-tests 冗余文件, 新增 c2h 测试助手 + cmake 构建系统 + 8 个 CUDA thrust examples
变更摘要:
- 删除: cudax/ (783 files, 7.2M) — 实验性组件,竞赛不需要
- 删除: python/ (226 files, 2.0M) — Python 绑定,竞赛不需要
- 删除: libcudacxx/{test,benchmarks,codegen,cmake,share} (4432 files, 31M)
保留: libcudacxx/include/ (1463 headers, cuda::std 编译依赖)
- 新增: c2h/ (27 files) — CUB Catch2 测试辅助头文件,编译 243 个测试必需
- 新增: cmake/ (29 files) — CCCL 原生 CMake 构建系统
- 新增: thrust/examples/cuda/ (7 files) + cpp_integration/ (1 file)
async_reduce, custom_temporary_allocation, explicit_cuda_stream,
global_device_vector, range_view, unwrap_pointer, wrap_pointer, device
结果: cccl_upstream 从 74M→35M (瘦身 53%), 核心内容 100% 保留:
27/27 tuning headers, 78 benchmarks, 243 tests,
60 thrust examples, 18 CUB examples, 全部编译头文件
This commit is contained in:
@@ -1,69 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDA Experimental in CUDA C++ Core Libraries,
|
||||
// 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) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDAX__UTILITY_ENSURE_CURRENT_DEVICE_CUH
|
||||
#define _CUDAX__UTILITY_ENSURE_CURRENT_DEVICE_CUH
|
||||
|
||||
#include <cuda/__cccl_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/__runtime/ensure_current_context.h>
|
||||
|
||||
#include <cuda/experimental/__device/logical_device.cuh>
|
||||
#include <cuda/experimental/__graph/concepts.cuh>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
#ifndef _CCCL_DOXYGEN_INVOKED // Do not document
|
||||
|
||||
namespace cuda::experimental
|
||||
{
|
||||
//! TODO we might want to change the comments to indicate it operates on contexts for certains differences
|
||||
//! with green context, but it depends on how exactly green context internals end up being
|
||||
|
||||
//! @brief RAII helper which on construction sets the current device to the specified one or one a
|
||||
//! stream was created under. It sets the state back on destruction.
|
||||
//!
|
||||
struct [[maybe_unused]] __ensure_current_device : ::cuda::__ensure_current_context
|
||||
{
|
||||
using __ensure_current_context::__ensure_current_context;
|
||||
|
||||
//! @brief Construct a new `__ensure_current_device` object and switch to the specified
|
||||
//! device.
|
||||
//!
|
||||
//! Note: if this logical device contains a green_context the device under which the green
|
||||
//! context was created will be set to current
|
||||
//!
|
||||
//! @param new_device The device to switch to
|
||||
//!
|
||||
//! @throws cuda_error if the device switch fails
|
||||
explicit __ensure_current_device(logical_device __new_device)
|
||||
: __ensure_current_context(__new_device.context())
|
||||
{}
|
||||
|
||||
_CCCL_TEMPLATE(typename _GraphInserter)
|
||||
_CCCL_REQUIRES(graph_inserter<_GraphInserter>)
|
||||
explicit __ensure_current_device(const _GraphInserter& __inserter)
|
||||
: __ensure_current_device(__inserter.get_device())
|
||||
{}
|
||||
};
|
||||
} // namespace cuda::experimental
|
||||
#endif // _CCCL_DOXYGEN_INVOKED
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDAX__UTILITY_ENSURE_CURRENT_DEVICE_CUH
|
||||
@@ -1,80 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDA Experimental in CUDA C++ Core Libraries,
|
||||
// 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) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __CUDAX_EXPERIMENTAL_UTILITY_MANUAL_LIFETIME
|
||||
#define __CUDAX_EXPERIMENTAL_UTILITY_MANUAL_LIFETIME
|
||||
|
||||
#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/std/__cstddef/byte.h>
|
||||
#include <cuda/std/__memory/addressof.h>
|
||||
#include <cuda/std/__new/device_new.h>
|
||||
#include <cuda/std/__new/launder.h>
|
||||
#include <cuda/std/__type_traits/is_callable.h>
|
||||
#include <cuda/std/__type_traits/is_nothrow_constructible.h>
|
||||
|
||||
#include <cuda/experimental/__execution/prologue.cuh>
|
||||
|
||||
namespace cuda::experimental
|
||||
{
|
||||
/// @brief A lazy type that can be used to delay the construction of a type.
|
||||
template <class _Ty>
|
||||
struct __manual_lifetime
|
||||
{
|
||||
template <class... _Ts>
|
||||
_CCCL_HOST_DEVICE_API auto __construct(_Ts&&... __ts) noexcept(::cuda::std::is_nothrow_constructible_v<_Ty, _Ts...>)
|
||||
-> _Ty&
|
||||
{
|
||||
// Use placement new directly instead of construct_at so we can use braced-init-list
|
||||
// construction
|
||||
_Ty* __value_ptr = ::new (static_cast<void*>(__data_)) _Ty{static_cast<_Ts&&>(__ts)...};
|
||||
return *::cuda::std::launder(__value_ptr);
|
||||
}
|
||||
|
||||
template <class _Fn, class... _Ts>
|
||||
_CCCL_HOST_DEVICE_API auto
|
||||
__construct_from(_Fn&& __fn, _Ts&&... __ts) noexcept(::cuda::std::__is_nothrow_callable_v<_Fn, _Ts...>) -> _Ty&
|
||||
{
|
||||
// Use placement new directly instead of construct_at so we can use braced-init-list
|
||||
// construction
|
||||
_Ty* __value_ptr = ::new (static_cast<void*>(__data_)) _Ty{static_cast<_Fn&&>(__fn)(static_cast<_Ts&&>(__ts)...)};
|
||||
return *::cuda::std::launder(__value_ptr);
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API auto __get() noexcept -> _Ty*
|
||||
{
|
||||
return reinterpret_cast<_Ty*>(__data_);
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API auto __get() const noexcept -> const _Ty*
|
||||
{
|
||||
return reinterpret_cast<const _Ty*>(__data_);
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API void __destroy() noexcept
|
||||
{
|
||||
__get()->~_Ty();
|
||||
}
|
||||
|
||||
alignas(_Ty)::cuda::std::byte __data_[sizeof(_Ty)];
|
||||
};
|
||||
} // namespace cuda::experimental
|
||||
|
||||
#include <cuda/experimental/__execution/epilogue.cuh>
|
||||
|
||||
#endif // __CUDAX_EXPERIMENTAL_UTILITY_MANUAL_LIFETIME
|
||||
@@ -1,93 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDA Experimental in CUDA C++ Core Libraries,
|
||||
// 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) 2022-2026 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDAX__UTILITY_MEYERS_SINGLETON
|
||||
#define _CUDAX__UTILITY_MEYERS_SINGLETON
|
||||
|
||||
#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/std/__type_traits/is_constructible.h>
|
||||
#include <cuda/std/__type_traits/is_copy_constructible.h>
|
||||
#include <cuda/std/__type_traits/is_default_constructible.h>
|
||||
#include <cuda/std/__type_traits/is_destructible.h>
|
||||
#include <cuda/std/__type_traits/is_move_constructible.h>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
namespace cuda::experimental
|
||||
{
|
||||
//! @brief A singleton template class implementing the Meyers Singleton design pattern.
|
||||
//!
|
||||
//! @tparam _Tp The type of the singleton object.
|
||||
//!
|
||||
//! Uses the "Construct On First Use Idiom" to prevent issues related to
|
||||
//! the static initialization order fiasco.
|
||||
//!
|
||||
//! Usage rules:
|
||||
//! - The default constructor of `_Tp` should be protected.
|
||||
//! - The destructor of `_Tp` should be protected.
|
||||
//! - The copy and move constructors of `_Tp` should be disabled (implicit if you follow the rules above).
|
||||
//!
|
||||
//! Example usage:
|
||||
//! @code
|
||||
//! class my_singleton : public meyers_singleton<my_singleton> {
|
||||
//! protected:
|
||||
//! my_singleton() = default;
|
||||
//! ~my_singleton() = default;
|
||||
//! };
|
||||
//! @endcode
|
||||
template <class _Tp>
|
||||
class meyers_singleton
|
||||
{
|
||||
protected:
|
||||
template <class _Up>
|
||||
struct __wrapper
|
||||
{
|
||||
using type = _Up;
|
||||
};
|
||||
friend typename __wrapper<_Tp>::type;
|
||||
|
||||
meyers_singleton() = default;
|
||||
~meyers_singleton() = default;
|
||||
meyers_singleton(const meyers_singleton&) = delete;
|
||||
meyers_singleton(meyers_singleton&&) = delete;
|
||||
|
||||
public:
|
||||
//! @brief Provides access to the single instance of the class.
|
||||
//!
|
||||
//! @return A reference to the singleton instance.
|
||||
//!
|
||||
//! If the instance hasn't been created yet, this function will create it.
|
||||
static _Tp& instance() noexcept
|
||||
{
|
||||
static_assert(!::cuda::std::is_default_constructible_v<_Tp>,
|
||||
"Make the default constructor of your Meyers singleton protected.");
|
||||
static_assert(!::cuda::std::is_destructible_v<_Tp>, "Make the destructor of your Meyers singleton protected.");
|
||||
static_assert(!::cuda::std::is_copy_constructible_v<_Tp>, "Disable the copy constructor of your Meyers singleton.");
|
||||
static_assert(!::cuda::std::is_move_constructible_v<_Tp>, "Disable the move constructor of your Meyers singleton.");
|
||||
struct _Derived : _Tp
|
||||
{};
|
||||
static _Derived __instance;
|
||||
return __instance;
|
||||
}
|
||||
};
|
||||
} // namespace cuda::experimental
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDAX__UTILITY_MEYERS_SINGLETON
|
||||
@@ -1,246 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDA Experimental in CUDA C++ Core Libraries,
|
||||
// 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) 2022-2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDAX__UTILITY_OPTIONALLY_STATIC
|
||||
#define _CUDAX__UTILITY_OPTIONALLY_STATIC
|
||||
|
||||
#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/std/__type_traits/conditional.h>
|
||||
#include <cuda/std/__type_traits/enable_if.h>
|
||||
#include <cuda/std/__type_traits/is_floating_point.h>
|
||||
#include <cuda/std/__type_traits/is_same.h>
|
||||
#include <cuda/std/__type_traits/is_unsigned.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace cuda::experimental
|
||||
{
|
||||
template <typename _Vp>
|
||||
constexpr _Vp __get_reserved_default()
|
||||
{
|
||||
return ::std::is_floating_point_v<_Vp> ? -::std::numeric_limits<_Vp>::max()
|
||||
: ::std::is_unsigned_v<_Vp>
|
||||
? ::std::numeric_limits<_Vp>::max()
|
||||
: ::std::numeric_limits<_Vp>::min();
|
||||
}
|
||||
|
||||
template <auto _Vp>
|
||||
using __copy_type_t = decltype(_Vp);
|
||||
|
||||
//! @brief A value that can be either a compile-time constant or a runtime value.
|
||||
//!
|
||||
//! When `_StaticV != _Reserved`, the value is known at compile time and occupies
|
||||
//! no storage. When `_StaticV == _Reserved`, the value is dynamic and stored in
|
||||
//! the object.
|
||||
//!
|
||||
//! All arithmetic and comparison operators are supported when the underlying
|
||||
//! type supports them.
|
||||
//!
|
||||
//! @tparam _StaticV The static value. Equal to `_Reserved` for dynamic values.
|
||||
//! @tparam _Reserved A sentinel indicating the value is dynamic.
|
||||
template <auto _StaticV, __copy_type_t<_StaticV> _Reserved = __get_reserved_default<__copy_type_t<_StaticV>>()>
|
||||
class optionally_static
|
||||
{
|
||||
public:
|
||||
using type = decltype(_StaticV);
|
||||
|
||||
static constexpr bool is_static = _StaticV != _Reserved;
|
||||
|
||||
static constexpr auto reserved_v = _Reserved;
|
||||
|
||||
constexpr optionally_static() = default;
|
||||
constexpr optionally_static(const optionally_static&) = default;
|
||||
constexpr optionally_static& operator=(const optionally_static&) = default;
|
||||
|
||||
//! @brief Construct a dynamic value. Only valid when `_StaticV == _Reserved`.
|
||||
//! @param[in] __dynamic_value The runtime value.
|
||||
constexpr optionally_static(type __dynamic_value)
|
||||
: __payload(__dynamic_value)
|
||||
{}
|
||||
|
||||
//! @brief Retrieve the stored value (static or dynamic).
|
||||
//! @return The stored value.
|
||||
constexpr type get() const
|
||||
{
|
||||
if constexpr (is_static)
|
||||
{
|
||||
return _StaticV;
|
||||
}
|
||||
else
|
||||
{
|
||||
return __payload;
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Implicit conversion to the underlying type.
|
||||
constexpr operator type() const
|
||||
{
|
||||
return get();
|
||||
}
|
||||
|
||||
//! @brief Retrieve a mutable reference to the stored dynamic value.
|
||||
//! @return Reference to the dynamic payload.
|
||||
constexpr type& get_ref()
|
||||
{
|
||||
return __payload;
|
||||
}
|
||||
|
||||
optionally_static& operator++()
|
||||
{
|
||||
++get_ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
optionally_static operator++(int)
|
||||
{
|
||||
auto __copy = *this;
|
||||
++*this;
|
||||
return __copy;
|
||||
}
|
||||
|
||||
optionally_static& operator--()
|
||||
{
|
||||
--get_ref();
|
||||
return *this;
|
||||
}
|
||||
|
||||
optionally_static operator--(int)
|
||||
{
|
||||
auto __copy = *this;
|
||||
--*this;
|
||||
return __copy;
|
||||
}
|
||||
|
||||
optionally_static operator+() const
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator-() const
|
||||
{
|
||||
if constexpr (!is_static)
|
||||
{
|
||||
return -get();
|
||||
}
|
||||
else if constexpr (-_StaticV == _Reserved)
|
||||
{
|
||||
return _Reserved;
|
||||
}
|
||||
else
|
||||
{
|
||||
return optionally_static<-_StaticV, _Reserved>();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct __nonesuch
|
||||
{};
|
||||
using __state_t = ::cuda::std::conditional_t<is_static, __nonesuch, type>;
|
||||
[[no_unique_address]] __state_t __payload = __state_t();
|
||||
};
|
||||
|
||||
#ifndef _CCCL_DOXYGEN_INVOKED
|
||||
|
||||
// clang-format off
|
||||
# define _CUDAX_OPTIONALLY_STATIC_BINARY_OP(op) \
|
||||
template <auto _V1, auto _V2, auto _R> \
|
||||
constexpr auto operator op(const optionally_static<_V1, _R>& __lhs, \
|
||||
const optionally_static<_V2, _R>& __rhs) \
|
||||
{ \
|
||||
if constexpr (!::std::remove_reference_t<decltype(__lhs)>::is_static \
|
||||
|| !::std::remove_reference_t<decltype(__rhs)>::is_static) \
|
||||
{ \
|
||||
return __lhs.get() op __rhs.get(); \
|
||||
} \
|
||||
else if constexpr ((_V1 op _V2) == _R) \
|
||||
{ \
|
||||
return _R; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
return optionally_static<(_V1 op _V2), _R>(); \
|
||||
} \
|
||||
} \
|
||||
template <auto _V, auto _R, typename _Tp> \
|
||||
constexpr auto operator op(const optionally_static<_V, _R>& __lhs, const _Tp& __rhs) \
|
||||
{ \
|
||||
return __lhs.get() op __rhs; \
|
||||
} \
|
||||
template <auto _V, auto _R, typename _Tp> \
|
||||
constexpr auto operator op(const _Tp& __lhs, const optionally_static<_V, _R>& __rhs) \
|
||||
{ \
|
||||
return __lhs op __rhs.get(); \
|
||||
} \
|
||||
template <auto _V2, auto _R> \
|
||||
constexpr auto& operator op##=(optionally_static<_R, _R>& __lhs, \
|
||||
const optionally_static<_V2, _R>& __rhs) \
|
||||
{ \
|
||||
return __lhs.get_ref() op## = __rhs.get(); \
|
||||
} \
|
||||
template <auto _R, typename _Tp> \
|
||||
constexpr auto& operator op##=(optionally_static<_R, _R>& __lhs, const _Tp & __rhs) \
|
||||
{ \
|
||||
return __lhs.get_ref() op## = __rhs; \
|
||||
}
|
||||
|
||||
_CUDAX_OPTIONALLY_STATIC_BINARY_OP(+)
|
||||
_CUDAX_OPTIONALLY_STATIC_BINARY_OP(-)
|
||||
_CUDAX_OPTIONALLY_STATIC_BINARY_OP(*)
|
||||
_CUDAX_OPTIONALLY_STATIC_BINARY_OP(/)
|
||||
_CUDAX_OPTIONALLY_STATIC_BINARY_OP(%)
|
||||
_CUDAX_OPTIONALLY_STATIC_BINARY_OP(&)
|
||||
_CUDAX_OPTIONALLY_STATIC_BINARY_OP(|)
|
||||
_CUDAX_OPTIONALLY_STATIC_BINARY_OP(^)
|
||||
|
||||
# undef _CUDAX_OPTIONALLY_STATIC_BINARY_OP
|
||||
|
||||
# define _CUDAX_OPTIONALLY_STATIC_COMPARISON_OP(op) \
|
||||
template <auto _V1, auto _V2, auto _R> \
|
||||
constexpr bool operator op(const optionally_static<_V1, _R>& __lhs, \
|
||||
const optionally_static<_V2, _R>& __rhs) \
|
||||
{ \
|
||||
return __lhs.get() op __rhs.get(); \
|
||||
} \
|
||||
template <auto _V, auto _R, typename _Tp, \
|
||||
typename = ::std::enable_if_t<!::std::is_same_v<_Tp, optionally_static<_V, _R>>>> \
|
||||
constexpr bool operator op(const optionally_static<_V, _R>& __lhs, const _Tp& __rhs) \
|
||||
{ \
|
||||
return __lhs.get() op __rhs; \
|
||||
} \
|
||||
template <auto _V, auto _R, typename _Tp, \
|
||||
typename = ::std::enable_if_t<!::std::is_same_v<_Tp, optionally_static<_V, _R>>>> \
|
||||
constexpr bool operator op(const _Tp& __lhs, const optionally_static<_V, _R>& __rhs) \
|
||||
{ \
|
||||
return __lhs op __rhs.get(); \
|
||||
}
|
||||
|
||||
_CUDAX_OPTIONALLY_STATIC_COMPARISON_OP(==)
|
||||
_CUDAX_OPTIONALLY_STATIC_COMPARISON_OP(!=)
|
||||
_CUDAX_OPTIONALLY_STATIC_COMPARISON_OP(<)
|
||||
_CUDAX_OPTIONALLY_STATIC_COMPARISON_OP(>)
|
||||
_CUDAX_OPTIONALLY_STATIC_COMPARISON_OP(<=)
|
||||
_CUDAX_OPTIONALLY_STATIC_COMPARISON_OP(>=)
|
||||
|
||||
# undef _CUDAX_OPTIONALLY_STATIC_COMPARISON_OP
|
||||
// clang-format on
|
||||
|
||||
#endif // _CCCL_DOXYGEN_INVOKED
|
||||
} // namespace cuda::experimental
|
||||
|
||||
#endif // _CUDAX__UTILITY_OPTIONALLY_STATIC
|
||||
@@ -1,85 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDA Experimental in CUDA C++ Core Libraries,
|
||||
// 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_EXPERIMENTAL___UTILITY_RESULT_POLICY_CUH
|
||||
#define _CUDA_EXPERIMENTAL___UTILITY_RESULT_POLICY_CUH
|
||||
|
||||
#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/std/__cccl/prologue.h>
|
||||
|
||||
// NOLINTBEGIN(bugprone-reserved-identifier)
|
||||
|
||||
namespace cuda::experimental
|
||||
{
|
||||
template <class _Derived>
|
||||
struct __result_policy_base
|
||||
{
|
||||
using __derived_type _CCCL_NODEBUG_ALIAS = _Derived;
|
||||
};
|
||||
|
||||
//! @brief Result specifier requesting that only a single rank receives the result.
|
||||
//!
|
||||
//! Passed as the leading argument to a cooperative or distributed algorithm to indicate
|
||||
//! that only the rank `dest` receives the result. Every other participating rank receives
|
||||
//! either no result or an unspecified value; the precise value seen by the non-destination
|
||||
//! ranks is defined by the algorithm.
|
||||
template <class _Tp>
|
||||
struct returned_to : __result_policy_base<returned_to<_Tp>>
|
||||
{
|
||||
_CCCL_HIDE_FROM_ABI returned_to() = delete;
|
||||
|
||||
_CCCL_API constexpr explicit returned_to(_Tp __rank) noexcept
|
||||
: __rank_{__rank}
|
||||
{}
|
||||
|
||||
_Tp __rank_;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES returned_to(_Tp) -> returned_to<_Tp>;
|
||||
|
||||
struct distributed_t : __result_policy_base<distributed_t>
|
||||
{};
|
||||
|
||||
//! @brief Result specifier requesting that each rank receives a slice of the result.
|
||||
//!
|
||||
//! Passed as the leading argument to a cooperative or distributed algorithm to indicate
|
||||
//! that every participating rank receives a portion of the global result rather than the
|
||||
//! whole. For example, a distributed sort delivers to each rank a slice of the globally
|
||||
//! sorted sequence, and a distributed scan delivers to each rank its portion of the global
|
||||
//! scan.
|
||||
_CCCL_GLOBAL_CONSTANT distributed_t distributed{};
|
||||
|
||||
struct broadcasted_t : __result_policy_base<broadcasted_t>
|
||||
{};
|
||||
|
||||
//! @brief Result specifier requesting that every rank receives an identical result.
|
||||
//!
|
||||
//! Passed as the leading argument to a cooperative or distributed algorithm to indicate
|
||||
//! that all participating ranks receive the same complete result.
|
||||
//!
|
||||
//! @snippet this_block.cu broadcasted reduce
|
||||
_CCCL_GLOBAL_CONSTANT broadcasted_t broadcasted{};
|
||||
} // namespace cuda::experimental
|
||||
|
||||
// NOLINTEND(bugprone-reserved-identifier)
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CUDA_EXPERIMENTAL___UTILITY_RESULT_POLICY_CUH
|
||||
@@ -1,100 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDA Experimental in CUDA C++ Core Libraries,
|
||||
// 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) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDAX__EXPERIMENTAL_UTILITY_SCOPE_EXIT
|
||||
#define _CUDAX__EXPERIMENTAL_UTILITY_SCOPE_EXIT
|
||||
|
||||
#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/std/__type_traits/integral_constant.h>
|
||||
#include <cuda/std/__type_traits/is_callable.h>
|
||||
#include <cuda/std/__type_traits/is_nothrow_constructible.h>
|
||||
#include <cuda/std/__utility/forward.h>
|
||||
|
||||
namespace cuda::experimental
|
||||
{
|
||||
// See: https://en.cppreference.com/w/cpp/experimental/scope_exit
|
||||
template <class _Fn>
|
||||
struct scope_exit
|
||||
{
|
||||
static_assert(::cuda::std::__is_nothrow_callable_v<_Fn&>,
|
||||
"The scope_guard function must be nothrow lvalue-callable with no arguments.");
|
||||
|
||||
template <class _Fn2>
|
||||
_CCCL_HOST_DEVICE_API explicit scope_exit(_Fn2&& __fn) noexcept(::cuda::std::is_nothrow_constructible_v<_Fn, _Fn2>)
|
||||
: scope_exit(::cuda::std::forward<_Fn2>(__fn), ::cuda::std::is_nothrow_constructible<_Fn, _Fn2>{})
|
||||
{
|
||||
static_assert(::cuda::std::is_nothrow_constructible_v<_Fn, _Fn2> || ::cuda::std::is_constructible_v<_Fn, _Fn2&>,
|
||||
"The scope_guard function must be nothrow constructible from the provided callable or "
|
||||
"constructible from an lvalue reference to the provided callable.");
|
||||
}
|
||||
|
||||
scope_exit(scope_exit&&) = default;
|
||||
scope_exit& operator=(scope_exit&&) = delete;
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
_CCCL_HOST_DEVICE_API ~scope_exit()
|
||||
{
|
||||
if (__active_)
|
||||
{
|
||||
__fn_();
|
||||
}
|
||||
}
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
_CCCL_HOST_DEVICE_API void release() noexcept
|
||||
{
|
||||
__active_ = false;
|
||||
}
|
||||
|
||||
private:
|
||||
// Handle the case where _Fn is nothrow constructible from _Fn2.
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Fn2>
|
||||
_CCCL_HOST_DEVICE_API explicit scope_exit(_Fn2&& __fn, ::cuda::std::true_type) noexcept
|
||||
: __fn_(::cuda::std::forward<_Fn2>(__fn))
|
||||
{}
|
||||
|
||||
// Handle the case where _Fn is not nothrow constructible from _Fn2, but is
|
||||
// constructible from _Fn2&. In this case we need to make a copy of __fn first to ensure
|
||||
// that if the copy throws we don't end up with a partially constructed scope_exit
|
||||
// object. We do this by creating a temporary scope_exit object that holds a reference
|
||||
// to the original callable, and then releasing it if the copy succeeds.
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Fn2>
|
||||
_CCCL_HOST_DEVICE_API explicit scope_exit(_Fn2&& __fn, ::cuda::std::false_type) noexcept(false)
|
||||
: scope_exit(__fn, scope_exit<_Fn2&>(__fn))
|
||||
{}
|
||||
|
||||
_CCCL_EXEC_CHECK_DISABLE
|
||||
template <class _Fn2>
|
||||
_CCCL_HOST_DEVICE_API explicit scope_exit(_Fn2& __fn, scope_exit<_Fn2&>&& __scope) noexcept(false)
|
||||
: __fn_(__fn) // copy not move because we don't want to invalidate __scope if the copy throws
|
||||
{
|
||||
__scope.release(); // the copy succeeded, so release __scope
|
||||
}
|
||||
|
||||
_Fn __fn_;
|
||||
bool __active_{true};
|
||||
};
|
||||
|
||||
template <class _Fn>
|
||||
_CCCL_DEDUCTION_GUIDE_ATTRIBUTES scope_exit(_Fn) -> scope_exit<_Fn>;
|
||||
} // namespace cuda::experimental
|
||||
|
||||
#endif // _CUDAX__EXPERIMENTAL_UTILITY_SCOPE_EXIT
|
||||
@@ -1,367 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDA Experimental in CUDA C++ Core Libraries,
|
||||
// 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) 2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __CUDAX_EXPERIMENTAL_UTILITY_SHARED_PTR
|
||||
#define __CUDAX_EXPERIMENTAL_UTILITY_SHARED_PTR
|
||||
|
||||
#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/std/__concepts/convertible_to.h>
|
||||
#include <cuda/std/__memory/addressof.h>
|
||||
#include <cuda/std/__memory/allocator_traits.h>
|
||||
#include <cuda/std/__new/device_new.h>
|
||||
#include <cuda/std/__type_traits/is_class.h>
|
||||
#include <cuda/std/__type_traits/is_nothrow_copy_constructible.h>
|
||||
#include <cuda/std/__type_traits/is_nothrow_move_constructible.h>
|
||||
#include <cuda/std/__utility/exchange.h>
|
||||
#include <cuda/std/__utility/move.h>
|
||||
#include <cuda/std/__utility/swap.h>
|
||||
#include <cuda/std/atomic>
|
||||
|
||||
// #include <cuda/experimental/__execution/lazy.cuh>
|
||||
#include <cuda/experimental/__utility/manual_lifetime.cuh>
|
||||
#include <cuda/experimental/__utility/scope_exit.cuh>
|
||||
|
||||
#include <cuda/experimental/__execution/prologue.cuh>
|
||||
|
||||
// This file contains a simplified implementation of a shared_ptr-like type
|
||||
// for use in CUDA C++ code. It supports basic shared ownership semantics,
|
||||
// but not advanced features like weak_ptr or aliasing constructors.
|
||||
namespace cuda::experimental
|
||||
{
|
||||
template <class _Ty>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT __shared_ptr;
|
||||
|
||||
template <class _Ty, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr<_Ty> __make_shared(_Args&&... __args)
|
||||
{
|
||||
return __shared_ptr<_Ty>::__make_shared(static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
template <class _Ty, class _Alloc, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr<_Ty> __allocate_shared(const _Alloc& __alloc, _Args&&... __args)
|
||||
{
|
||||
return __shared_ptr<_Ty>::__allocate_shared(__alloc, static_cast<_Args&&>(__args)...);
|
||||
}
|
||||
|
||||
namespace __detail
|
||||
{
|
||||
struct __shared_ptr_base
|
||||
{
|
||||
struct __control_block
|
||||
{
|
||||
using __destroy_vfn_t = void(__control_block*, void*) noexcept;
|
||||
__destroy_vfn_t* __destroy_vfn_ = nullptr;
|
||||
|
||||
::cuda::std::atomic<size_t> __ref_count_{1};
|
||||
::cuda::std::atomic<size_t> __reserved_{0};
|
||||
};
|
||||
|
||||
__control_block* __cb_ptr_ = nullptr;
|
||||
};
|
||||
|
||||
template <class _Alloc, class _Value>
|
||||
using __rebind_alloc_t = typename ::cuda::std::allocator_traits<_Alloc>::template rebind_alloc<_Value>;
|
||||
} // namespace __detail
|
||||
|
||||
template <class _Ty>
|
||||
struct _CCCL_TYPE_VISIBILITY_DEFAULT _CCCL_DECLSPEC_EMPTY_BASES __shared_ptr //
|
||||
: private __detail::__shared_ptr_base
|
||||
{
|
||||
using element_type = _Ty;
|
||||
|
||||
_CCCL_HIDE_FROM_ABI __shared_ptr() noexcept = default;
|
||||
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr(::cuda::std::nullptr_t) noexcept {}
|
||||
|
||||
// move constructor
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr(__shared_ptr&& __other) noexcept
|
||||
: __detail::__shared_ptr_base{::cuda::std::exchange(__other.__cb_ptr_, nullptr)}
|
||||
, __val_ptr_{::cuda::std::exchange(__other.__val_ptr_, nullptr)}
|
||||
{}
|
||||
|
||||
// copy constructor
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr(const __shared_ptr& __other) noexcept
|
||||
: __detail::__shared_ptr_base{__other.__cb_ptr_}
|
||||
, __val_ptr_{__other.__val_ptr_}
|
||||
{
|
||||
if (__cb_ptr_)
|
||||
{
|
||||
__cb_ptr_->__ref_count_.fetch_add(1, ::cuda::std::memory_order_acq_rel);
|
||||
}
|
||||
}
|
||||
|
||||
// converting move constructor
|
||||
_CCCL_TEMPLATE(class _Other)
|
||||
_CCCL_REQUIRES(::cuda::std::convertible_to<_Other*, _Ty*>)
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr(__shared_ptr<_Other>&& __other) noexcept
|
||||
: __detail::__shared_ptr_base{::cuda::std::exchange(__other.__cb_ptr_, nullptr)}
|
||||
, __val_ptr_{::cuda::std::exchange(__other.__val_ptr_, nullptr)}
|
||||
{}
|
||||
|
||||
// converting copy constructor
|
||||
_CCCL_TEMPLATE(class _Other)
|
||||
_CCCL_REQUIRES(::cuda::std::convertible_to<_Other*, _Ty*>)
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr(const __shared_ptr<_Other>& __other) noexcept
|
||||
: __detail::__shared_ptr_base{__other.__cb_ptr_}
|
||||
, __val_ptr_{__other.__val_ptr_}
|
||||
{
|
||||
if (__cb_ptr_)
|
||||
{
|
||||
__cb_ptr_->__ref_count_.fetch_add(1, ::cuda::std::memory_order_acq_rel);
|
||||
}
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr& operator=(__shared_ptr&& __other) noexcept
|
||||
{
|
||||
__shared_ptr(_CCCL_MOVE(__other)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr& operator=(const __shared_ptr& __other) noexcept
|
||||
{
|
||||
__shared_ptr(__other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Other)
|
||||
_CCCL_REQUIRES(::cuda::std::convertible_to<_Other*, _Ty*>)
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr& operator=(__shared_ptr<_Other>&& __other) noexcept
|
||||
{
|
||||
__shared_ptr(_CCCL_MOVE(__other)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_TEMPLATE(class _Other)
|
||||
_CCCL_REQUIRES(::cuda::std::convertible_to<_Other*, _Ty*>)
|
||||
_CCCL_HOST_DEVICE_API __shared_ptr& operator=(const __shared_ptr<_Other>& __other) noexcept
|
||||
{
|
||||
__shared_ptr(__other).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API ~__shared_ptr()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API void swap(__shared_ptr& __other) noexcept
|
||||
{
|
||||
::cuda::std::swap(__cb_ptr_, __other.__cb_ptr_);
|
||||
::cuda::std::swap(__val_ptr_, __other.__val_ptr_);
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API friend void swap(__shared_ptr& __lhs, __shared_ptr& __rhs) noexcept
|
||||
{
|
||||
__lhs.swap(__rhs);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API _Ty* operator->() const noexcept
|
||||
{
|
||||
return __val_ptr_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API _Ty& operator*() const noexcept
|
||||
{
|
||||
return *__val_ptr_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API _Ty* get() const noexcept
|
||||
{
|
||||
return __val_ptr_;
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API void reset() noexcept
|
||||
{
|
||||
if (__cb_ptr_)
|
||||
{
|
||||
if (__cb_ptr_->__ref_count_.fetch_sub(1, ::cuda::std::memory_order_acq_rel) == 1)
|
||||
{
|
||||
__cb_ptr_->__destroy_vfn_(__cb_ptr_, __val_ptr_);
|
||||
}
|
||||
__cb_ptr_ = nullptr;
|
||||
__val_ptr_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API size_t use_count() const noexcept
|
||||
{
|
||||
return __cb_ptr_ ? __cb_ptr_->__ref_count_.load(::cuda::std::memory_order_acquire) : 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API explicit operator bool() const noexcept
|
||||
{
|
||||
return __cb_ptr_ != nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API bool operator!() const noexcept
|
||||
{
|
||||
return __cb_ptr_ == nullptr;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API bool operator==(const __shared_ptr& __other) const noexcept
|
||||
{
|
||||
return __cb_ptr_ == __other.__cb_ptr_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_DEVICE_API bool operator!=(const __shared_ptr& __other) const noexcept
|
||||
{
|
||||
return !(*this == __other);
|
||||
}
|
||||
|
||||
private:
|
||||
template <class>
|
||||
friend struct __shared_ptr;
|
||||
|
||||
template <class _Ty2, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API friend __shared_ptr<_Ty2> __make_shared(_Args&&...);
|
||||
|
||||
template <class _Ty2, class _Alloc, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API friend __shared_ptr<_Ty2> __allocate_shared(const _Alloc&, _Args&&...);
|
||||
|
||||
_CCCL_HOST_DEVICE_API explicit __shared_ptr(__shared_ptr_base::__control_block* __cb_ptr, _Ty* __val_ptr) noexcept
|
||||
: __detail::__shared_ptr_base{__cb_ptr}
|
||||
, __val_ptr_{__val_ptr}
|
||||
{}
|
||||
|
||||
template <class _Deleter>
|
||||
struct __deleter_wrapper
|
||||
{
|
||||
_CCCL_HOST_DEVICE_API __deleter_wrapper(_Deleter __deleter) noexcept
|
||||
: __deleter_{static_cast<_Deleter&&>(__deleter)}
|
||||
{}
|
||||
|
||||
_CCCL_HOST_DEVICE_API void operator()(_Ty* __ptr) noexcept
|
||||
{
|
||||
__deleter_(__ptr);
|
||||
}
|
||||
|
||||
_Deleter __deleter_;
|
||||
};
|
||||
|
||||
struct _CCCL_DECLSPEC_EMPTY_BASES __control_block : __shared_ptr_base::__control_block
|
||||
{
|
||||
using __destroy_vfn_t = void(__control_block*) noexcept;
|
||||
|
||||
template <class... _Args>
|
||||
_CCCL_HOST_DEVICE_API explicit __control_block(_Args&&... __args) noexcept(
|
||||
::cuda::std::is_nothrow_constructible_v<_Ty, _Args...>)
|
||||
: __shared_ptr_base::__control_block{&__control_block::__destroy}
|
||||
, __value_(static_cast<_Args&&>(__args)...)
|
||||
{}
|
||||
|
||||
_CCCL_HOST_DEVICE_API static void __destroy(__shared_ptr_base::__control_block* __cp_ptr, void*) noexcept
|
||||
{
|
||||
delete static_cast<__control_block*>(__cp_ptr);
|
||||
}
|
||||
|
||||
_Ty __value_;
|
||||
|
||||
protected:
|
||||
// control blocks must be destroyed using the __destroy_vfn_ member.
|
||||
_CCCL_HIDE_FROM_ABI ~__control_block() = default;
|
||||
};
|
||||
|
||||
template <class _Deleter, bool _IsClass = ::cuda::std::is_class_v<_Deleter>>
|
||||
struct _CCCL_DECLSPEC_EMPTY_BASES __control_block_with_deleter
|
||||
: __control_block
|
||||
, _Deleter
|
||||
{
|
||||
static_assert(::cuda::std::is_nothrow_move_constructible_v<_Deleter>, "Deleter must be nothrow movable");
|
||||
|
||||
template <class... _Args>
|
||||
_CCCL_HOST_DEVICE_API explicit __control_block_with_deleter(_Deleter __deleter, _Args&&... __args) noexcept(
|
||||
::cuda::std::is_nothrow_constructible_v<_Ty, _Args...>)
|
||||
: __control_block(static_cast<_Args&&>(__args)...)
|
||||
, _Deleter{static_cast<_Deleter&&>(__deleter)}
|
||||
{
|
||||
this->__destroy_vfn_ = &__control_block_with_deleter::__destroy;
|
||||
}
|
||||
|
||||
_CCCL_HOST_DEVICE_API static void __destroy(__shared_ptr_base::__control_block* __cb_ptr, void* __val_ptr) noexcept
|
||||
{
|
||||
_Deleter& __deleter = *static_cast<__control_block_with_deleter*>(__cb_ptr);
|
||||
__deleter(static_cast<_Ty*>(__val_ptr));
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Deleter>
|
||||
struct __control_block_with_deleter<_Deleter, false> : __control_block_with_deleter<__deleter_wrapper<_Deleter>>
|
||||
{
|
||||
using __control_block_with_deleter<__deleter_wrapper<_Deleter>>::__control_block_with_deleter;
|
||||
};
|
||||
|
||||
template <class _Alloc>
|
||||
struct _CCCL_DECLSPEC_EMPTY_BASES __allocator_deleter : _Alloc
|
||||
{
|
||||
using __control_block_t = __control_block_with_deleter<__allocator_deleter>;
|
||||
static_assert(::cuda::std::is_nothrow_copy_constructible_v<_Alloc>, "Allocator must be nothrow copyable");
|
||||
|
||||
_CCCL_HOST_DEVICE_API explicit __allocator_deleter(const _Alloc& __alloc) noexcept
|
||||
: _Alloc{__alloc}
|
||||
{}
|
||||
|
||||
_CCCL_HOST_DEVICE_API void operator()([[maybe_unused]] _Ty* __ptr) noexcept
|
||||
{
|
||||
__control_block_t* __cb_ptr = static_cast<__control_block_t*>(this);
|
||||
_CCCL_ASSERT(::cuda::std::addressof(__cb_ptr->__value_) == __ptr, "Pointer mismatch in allocator deleter");
|
||||
|
||||
using __cb_alloc_t = __detail::__rebind_alloc_t<_Alloc, __control_block_t>;
|
||||
__cb_alloc_t __cb_alloc{static_cast<_Alloc&>(*__cb_ptr)};
|
||||
|
||||
// Run the destructor for the control block and deallocate it:
|
||||
::cuda::std::allocator_traits<__cb_alloc_t>::destroy(__cb_alloc, __cb_ptr);
|
||||
::cuda::std::allocator_traits<__cb_alloc_t>::deallocate(__cb_alloc, __cb_ptr, 1);
|
||||
}
|
||||
};
|
||||
|
||||
template <class... _Args>
|
||||
_CCCL_HOST_DEVICE_API static __shared_ptr __make_shared(_Args&&... __args)
|
||||
{
|
||||
auto* __cb_ptr = ::new __control_block(static_cast<_Args&&>(__args)...);
|
||||
return __shared_ptr{__cb_ptr, ::cuda::std::addressof(__cb_ptr->__value_)};
|
||||
}
|
||||
|
||||
template <class _Alloc, class... _Args>
|
||||
_CCCL_HOST_DEVICE_API static __shared_ptr __allocate_shared(const _Alloc& __alloc, _Args&&... __args)
|
||||
{
|
||||
using __control_block_t = __control_block_with_deleter<__allocator_deleter<_Alloc>>;
|
||||
using __cb_alloc_t = __detail::__rebind_alloc_t<_Alloc, __control_block_t>;
|
||||
using __traits_t = ::cuda::std::allocator_traits<__cb_alloc_t>;
|
||||
__cb_alloc_t __cb_alloc{__alloc};
|
||||
|
||||
// allocate memory for control block
|
||||
auto* __cb_ptr = __traits_t::allocate(__cb_alloc, 1);
|
||||
|
||||
// use scope_exit to deallocate if construction throws
|
||||
scope_exit __on_exit([__cb_ptr, &__cb_alloc]() noexcept {
|
||||
__traits_t::deallocate(__cb_alloc, __cb_ptr, 1);
|
||||
});
|
||||
__traits_t::construct(__cb_alloc, __cb_ptr, __allocator_deleter<_Alloc>{__alloc}, static_cast<_Args&&>(__args)...);
|
||||
__on_exit.release();
|
||||
|
||||
return __shared_ptr{__cb_ptr, ::cuda::std::addressof(__cb_ptr->__value_)};
|
||||
}
|
||||
|
||||
_Ty* __val_ptr_ = nullptr;
|
||||
};
|
||||
} // namespace cuda::experimental
|
||||
|
||||
#include <cuda/experimental/__execution/epilogue.cuh>
|
||||
|
||||
#endif // __CUDAX_EXPERIMENTAL_UTILITY_SHARED_PTR
|
||||
@@ -1,103 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of CUDA Experimental in CUDA C++ Core Libraries,
|
||||
// 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) 2022-2025 NVIDIA CORPORATION & AFFILIATES.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _CUDAX__UTILITY_UNSTABLE_UNIQUE
|
||||
#define _CUDAX__UTILITY_UNSTABLE_UNIQUE
|
||||
|
||||
#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/std/__functional/operations.h>
|
||||
#include <cuda/std/__iterator/concepts.h>
|
||||
#include <cuda/std/__iterator/next.h>
|
||||
#include <cuda/std/__iterator/prev.h>
|
||||
#include <cuda/std/__utility/move.h>
|
||||
|
||||
namespace cuda::experimental
|
||||
{
|
||||
//! @brief Removes duplicates from a sorted range using a custom predicate.
|
||||
//!
|
||||
//! Operates from both sides of the range, moving elements from the right-hand
|
||||
//! side to the left to eliminate duplicates. The relative order of elements is
|
||||
//! not preserved. Requires a bidirectional iterator.
|
||||
//!
|
||||
//! @tparam _Iterator The type of the iterator.
|
||||
//! @tparam _BinaryPredicate The type of the predicate.
|
||||
//!
|
||||
//! @param[in] __first Iterator to the beginning of the range.
|
||||
//! @param[in] __last Iterator past the end of the range.
|
||||
//! @param[in] __pred The predicate used to compare adjacent elements.
|
||||
//!
|
||||
//! @return Iterator to the new end of the range after duplicates have been removed.
|
||||
template <class _Iterator, class _BinaryPredicate>
|
||||
_CCCL_HOST_API _Iterator unstable_unique(_Iterator __first, _Iterator __last, _BinaryPredicate __pred)
|
||||
{
|
||||
static_assert(::cuda::std::bidirectional_iterator<_Iterator>, "unstable_unique requires a bidirectional iterator");
|
||||
if (__first == __last || ::cuda::std::next(__first) == __last)
|
||||
{
|
||||
return __last;
|
||||
}
|
||||
|
||||
bool __first_is_known_duplicate = false;
|
||||
for (++__first; __first != __last; ++__first)
|
||||
{
|
||||
if (!__first_is_known_duplicate)
|
||||
{
|
||||
if (!__pred(*__first, *::cuda::std::prev(__first)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_CCCL_ASSERT(__first != __last, "unstable_unique: iterator out of range");
|
||||
for (--__last;; --__last)
|
||||
{
|
||||
if (__first == __last)
|
||||
{
|
||||
return __first;
|
||||
}
|
||||
_CCCL_ASSERT(__first != __last, "unstable_unique: iterator out of range");
|
||||
if (!__pred(*__last, *::cuda::std::prev(__last)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
_CCCL_ASSERT(!__pred(*__first, *__last), "unstable_unique: unexpected duplicate");
|
||||
__first_is_known_duplicate = __pred(*__first, *::cuda::std::next(__first));
|
||||
*__first = ::cuda::std::move(*__last);
|
||||
}
|
||||
|
||||
return __first;
|
||||
}
|
||||
|
||||
//! @brief Removes duplicates from a sorted range using `operator==`.
|
||||
//!
|
||||
//! Equivalent to calling the predicate overload with `operator==`.
|
||||
//!
|
||||
//! @tparam _Iterator The type of the iterator.
|
||||
//!
|
||||
//! @param[in] __first Iterator to the beginning of the range.
|
||||
//! @param[in] __last Iterator past the end of the range.
|
||||
//!
|
||||
//! @return Iterator to the new end of the range after duplicates have been removed.
|
||||
template <class _Iterator>
|
||||
_CCCL_HOST_API _Iterator unstable_unique(_Iterator __first, _Iterator __last)
|
||||
{
|
||||
return ::cuda::experimental::unstable_unique(__first, __last, ::cuda::std::equal_to<>{});
|
||||
}
|
||||
} // namespace cuda::experimental
|
||||
|
||||
#endif // _CUDAX__UTILITY_UNSTABLE_UNIQUE
|
||||
Reference in New Issue
Block a user