[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,318 +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 _CUDAX__CONTAINER_GRAPH_BUFFER_CUH
|
||||
#define _CUDAX__CONTAINER_GRAPH_BUFFER_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
|
||||
|
||||
#if _CCCL_CTK_AT_LEAST(12, 2)
|
||||
|
||||
# include <cuda/__memory_resource/properties.h>
|
||||
# include <cuda/__runtime/api_wrapper.h>
|
||||
# include <cuda/__stream/invalid_stream.h>
|
||||
# include <cuda/__stream/stream_ref.h>
|
||||
# include <cuda/__type_traits/is_trivially_copyable.h>
|
||||
# include <cuda/__utility/no_init.h>
|
||||
# include <cuda/std/__utility/exchange.h>
|
||||
# include <cuda/std/__utility/move.h>
|
||||
# include <cuda/std/cstddef>
|
||||
# include <cuda/std/initializer_list>
|
||||
# include <cuda/std/span>
|
||||
|
||||
# include <cuda/experimental/__graph/copy_bytes.cuh>
|
||||
# include <cuda/experimental/__graph/fill_bytes.cuh>
|
||||
# include <cuda/experimental/__graph/graph_memory_resource.cuh>
|
||||
# include <cuda/experimental/__graph/graph_node_ref.cuh>
|
||||
# include <cuda/experimental/__graph/path_builder.cuh>
|
||||
|
||||
# include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
namespace cuda::experimental
|
||||
{
|
||||
//! @rst
|
||||
//! .. _cudax-container-graph-buffer:
|
||||
//!
|
||||
//! Graph buffer
|
||||
//! ------------
|
||||
//!
|
||||
//! ``graph_buffer`` provides typed device memory allocated as a CUDA graph node.
|
||||
//! It mirrors the API of ``cuda::buffer`` but takes a ``path_builder&`` instead of
|
||||
//! a ``stream_ref``. Allocation inserts a ``cuGraphAddMemAllocNode`` into the graph.
|
||||
//!
|
||||
//! Memory can be freed in three ways:
|
||||
//! - ``destroy(path_builder&)`` — inserts a free node into the graph
|
||||
//! - ``destroy(stream_ref)`` — frees asynchronously on a stream (for memory that outlives the graph)
|
||||
//! - Destructor — frees on the stored stream if one was set via ``set_stream()``
|
||||
//!
|
||||
//! If the destructor runs with no stream set and the buffer is non-empty, it asserts
|
||||
//! in debug mode. In release mode the memory leaks.
|
||||
//!
|
||||
//! @endrst
|
||||
//! @tparam _Tp The element type stored in the buffer. Must be trivially copyable.
|
||||
template <class _Tp>
|
||||
class graph_buffer
|
||||
{
|
||||
static_assert(::cuda::is_trivially_copyable_v<_Tp>, "graph_buffer requires T to be trivially copyable.");
|
||||
|
||||
public:
|
||||
using value_type = _Tp;
|
||||
using pointer = _Tp*;
|
||||
using const_pointer = const _Tp*;
|
||||
using size_type = ::cuda::std::size_t;
|
||||
using properties_list = ::cuda::mr::properties_list<::cuda::mr::device_accessible>;
|
||||
|
||||
private:
|
||||
graph_memory_resource __mr_;
|
||||
size_type __count_ = 0;
|
||||
_Tp* __buf_ = nullptr;
|
||||
::cudaStream_t __stream_ = ::cuda::__invalid_stream();
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API pointer __get_data() const noexcept
|
||||
{
|
||||
return __buf_;
|
||||
}
|
||||
|
||||
//! @brief Causes the buffer to be treated as a span when passed to cudax::launch.
|
||||
[[nodiscard]] _CCCL_HOST_API friend auto transform_launch_argument(::cuda::stream_ref, graph_buffer& __self) noexcept
|
||||
-> ::cuda::std::span<_Tp>
|
||||
{
|
||||
return {__self.__get_data(), __self.__count_};
|
||||
}
|
||||
|
||||
//! @brief Causes the buffer to be treated as a const span when passed to cudax::launch.
|
||||
[[nodiscard]] _CCCL_HOST_API friend auto
|
||||
transform_launch_argument(::cuda::stream_ref, const graph_buffer& __self) noexcept -> ::cuda::std::span<const _Tp>
|
||||
{
|
||||
return {__self.__get_data(), __self.__count_};
|
||||
}
|
||||
|
||||
public:
|
||||
graph_buffer() = delete;
|
||||
|
||||
//! @brief Allocates uninitialized storage for \p __count elements.
|
||||
_CCCL_HOST_API graph_buffer(path_builder& __pb, graph_memory_resource __mr, size_type __count, ::cuda::no_init_t)
|
||||
: __mr_(::cuda::std::move(__mr))
|
||||
, __count_(__count)
|
||||
, __buf_(__count_ == 0 ? nullptr : static_cast<_Tp*>(__mr_.allocate(__pb, __count_ * sizeof(_Tp), alignof(_Tp))))
|
||||
{}
|
||||
|
||||
//! @brief Allocates storage and fills with \p __value.
|
||||
_CCCL_HOST_API graph_buffer(path_builder& __pb, graph_memory_resource __mr, size_type __count, const _Tp& __value)
|
||||
: __mr_(::cuda::std::move(__mr))
|
||||
, __count_(__count)
|
||||
, __buf_(__count_ == 0 ? nullptr : static_cast<_Tp*>(__mr_.allocate(__pb, __count_ * sizeof(_Tp), alignof(_Tp))))
|
||||
{
|
||||
if (__count_ > 0)
|
||||
{
|
||||
if constexpr (sizeof(_Tp) == 1)
|
||||
{
|
||||
::cuda::std::uint8_t __byte_val =
|
||||
static_cast<::cuda::std::uint8_t>(reinterpret_cast<const unsigned char&>(__value));
|
||||
::cuda::experimental::fill_bytes(__pb, ::cuda::std::span<_Tp>(__get_data(), __count_), __byte_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: support non-zero multi-byte values via a kernel node
|
||||
::cuda::experimental::fill_bytes(
|
||||
__pb, ::cuda::std::span<_Tp>(__get_data(), __count_), static_cast<::cuda::std::uint8_t>(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Allocates storage and copies from a contiguous span.
|
||||
_CCCL_HOST_API graph_buffer(path_builder& __pb, graph_memory_resource __mr, ::cuda::std::span<const _Tp> __src)
|
||||
: __mr_(::cuda::std::move(__mr))
|
||||
, __count_(__src.size())
|
||||
, __buf_(__count_ == 0 ? nullptr : static_cast<_Tp*>(__mr_.allocate(__pb, __count_ * sizeof(_Tp), alignof(_Tp))))
|
||||
{
|
||||
if (__count_ > 0)
|
||||
{
|
||||
::cuda::experimental::copy_bytes(__pb, __src, ::cuda::std::span<_Tp>{__get_data(), __count_});
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Allocates storage and copies from an initializer list.
|
||||
_CCCL_HOST_API graph_buffer(path_builder& __pb, graph_memory_resource __mr, ::cuda::std::initializer_list<_Tp> __ilist)
|
||||
: graph_buffer(__pb, ::cuda::std::move(__mr), ::cuda::std::span<const _Tp>{__ilist.begin(), __ilist.size()})
|
||||
{}
|
||||
|
||||
graph_buffer(const graph_buffer&) = delete;
|
||||
graph_buffer& operator=(const graph_buffer&) = delete;
|
||||
|
||||
//! @brief Move-constructs from another graph_buffer.
|
||||
_CCCL_HOST_API graph_buffer(graph_buffer&& __other) noexcept
|
||||
: __mr_(::cuda::std::move(__other.__mr_))
|
||||
, __count_(::cuda::std::exchange(__other.__count_, 0))
|
||||
, __buf_(::cuda::std::exchange(__other.__buf_, nullptr))
|
||||
, __stream_(::cuda::std::exchange(__other.__stream_, ::cuda::__invalid_stream()))
|
||||
{}
|
||||
|
||||
//! @brief Move-assigns from another graph_buffer.
|
||||
_CCCL_HOST_API graph_buffer& operator=(graph_buffer&& __other) noexcept
|
||||
{
|
||||
if (this != &__other)
|
||||
{
|
||||
_CCCL_ASSERT(__buf_ == nullptr || __stream_ != ::cuda::__invalid_stream(),
|
||||
"graph_buffer move-assigned over non-empty buffer with no stream set");
|
||||
if (__buf_ != nullptr && __stream_ != ::cuda::__invalid_stream())
|
||||
{
|
||||
destroy(::cuda::stream_ref{__stream_});
|
||||
}
|
||||
__mr_ = ::cuda::std::move(__other.__mr_);
|
||||
__count_ = ::cuda::std::exchange(__other.__count_, 0);
|
||||
__buf_ = ::cuda::std::exchange(__other.__buf_, nullptr);
|
||||
__stream_ = ::cuda::std::exchange(__other.__stream_, ::cuda::__invalid_stream());
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! @brief Destructor. Frees device memory on the stored stream if one was set.
|
||||
_CCCL_HOST_API ~graph_buffer()
|
||||
{
|
||||
if (__buf_ != nullptr)
|
||||
{
|
||||
_CCCL_ASSERT(__stream_ != ::cuda::__invalid_stream(),
|
||||
"graph_buffer destroyed with live memory but no stream set. "
|
||||
"Call set_stream(), destroy(stream_ref), or destroy(path_builder&) before destruction.");
|
||||
if (__stream_ != ::cuda::__invalid_stream())
|
||||
{
|
||||
destroy(::cuda::stream_ref{__stream_});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Set the stream to use for automatic cleanup in the destructor.
|
||||
_CCCL_HOST_API void set_stream(::cuda::stream_ref __stream) noexcept
|
||||
{
|
||||
__stream_ = __stream.get();
|
||||
}
|
||||
|
||||
//! @brief Returns the stream set for automatic cleanup.
|
||||
[[nodiscard]] _CCCL_HOST_API ::cuda::stream_ref stream() const noexcept
|
||||
{
|
||||
return ::cuda::stream_ref{__stream_};
|
||||
}
|
||||
|
||||
//! @brief Insert a free node into the graph to deallocate the buffer.
|
||||
_CCCL_HOST_API graph_node_ref destroy(path_builder& __pb)
|
||||
{
|
||||
if (__buf_ == nullptr)
|
||||
{
|
||||
return graph_node_ref{};
|
||||
}
|
||||
|
||||
__mr_.deallocate(__pb, __buf_, __count_ * sizeof(_Tp), alignof(_Tp));
|
||||
auto __free_node = __pb.get_dependencies()[0];
|
||||
__buf_ = nullptr;
|
||||
__count_ = 0;
|
||||
return graph_node_ref{__free_node, __pb.get_native_graph_handle()};
|
||||
}
|
||||
|
||||
//! @brief Free the buffer's device memory asynchronously on a stream.
|
||||
_CCCL_HOST_API void destroy(::cuda::stream_ref __stream)
|
||||
{
|
||||
if (__buf_ != nullptr)
|
||||
{
|
||||
__mr_.deallocate(__stream, __buf_, __count_ * sizeof(_Tp), alignof(_Tp));
|
||||
__buf_ = nullptr;
|
||||
__count_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API pointer data() noexcept
|
||||
{
|
||||
return __get_data();
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API const_pointer data() const noexcept
|
||||
{
|
||||
return __get_data();
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API pointer begin() noexcept
|
||||
{
|
||||
return __get_data();
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API const_pointer begin() const noexcept
|
||||
{
|
||||
return __get_data();
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API pointer end() noexcept
|
||||
{
|
||||
return __get_data() + __count_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API const_pointer end() const noexcept
|
||||
{
|
||||
return __get_data() + __count_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API constexpr size_type size() const noexcept
|
||||
{
|
||||
return __count_;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API constexpr size_type size_bytes() const noexcept
|
||||
{
|
||||
return __count_ * sizeof(_Tp);
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API constexpr bool empty() const noexcept
|
||||
{
|
||||
return __count_ == 0;
|
||||
}
|
||||
|
||||
[[nodiscard]] _CCCL_HOST_API const graph_memory_resource& memory_resource() const noexcept
|
||||
{
|
||||
return __mr_;
|
||||
}
|
||||
};
|
||||
|
||||
//! @brief Create a graph_buffer with uninitialized storage.
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_HOST_API graph_buffer<_Tp>
|
||||
make_buffer(path_builder& __pb, graph_memory_resource __mr, ::cuda::std::size_t __count, ::cuda::no_init_t)
|
||||
{
|
||||
return graph_buffer<_Tp>{__pb, ::cuda::std::move(__mr), __count, ::cuda::no_init};
|
||||
}
|
||||
|
||||
//! @brief Create a graph_buffer filled with a value.
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_HOST_API graph_buffer<_Tp>
|
||||
make_buffer(path_builder& __pb, graph_memory_resource __mr, ::cuda::std::size_t __count, const _Tp& __value)
|
||||
{
|
||||
return graph_buffer<_Tp>{__pb, ::cuda::std::move(__mr), __count, __value};
|
||||
}
|
||||
|
||||
//! @brief Create a graph_buffer from a span of data.
|
||||
template <class _Tp>
|
||||
[[nodiscard]] _CCCL_HOST_API graph_buffer<_Tp>
|
||||
make_buffer(path_builder& __pb, graph_memory_resource __mr, ::cuda::std::span<const _Tp> __src)
|
||||
{
|
||||
return graph_buffer<_Tp>{__pb, ::cuda::std::move(__mr), __src};
|
||||
}
|
||||
} // namespace cuda::experimental
|
||||
|
||||
# include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif // _CCCL_CTK_AT_LEAST(12, 2)
|
||||
|
||||
#endif // _CUDAX__CONTAINER_GRAPH_BUFFER_CUH
|
||||
@@ -1,292 +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__CONTAINERS_UNINITIALIZED_BUFFER_H
|
||||
#define __CUDAX__CONTAINERS_UNINITIALIZED_BUFFER_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/__memory_resource/any_resource.h>
|
||||
#include <cuda/__memory_resource/properties.h>
|
||||
#include <cuda/std/__memory/align.h>
|
||||
#include <cuda/std/__new/launder.h>
|
||||
#include <cuda/std/__type_traits/type_set.h>
|
||||
#include <cuda/std/__utility/exchange.h>
|
||||
#include <cuda/std/__utility/move.h>
|
||||
#include <cuda/std/__utility/swap.h>
|
||||
#include <cuda/std/span>
|
||||
|
||||
#include <cuda/std/__cccl/prologue.h>
|
||||
|
||||
//! @file
|
||||
//! The \c uninitialized_buffer class provides a typed buffer allocated from a given memory resource.
|
||||
namespace cuda::experimental
|
||||
{
|
||||
//! @rst
|
||||
//! .. _cudax-containers-uninitialized-buffer:
|
||||
//!
|
||||
//! Uninitialized type-safe memory storage
|
||||
//! ---------------------------------------
|
||||
//!
|
||||
//! ``uninitialized_buffer`` provides a typed buffer allocated from a given :ref:`memory resource
|
||||
//! <libcudacxx-extended-api-memory-resources-resource>`. It handles alignment and release of the allocation.
|
||||
//! The memory is uninitialized, so that a user needs to ensure elements are properly constructed.
|
||||
//!
|
||||
//! In addition to being type-safe, ``uninitialized_buffer`` also takes a set of :ref:`properties
|
||||
//! <libcudacxx-extended-api-memory-resources-properties>` to ensure that e.g. execution space constraints are checked
|
||||
//! at compile time. However, we can only forward stateless properties. If a user wants to use a stateful one, then they
|
||||
//! need to implement :ref:`get_property(const device_buffer&, Property)
|
||||
//! <libcudacxx-extended-api-memory-resources-properties>`.
|
||||
//!
|
||||
//! @endrst
|
||||
//! @tparam _Tp the type to be stored in the buffer
|
||||
//! @tparam _Properties... The properties the allocated memory satisfies
|
||||
template <class _Tp, class... _Properties>
|
||||
class uninitialized_buffer
|
||||
{
|
||||
private:
|
||||
static_assert(::cuda::mr::__contains_execution_space_property<_Properties...>,
|
||||
"The properties of cuda::experimental::uninitialized_buffer must contain at least one execution space "
|
||||
"property!");
|
||||
|
||||
using __resource = ::cuda::mr::any_synchronous_resource<_Properties...>;
|
||||
|
||||
__resource __mr_;
|
||||
size_t __count_ = 0;
|
||||
void* __buf_ = nullptr;
|
||||
|
||||
template <class, class...>
|
||||
friend class uninitialized_buffer;
|
||||
|
||||
//! @brief Helper to check whether a different buffer still satisfies all properties of this one
|
||||
template <class... _OtherProperties>
|
||||
static constexpr bool __properties_match =
|
||||
!::cuda::std::is_same_v<::cuda::std::__make_type_set<_Properties...>,
|
||||
::cuda::std::__make_type_set<_OtherProperties...>>
|
||||
&& ::cuda::std::__type_set_contains_v<::cuda::std::__make_type_set<_OtherProperties...>, _Properties...>;
|
||||
|
||||
//! @brief Determines the allocation size given the alignment and size of `T`
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI static constexpr size_t __get_allocation_size(const size_t __count) noexcept
|
||||
{
|
||||
constexpr size_t __alignment = alignof(_Tp);
|
||||
return (__count * sizeof(_Tp) + (__alignment - 1)) & ~(__alignment - 1);
|
||||
}
|
||||
|
||||
//! @brief Determines the properly aligned start of the buffer given the alignment and size of `T`
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI _Tp* __get_data() const noexcept
|
||||
{
|
||||
constexpr size_t __alignment = alignof(_Tp);
|
||||
size_t __space = __get_allocation_size(__count_);
|
||||
void* __ptr = __buf_;
|
||||
return ::cuda::std::launder(
|
||||
static_cast<_Tp*>(::cuda::std::align(__alignment, __count_ * sizeof(_Tp), __ptr, __space)));
|
||||
}
|
||||
|
||||
//! @brief Causes the buffer to be treated as a span when passed to cudax::launch.
|
||||
//! @pre The buffer must have the cuda::mr::device_accessible property.
|
||||
template <class _Tp2 = _Tp>
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI friend auto
|
||||
transform_launch_argument(::cuda::stream_ref, uninitialized_buffer& __self) noexcept
|
||||
_CCCL_TRAILING_REQUIRES(::cuda::std::span<_Tp>)(
|
||||
::cuda::std::same_as<_Tp, _Tp2>&& ::cuda::std::__is_included_in_v<::cuda::mr::device_accessible, _Properties...>)
|
||||
{
|
||||
return {__self.__get_data(), __self.size()};
|
||||
}
|
||||
|
||||
//! @brief Causes the buffer to be treated as a span when passed to cudax::launch
|
||||
//! @pre The buffer must have the cuda::mr::device_accessible property.
|
||||
template <class _Tp2 = _Tp>
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI friend auto
|
||||
transform_launch_argument(::cuda::stream_ref, const uninitialized_buffer& __self) noexcept
|
||||
_CCCL_TRAILING_REQUIRES(::cuda::std::span<const _Tp>)(
|
||||
::cuda::std::same_as<_Tp, _Tp2>&& ::cuda::std::__is_included_in_v<::cuda::mr::device_accessible, _Properties...>)
|
||||
{
|
||||
return {__self.__get_data(), __self.size()};
|
||||
}
|
||||
|
||||
public:
|
||||
using value_type = _Tp;
|
||||
using reference = _Tp&;
|
||||
using const_reference = const _Tp&;
|
||||
using pointer = _Tp*;
|
||||
using const_pointer = const _Tp*;
|
||||
using size_type = size_t;
|
||||
|
||||
//! @brief Constructs an \c uninitialized_buffer and allocates sufficient storage for \p __count elements through
|
||||
//! \p __mr
|
||||
//! @param __mr The memory resource to allocate the buffer with.
|
||||
//! @param __count The desired size of the buffer.
|
||||
//! @note Depending on the alignment requirements of `T` the size of the underlying allocation might be larger
|
||||
//! than `count * sizeof(T)`.
|
||||
//! @note Only allocates memory when \p __count > 0
|
||||
_CCCL_HIDE_FROM_ABI uninitialized_buffer(__resource __mr, const size_t __count)
|
||||
: __mr_(::cuda::std::move(__mr))
|
||||
, __count_(__count)
|
||||
, __buf_(__count_ == 0 ? nullptr : __mr_.allocate_sync(__get_allocation_size(__count_), alignof(_Tp)))
|
||||
{}
|
||||
|
||||
_CCCL_HIDE_FROM_ABI uninitialized_buffer(const uninitialized_buffer&) = delete;
|
||||
_CCCL_HIDE_FROM_ABI uninitialized_buffer& operator=(const uninitialized_buffer&) = delete;
|
||||
|
||||
//! @brief Move-constructs a \c uninitialized_buffer from \p __other
|
||||
//! @param __other Another \c uninitialized_buffer
|
||||
//! Takes ownership of the allocation in \p __other and resets it
|
||||
_CCCL_HIDE_FROM_ABI uninitialized_buffer(uninitialized_buffer&& __other) noexcept
|
||||
: __mr_(::cuda::std::move(__other.__mr_))
|
||||
, __count_(::cuda::std::exchange(__other.__count_, 0))
|
||||
, __buf_(::cuda::std::exchange(__other.__buf_, nullptr))
|
||||
{}
|
||||
|
||||
//! @brief Move-constructs a \c uninitialized_buffer from another \c uninitialized_buffer with matching properties
|
||||
//! @param __other Another \c uninitialized_buffer
|
||||
//! Takes ownership of the allocation in \p __other and resets it
|
||||
_CCCL_TEMPLATE(class... _OtherProperties)
|
||||
_CCCL_REQUIRES(__properties_match<_OtherProperties...>)
|
||||
_CCCL_HIDE_FROM_ABI uninitialized_buffer(uninitialized_buffer<_Tp, _OtherProperties...>&& __other) noexcept
|
||||
: __mr_(::cuda::std::move(__other.__mr_))
|
||||
, __count_(::cuda::std::exchange(__other.__count_, 0))
|
||||
, __buf_(::cuda::std::exchange(__other.__buf_, nullptr))
|
||||
{}
|
||||
|
||||
//! @brief Move-assigns a \c uninitialized_buffer from \p __other
|
||||
//! @param __other Another \c uninitialized_buffer
|
||||
//! Deallocates the current allocation and then takes ownership of the allocation in \p __other and resets it
|
||||
_CCCL_HIDE_FROM_ABI uninitialized_buffer& operator=(uninitialized_buffer&& __other) noexcept
|
||||
{
|
||||
if (this == ::cuda::std::addressof(__other))
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (__buf_)
|
||||
{
|
||||
__mr_.deallocate_sync(__buf_, __get_allocation_size(__count_), alignof(_Tp));
|
||||
}
|
||||
|
||||
__mr_ = ::cuda::std::move(__other.__mr_);
|
||||
__count_ = ::cuda::std::exchange(__other.__count_, 0);
|
||||
__buf_ = ::cuda::std::exchange(__other.__buf_, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! @brief Destroys an \c uninitialized_buffer, deallocates the buffer and destroys the memory resource
|
||||
//! @warning destroy does not destroy any objects that may or may not reside within the buffer. It is the
|
||||
//! user's responsibility to ensure that all objects within the buffer have been properly destroyed.
|
||||
_CCCL_HIDE_FROM_ABI void destroy()
|
||||
{
|
||||
if (__buf_)
|
||||
{
|
||||
__mr_.deallocate_sync(__buf_, __get_allocation_size(__count_), alignof(_Tp));
|
||||
__buf_ = nullptr;
|
||||
__count_ = 0;
|
||||
}
|
||||
auto __tmp_mr = ::cuda::std::move(__mr_);
|
||||
}
|
||||
|
||||
//! @brief Destroys an \c uninitialized_buffer, deallocates the buffer and destroys the memory resource
|
||||
//! @warning The destructor does not destroy any objects that may or may not reside within the buffer. It is the
|
||||
//! user's responsibility to ensure that all objects within the buffer have been properly destroyed.
|
||||
_CCCL_HIDE_FROM_ABI ~uninitialized_buffer()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
//! @brief Returns an aligned pointer to the first element in the buffer
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI pointer begin() noexcept
|
||||
{
|
||||
return __get_data();
|
||||
}
|
||||
|
||||
//! @overload
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI const_pointer begin() const noexcept
|
||||
{
|
||||
return __get_data();
|
||||
}
|
||||
|
||||
//! @brief Returns an aligned pointer to the element following the last element of the buffer.
|
||||
//! This element acts as a placeholder; attempting to access it results in undefined behavior.
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI pointer end() noexcept
|
||||
{
|
||||
return __get_data() + __count_;
|
||||
}
|
||||
|
||||
//! @overload
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI const_pointer end() const noexcept
|
||||
{
|
||||
return __get_data() + __count_;
|
||||
}
|
||||
|
||||
//! @brief Returns an aligned pointer to the first element in the buffer
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI pointer data() noexcept
|
||||
{
|
||||
return __get_data();
|
||||
}
|
||||
|
||||
//! @overload
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI const_pointer data() const noexcept
|
||||
{
|
||||
return __get_data();
|
||||
}
|
||||
|
||||
//! @brief Returns the size of the allocation
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI constexpr size_type size() const noexcept
|
||||
{
|
||||
return __count_;
|
||||
}
|
||||
|
||||
//! @brief Returns the size of the buffer in bytes
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept
|
||||
{
|
||||
return __count_ * sizeof(_Tp);
|
||||
}
|
||||
|
||||
//! @rst
|
||||
//! Returns a \c const reference to the :ref:`any_resource <libcudacxx-memory-resource-any-resource>`
|
||||
//! that holds the memory resource used to allocate the buffer
|
||||
//! @endrst
|
||||
[[nodiscard]] _CCCL_HIDE_FROM_ABI const __resource& memory_resource() const noexcept
|
||||
{
|
||||
return __mr_;
|
||||
}
|
||||
|
||||
//! @brief Forwards the passed Properties
|
||||
_CCCL_TEMPLATE(class _Property)
|
||||
_CCCL_REQUIRES((!property_with_value<_Property>) _CCCL_AND ::cuda::std::__is_included_in_v<_Property, _Properties...>)
|
||||
_CCCL_HIDE_FROM_ABI friend constexpr void get_property(const uninitialized_buffer&, _Property) noexcept {}
|
||||
|
||||
//! @brief Internal method to grow the allocation to a new size \p __count.
|
||||
//! @param __count The new size of the allocation.
|
||||
//! @return An \c uninitialized_buffer that holds the previous allocation
|
||||
//! @warning This buffer must outlive the returned buffer
|
||||
_CCCL_HIDE_FROM_ABI uninitialized_buffer __replace_allocation(const size_t __count)
|
||||
{
|
||||
// Create a new buffer with a reference to the stored memory resource and swap allocation information
|
||||
uninitialized_buffer __ret{::cuda::mr::synchronous_resource_ref<_Properties...>{__mr_}, __count};
|
||||
::cuda::std::swap(__count_, __ret.__count_);
|
||||
::cuda::std::swap(__buf_, __ret.__buf_);
|
||||
return __ret;
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
using uninitialized_device_buffer = uninitialized_buffer<_Tp, ::cuda::mr::device_accessible>;
|
||||
} // namespace cuda::experimental
|
||||
|
||||
#include <cuda/std/__cccl/epilogue.h>
|
||||
|
||||
#endif //__CUDAX__CONTAINERS_UNINITIALIZED_BUFFER_H
|
||||
Reference in New Issue
Block a user