[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
This commit is contained in:
EngineX CI
2026-07-30 09:35:51 +00:00
parent b4d01f481e
commit 56fd68e7dd
8871 changed files with 1454674 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,439 @@
//===----------------------------------------------------------------------===//
//
// 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_HETEROGENEOUS_ITERATOR_CUH
#define __CUDAX__CONTAINERS_HETEROGENEOUS_ITERATOR_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_HAS_CTK()
# include <cuda/__memory_resource/properties.h>
# include <cuda/std/__iterator/iterator_traits.h>
# include <cuda/std/__memory/addressof.h>
# include <cuda/std/__memory/pointer_traits.h>
# include <cuda/std/__type_traits/is_const.h>
# include <cuda/std/__type_traits/is_same.h>
# include <cuda/std/__type_traits/maybe_const.h>
# include <cuda/std/__type_traits/remove_const.h>
# include <cuda/std/cstdint>
# include <cuda/std/__cccl/prologue.h>
//! @file
//! @brief The \c heterogeneous_iterator class is an iterator that provides typed execution space safety.
_CCCL_BEGIN_NAMESPACE_CUDA
enum class __is_heterogeneous_const_iter
{
__no,
__yes,
};
//! @rst
//! .. _libcudacxx-containers-heterogeneous-iterator:
//!
//! Type safe iterator over heterogeneous memory
//! ---------------------------------------------
//!
//! ``heterogeneous_iterator`` provides a type safe access over heterogeneous memory. Depending on whether the memory is
//! tagged as host-accessible and / or device-accessible the iterator restricts memory access.
//! All operations that do not require memory access are always available on host and device.
//!
//! @endrst
//! @tparam _Tp The underlying type of the elements the \c heterogeneous_iterator points at.
//! @tparam _IsConst Enumeration choosing whether the \c heterogeneous_iterator allows mutating the element pointed to.
//! @tparam _Properties The properties that the \c heterogeneous_iterator is tagged with.
template <class _CvTp, class... _Properties>
class heterogeneous_iterator;
// We restrict all accessors of the iterator based on the execution space
template <class _Tp, __is_heterogeneous_const_iter _IsConst, ::cuda::mr::__memory_accessibility _Space>
class __heterogeneous_iterator_access;
template <class _Tp, __is_heterogeneous_const_iter _IsConst>
class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessibility ::__host>
{
public:
using iterator_concept = ::cuda::std::contiguous_iterator_tag;
using iterator_category = ::cuda::std::random_access_iterator_tag;
using value_type = _Tp;
using difference_type = ::cuda::std::ptrdiff_t;
using pointer = ::cuda::std::__maybe_const<_IsConst == __is_heterogeneous_const_iter::__yes, _Tp>*;
using reference = ::cuda::std::__maybe_const<_IsConst == __is_heterogeneous_const_iter::__yes, _Tp>&;
_CCCL_HIDE_FROM_ABI __heterogeneous_iterator_access() = default;
_CCCL_API explicit constexpr __heterogeneous_iterator_access(pointer __ptr) noexcept
: __ptr_(__ptr)
{}
//! @brief Dereference a \c heterogeneous_iterator
//! @return A reference to the element the iterator points to
[[nodiscard]] _CCCL_HOST_API constexpr reference operator*() const noexcept
{
return *__ptr_;
}
//! @brief Operator arrow on a \c heterogeneous_iterator
//! @return A pointer to the element the iterator points to
[[nodiscard]] _CCCL_HOST_API constexpr pointer operator->() const noexcept
{
return __ptr_;
}
//! @brief Dereference a \c heterogeneous_iterator
//! @param __count The offset at which we want to dereference
//! @return A reference of the \p __count th element after the one the iterator points to
[[nodiscard]] _CCCL_HOST_API constexpr reference operator[](const difference_type __count) const noexcept
{
return *(__ptr_ + __count);
}
protected:
pointer __ptr_ = nullptr;
template <class, class...>
friend class heterogeneous_iterator;
};
template <class _Tp, __is_heterogeneous_const_iter _IsConst>
class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessibility ::__device>
{
public:
using iterator_concept = ::cuda::std::contiguous_iterator_tag;
using iterator_category = ::cuda::std::random_access_iterator_tag;
using value_type = _Tp;
using difference_type = ::cuda::std::ptrdiff_t;
using pointer = ::cuda::std::__maybe_const<_IsConst == __is_heterogeneous_const_iter::__yes, _Tp>*;
using reference = ::cuda::std::__maybe_const<_IsConst == __is_heterogeneous_const_iter::__yes, _Tp>&;
_CCCL_HIDE_FROM_ABI __heterogeneous_iterator_access() = default;
_CCCL_API explicit constexpr __heterogeneous_iterator_access(pointer __ptr) noexcept
: __ptr_(__ptr)
{}
//! @brief Dereference a \c heterogeneous_iterator
//! @return A reference to the element the iterator points to
[[nodiscard]] _CCCL_DEVICE_API constexpr reference operator*() const noexcept
{
return *__ptr_;
}
//! @brief Operator arrow on a \c heterogeneous_iterator
//! @return A pointer to the element the iterator points to
[[nodiscard]] _CCCL_DEVICE_API constexpr pointer operator->() const noexcept
{
return __ptr_;
}
//! @brief Dereference a \c heterogeneous_iterator
//! @param __count The offset at which we want to dereference
//! @return A reference of the \p __count th element after the one the iterator points to
[[nodiscard]] _CCCL_DEVICE_API constexpr reference operator[](const difference_type __count) const noexcept
{
return *(__ptr_ + __count);
}
protected:
pointer __ptr_ = nullptr;
template <class, class...>
friend class heterogeneous_iterator;
};
template <class _Tp, __is_heterogeneous_const_iter _IsConst>
class __heterogeneous_iterator_access<_Tp, _IsConst, ::cuda::mr::__memory_accessibility ::__host_device>
{
public:
using iterator_concept = ::cuda::std::contiguous_iterator_tag;
using iterator_category = ::cuda::std::random_access_iterator_tag;
using value_type = _Tp;
using difference_type = ::cuda::std::ptrdiff_t;
using pointer = ::cuda::std::__maybe_const<_IsConst == __is_heterogeneous_const_iter::__yes, _Tp>*;
using reference = ::cuda::std::__maybe_const<_IsConst == __is_heterogeneous_const_iter::__yes, _Tp>&;
_CCCL_HIDE_FROM_ABI __heterogeneous_iterator_access() = default;
_CCCL_API explicit constexpr __heterogeneous_iterator_access(pointer __ptr) noexcept
: __ptr_(__ptr)
{}
//! @brief Dereference a \c heterogeneous_iterator
//! @return A reference to the element the iterator points to
[[nodiscard]] _CCCL_API constexpr reference operator*() const noexcept
{
return *__ptr_;
}
//! @brief Operator arrow on a \c heterogeneous_iterator
//! @return A pointer to the element the iterator points to
[[nodiscard]] _CCCL_API constexpr pointer operator->() const noexcept
{
return __ptr_;
}
//! @brief Dereference a \c heterogeneous_iterator
//! @param __count The offset at which we want to dereference
//! @return A reference to the `__count` element after the one the iterator points to
[[nodiscard]] _CCCL_API constexpr reference operator[](const difference_type __count) const noexcept
{
return *(__ptr_ + __count);
}
protected:
pointer __ptr_ = nullptr;
template <class, class...>
friend class heterogeneous_iterator;
};
template <class _CvTp, class... _Properties>
class heterogeneous_iterator
: public __heterogeneous_iterator_access<
::cuda::std::remove_const_t<_CvTp>,
::cuda::std::is_const_v<_CvTp> ? __is_heterogeneous_const_iter::__yes : __is_heterogeneous_const_iter::__no,
::cuda::mr::__memory_accessibility_from_properties<_Properties...>::value>
{
using __base = __heterogeneous_iterator_access<
::cuda::std::remove_const_t<_CvTp>,
::cuda::std::is_const_v<_CvTp> ? __is_heterogeneous_const_iter::__yes : __is_heterogeneous_const_iter::__no,
::cuda::mr::__memory_accessibility_from_properties<_Properties...>::value>;
public:
using iterator_concept = ::cuda::std::contiguous_iterator_tag;
using iterator_category = ::cuda::std::random_access_iterator_tag;
using value_type = ::cuda::std::remove_const_t<_CvTp>;
using difference_type = ::cuda::std::ptrdiff_t;
using pointer = _CvTp*;
using reference = _CvTp&;
_CCCL_HIDE_FROM_ABI heterogeneous_iterator() = default;
//! @brief Construct a \c heterogeneous_iterator from a pointer to the underlying memory
_CCCL_API constexpr heterogeneous_iterator(pointer __ptr) noexcept
: __base(__ptr)
{}
//! @brief Constructs an immutable \c heterogeneous_iterator from a mutable one
//! @param __other The mutable \c heterogeneous_iterator
_CCCL_TEMPLATE(class _OtherTp, class _CvTp2 = _CvTp)
_CCCL_REQUIRES((::cuda::std::is_same_v<_OtherTp, value_type>) _CCCL_AND(::cuda::std::is_const_v<_CvTp2>))
_CCCL_API constexpr heterogeneous_iterator(heterogeneous_iterator<_OtherTp, _Properties...> __other) noexcept
: __base(__other.__ptr_)
{}
//! @brief Increment of a \c heterogeneous_iterator
//! @return The heterogeneous_iterator pointing to the next element
_CCCL_API constexpr heterogeneous_iterator& operator++() noexcept
{
++this->__ptr_;
return *this;
}
//! @brief Post-increment of a \c heterogeneous_iterator
//! @return A copy of the heterogeneous_iterator pointing to the next element
_CCCL_API constexpr heterogeneous_iterator operator++(int) noexcept
{
heterogeneous_iterator __temp = *this;
++this->__ptr_;
return __temp;
}
//! @brief Decrement of a \c heterogeneous_iterator
//! @return The heterogeneous_iterator pointing to the previous element
_CCCL_API constexpr heterogeneous_iterator& operator--() noexcept
{
--this->__ptr_;
return *this;
}
//! @brief Post-decrement of a \c heterogeneous_iterator
//! @return A copy of the heterogeneous_iterator pointing to the previous element
_CCCL_API constexpr heterogeneous_iterator operator--(int) noexcept
{
heterogeneous_iterator __temp = *this;
--this->__ptr_;
return __temp;
}
//! @brief Advance a \c heterogeneous_iterator
//! @param __count The number of elements to advance.
//! @return The heterogeneous_iterator advanced by \p __count
_CCCL_API constexpr heterogeneous_iterator& operator+=(const difference_type __count) noexcept
{
this->__ptr_ += __count;
return *this;
}
//! @brief Advance a \c heterogeneous_iterator
//! @param __count The number of elements to advance.
//! @return A copy of this heterogeneous_iterator advanced by \p __count
[[nodiscard]] _CCCL_API constexpr heterogeneous_iterator operator+(const difference_type __count) const noexcept
{
heterogeneous_iterator __temp = *this;
__temp += __count;
return __temp;
}
# ifndef _CCCL_DOXYGEN_INVOKED // Do not document
//! @brief Advance a \c heterogeneous_iterator
//! @param __count The number of elements to advance.
//! @param __other A heterogeneous_iterator.
//! @return \p __other advanced by \p __count
[[nodiscard]] _CCCL_API friend constexpr heterogeneous_iterator
operator+(const difference_type __count, heterogeneous_iterator __other) noexcept
{
__other += __count;
return __other;
}
# endif // _CCCL_DOXYGEN_INVOKED
//! @brief Advance a \c heterogeneous_iterator by the negative value of \p __count
//! @param __count The number of elements to advance.
//! @return The heterogeneous_iterator advanced by the negative value of \p __count
_CCCL_API constexpr heterogeneous_iterator& operator-=(const difference_type __count) noexcept
{
this->__ptr_ -= __count;
return *this;
}
//! @brief Advance a \c heterogeneous_iterator by the negative value of \p __count
//! @param __count The number of elements to advance.
//! @return A copy of this heterogeneous_iterator advanced by the negative value of \p __count
[[nodiscard]] _CCCL_API constexpr heterogeneous_iterator operator-(const difference_type __count) const noexcept
{
heterogeneous_iterator __temp = *this;
__temp -= __count;
return __temp;
}
//! @brief Distance between two heterogeneous_iterator
//! @param __other The other heterogeneous_iterator.
//! @return The distance between the two elements the heterogeneous_iterator point to
[[nodiscard]] _CCCL_API constexpr difference_type operator-(const heterogeneous_iterator& __other) const noexcept
{
return static_cast<difference_type>(this->__ptr_ - __other.__ptr_);
}
# ifndef _CCCL_DOXYGEN_INVOKED // Do not document
//! @brief Equality comparison between two heterogeneous_iterator
//! @param __lhs A heterogeneous_iterator.
//! @param __rhs Another heterogeneous_iterator.
//! @return true, if both heterogeneous_iterator point to the same element
[[nodiscard]] _CCCL_API friend constexpr bool
operator==(const heterogeneous_iterator& __lhs, const heterogeneous_iterator& __rhs) noexcept
{
return __lhs.__ptr_ == __rhs.__ptr_;
}
# if _CCCL_STD_VER <= 2017
//! @brief Inequality comparison between two heterogeneous_iterator
//! @param __lhs A heterogeneous_iterator.
//! @param __rhs Another heterogeneous_iterator.
//! @return false, if both heterogeneous_iterator point to the same element
[[nodiscard]] _CCCL_API friend constexpr bool
operator!=(const heterogeneous_iterator& __lhs, const heterogeneous_iterator& __rhs) noexcept
{
return __lhs.__ptr_ != __rhs.__ptr_;
}
# endif // _CCCL_STD_VER <= 2017
# if _LIBCUDACXX_HAS_SPACESHIP_OPERATOR()
[[nodiscard]] _CCCL_API friend constexpr ::cuda::std::strong_ordering
operator<=>(const heterogeneous_iterator& __lhs, const heterogeneous_iterator& __rhs) noexcept
{
return __lhs.__ptr_ <=> __rhs.__ptr_;
}
# else // ^^^ _LIBCUDACXX_HAS_SPACESHIP_OPERATOR() ^^^ / vvv !_LIBCUDACXX_HAS_SPACESHIP_OPERATOR() vvv
//! @brief Less than relation between two heterogeneous_iterator
//! @param __lhs A heterogeneous_iterator.
//! @param __rhs Another heterogeneous_iterator.
//! @return true, if the address of the element pointed to by \p __lhs is less then the address of the one pointed to
//! by \p __rhs
[[nodiscard]] _CCCL_API friend constexpr bool
operator<(const heterogeneous_iterator& __lhs, const heterogeneous_iterator& __rhs) noexcept
{
return __lhs.__ptr_ < __rhs.__ptr_;
}
//! @brief Less equal relation between two heterogeneous_iterator
//! @param __lhs A heterogeneous_iterator.
//! @param __rhs Another heterogeneous_iterator.
//! @return true, if the address of the element pointed to by \p __lhs is less then or equal to the address of the one
//! pointed to by \p __rhs
[[nodiscard]] _CCCL_API friend constexpr bool
operator<=(const heterogeneous_iterator& __lhs, const heterogeneous_iterator& __rhs) noexcept
{
return __lhs.__ptr_ <= __rhs.__ptr_;
}
//! @brief Greater then relation between two heterogeneous_iterator
//! @param __lhs A heterogeneous_iterator.
//! @param __rhs Another heterogeneous_iterator.
//! @return true, if the address of the element pointed to by \p __lhs is greater then the address of the one
//! pointed to by \p __rhs
[[nodiscard]] _CCCL_API friend constexpr bool
operator>(const heterogeneous_iterator& __lhs, const heterogeneous_iterator& __rhs) noexcept
{
return __lhs.__ptr_ > __rhs.__ptr_;
}
//! @brief Greater equal relation between two heterogeneous_iterator
//! @param __lhs A heterogeneous_iterator.
//! @param __rhs Another heterogeneous_iterator.
//! @return true, if the address of the element pointed to by \p __lhs is greater then or equal to the address of the
//! one pointed to by \p __rhs
[[nodiscard]] _CCCL_API friend constexpr bool
operator>=(const heterogeneous_iterator& __lhs, const heterogeneous_iterator& __rhs) noexcept
{
return __lhs.__ptr_ >= __rhs.__ptr_;
}
# endif // !_LIBCUDACXX_HAS_SPACESHIP_OPERATOR()
# endif // _CCCL_DOXYGEN_INVOKED
_CCCL_API constexpr pointer __unwrap() const noexcept
{
return this->__ptr_;
}
};
_CCCL_END_NAMESPACE_CUDA
_CCCL_BEGIN_NAMESPACE_CUDA_STD
// Here be dragons: We need to ensure that the iterator can work with legacy interfaces that take a pointer.
// This will obviously eat all of our execution checks
template <class _Tp, class... _Properties>
struct pointer_traits<::cuda::heterogeneous_iterator<_Tp, _Properties...>>
{
using pointer = ::cuda::heterogeneous_iterator<_Tp, _Properties...>;
using element_type = _Tp;
using difference_type = ::cuda::std::ptrdiff_t;
//! @brief Retrieve the address of the element pointed at by an heterogeneous_iterator
//! @param __iter A heterogeneous_iterator.
//! @return A pointer to the element pointed to by the heterogeneous_iterator
[[nodiscard]] _CCCL_API static constexpr element_type* to_address(const pointer __iter) noexcept
{
return ::cuda::std::to_address(__iter.__unwrap());
}
};
_CCCL_END_NAMESPACE_CUDA_STD
# include <cuda/std/__cccl/epilogue.h>
#endif // _CCCL_HAS_CTK()
#endif //__CUDAX__CONTAINERS_HETEROGENEOUS_ITERATOR_CUH

View File

@@ -0,0 +1,127 @@
//===----------------------------------------------------------------------===//
//
// 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___CONTAINER_MAKE_BUFFER_WITH_POOL_H
#define _CUDA___CONTAINER_MAKE_BUFFER_WITH_POOL_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
#if _CCCL_HAS_CTK()
# include <cuda/__container/buffer.h>
# include <cuda/__memory_pool/device_memory_pool.h>
# if _CCCL_CTK_AT_LEAST(12, 9)
# include <cuda/__memory_pool/pinned_memory_pool.h>
# endif // _CCCL_CTK_AT_LEAST(12, 9)
# if _CCCL_CTK_AT_LEAST(13, 0)
# include <cuda/__memory_pool/managed_memory_pool.h>
# endif // _CCCL_CTK_AT_LEAST(13, 0)
# include <cuda/std/__execution/env.h>
# include <cuda/std/__utility/forward.h>
# include <cuda/std/initializer_list>
# include <cuda/std/__cccl/prologue.h>
_CCCL_BEGIN_NAMESPACE_CUDA
//! @brief Creates a buffer backed by the default device memory pool.
//! @param __stream The stream used for allocation.
//! @param __device The device whose default memory pool will be used.
//! @param __args Remaining arguments forwarded to `make_buffer`.
//! @see make_buffer for the full set of supported argument combinations.
template <class _Tp, class... _Args>
_CCCL_HOST_API auto make_device_buffer(stream_ref __stream, device_ref __device, _Args&&... __args)
{
return ::cuda::make_buffer<_Tp>(
__stream, ::cuda::device_default_memory_pool(__device), ::cuda::std::forward<_Args>(__args)...);
}
//! @brief Creates a buffer backed by the default device memory pool from an initializer_list.
//! @param __stream The stream used for allocation.
//! @param __device The device whose default memory pool will be used.
//! @param __ilist The initializer_list being copied into the buffer.
//! @param __env The environment providing additional configuration.
template <class _Tp, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto make_device_buffer(
stream_ref __stream, device_ref __device, ::cuda::std::initializer_list<_Tp> __ilist, const _Env& __env = {})
{
return ::cuda::make_buffer<_Tp>(__stream, ::cuda::device_default_memory_pool(__device), __ilist, __env);
}
# if _CCCL_CTK_AT_LEAST(12, 9)
//! @brief Creates a buffer backed by the default pinned memory pool.
//! @param __stream The stream used for allocation.
//! @param __args Remaining arguments forwarded to `make_buffer`.
//! @see make_buffer for the full set of supported argument combinations.
template <class _Tp, class... _Args>
_CCCL_HOST_API auto make_pinned_buffer(stream_ref __stream, _Args&&... __args)
{
return ::cuda::make_buffer<_Tp>(
__stream, ::cuda::pinned_default_memory_pool(), ::cuda::std::forward<_Args>(__args)...);
}
//! @brief Creates a buffer backed by the default pinned memory pool from an initializer_list.
//! @param __stream The stream used for allocation.
//! @param __ilist The initializer_list being copied into the buffer.
//! @param __env The environment providing additional configuration.
template <class _Tp, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto
make_pinned_buffer(stream_ref __stream, ::cuda::std::initializer_list<_Tp> __ilist, const _Env& __env = {})
{
return ::cuda::make_buffer<_Tp>(__stream, ::cuda::pinned_default_memory_pool(), __ilist, __env);
}
# endif // _CCCL_CTK_AT_LEAST(12, 9)
# if _CCCL_CTK_AT_LEAST(13, 0)
//! @brief Creates a buffer backed by the default managed memory pool.
//! @param __stream The stream used for allocation.
//! @param __args Remaining arguments forwarded to `make_buffer`.
//! @see make_buffer for the full set of supported argument combinations.
template <class _Tp, class... _Args>
_CCCL_HOST_API auto make_managed_buffer(stream_ref __stream, _Args&&... __args)
{
return ::cuda::make_buffer<_Tp>(
__stream, ::cuda::managed_default_memory_pool(), ::cuda::std::forward<_Args>(__args)...);
}
//! @brief Creates a buffer backed by the default managed memory pool from an initializer_list.
//! @param __stream The stream used for allocation.
//! @param __ilist The initializer_list being copied into the buffer.
//! @param __env The environment providing additional configuration.
template <class _Tp, class _Env = ::cuda::std::execution::env<>>
_CCCL_HOST_API auto
make_managed_buffer(stream_ref __stream, ::cuda::std::initializer_list<_Tp> __ilist, const _Env& __env = {})
{
return ::cuda::make_buffer<_Tp>(__stream, ::cuda::managed_default_memory_pool(), __ilist, __env);
}
# endif // _CCCL_CTK_AT_LEAST(13, 0)
_CCCL_END_NAMESPACE_CUDA
# include <cuda/std/__cccl/epilogue.h>
#endif // _CCCL_HAS_CTK()
#endif // _CUDA___CONTAINER_MAKE_BUFFER_WITH_POOL_H

View File

@@ -0,0 +1,211 @@
//===----------------------------------------------------------------------===//
//
// 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___CONTAINER_RESIZABLE_BUFFER_H
#define _CUDA___CONTAINER_RESIZABLE_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
#if _CCCL_HAS_CTK()
# include <cuda/__container/buffer.h>
# include <cuda/std/__host_stdlib/stdexcept>
# include <cuda/std/__memory/addressof.h>
# include <cuda/std/__utility/exchange.h>
# include <cuda/std/__utility/move.h>
# include <cuda/std/__utility/swap.h>
# include <cuda/std/__cccl/prologue.h>
_CCCL_BEGIN_NAMESPACE_CUDA
_CCCL_BEGIN_NAMESPACE_ABI_VER4_BUMP
//! @brief Internal buffer adapter that tracks allocation capacity separately
//! from logical size.
//!
//! `cuda::__resizable_buffer` preserves the `cuda::buffer` interface through
//! public inheritance. The inherited `size()` remains the logical number of
//! elements, while `capacity()` is the number of elements that can be addressed
//! without reallocating.
template <class _Tp, class... _Properties>
class __resizable_buffer : public buffer<_Tp, _Properties...>
{
using __base_t = buffer<_Tp, _Properties...>;
public:
using size_type = typename __base_t::size_type;
private:
size_type __capacity_ = static_cast<const __base_t&>(*this).size();
_CCCL_HOST_API void __replace_allocation(::cuda::stream_ref __stream, size_type __new_capacity)
{
const auto __old_size = this->size();
const auto __old_capacity = __capacity_;
_CCCL_ASSERT(__old_size <= __new_capacity,
"cuda::__resizable_buffer reallocation capacity must be at least the current size");
auto __old_buffer = __base_t::__replace_allocation(__stream, __new_capacity);
__capacity_ = __new_capacity;
__old_buffer.__set_size_unsynchronized(__old_capacity);
if (__old_size != 0)
{
::cuda::__copy_cross_buffers(__stream, *this, __old_buffer, __old_size);
// Free on the copy stream so the stream-ordered deallocation happens
// after the read from the old allocation.
__old_buffer.destroy(__stream);
}
else
{
__old_buffer.destroy();
}
__base_t::__set_size_unsynchronized(__old_size);
}
_CCCL_HOST_API void __replace_allocation_discard(::cuda::stream_ref __stream, size_type __new_capacity)
{
const auto __old_capacity = ::cuda::std::exchange(__capacity_, 0);
__base_t::__replace_allocation_discard(__stream, __new_capacity, __old_capacity);
__capacity_ = __new_capacity;
}
public:
using __base_t::__base_t;
//! @brief Constructs a resizable buffer by taking over an existing
//! `cuda::buffer` allocation.
//!
//! The initial capacity is the source buffer size.
_CCCL_HOST_API explicit __resizable_buffer(__base_t&& __buffer) noexcept
: __base_t(::cuda::std::move(__buffer))
{}
__resizable_buffer(const __resizable_buffer&) = delete;
__resizable_buffer& operator=(const __resizable_buffer&) = delete;
_CCCL_HOST_API __resizable_buffer(__resizable_buffer&& __other) noexcept
: __base_t(::cuda::std::move(__other))
, __capacity_(::cuda::std::exchange(__other.__capacity_, 0))
{}
_CCCL_HOST_API __resizable_buffer& operator=(__resizable_buffer&& __other) noexcept
{
if (this != ::cuda::std::addressof(__other))
{
__base_t::__set_size_unsynchronized(__capacity_);
__base_t::operator=(::cuda::std::move(__other));
__capacity_ = ::cuda::std::exchange(__other.__capacity_, 0);
}
return *this;
}
_CCCL_HOST_API ~__resizable_buffer() noexcept
{
__base_t::__set_size_unsynchronized(__capacity_);
}
//! @brief Returns the number of elements that fit in the current allocation
//! without reallocating.
[[nodiscard]] _CCCL_HOST_API size_type capacity() const noexcept
{
return __capacity_;
}
//! @brief Returns `capacity() * sizeof(value_type)`.
[[nodiscard]] _CCCL_HOST_API size_type capacity_bytes() const noexcept
{
return __capacity_ * sizeof(_Tp);
}
//! @brief Changes the logical size without stream ordering or reallocating.
//!
//! This member only updates the host-side logical size. It can shrink or grow
//! within `capacity()`, and throws if growth would require reallocation.
_CCCL_HOST_API void resize_unsynchronized(size_type __new_size, ::cuda::no_init_t)
{
if (__new_size > __capacity_)
{
_CCCL_THROW(::std::invalid_argument,
"cuda::__resizable_buffer::resize_unsynchronized cannot grow beyond capacity");
}
__base_t::__set_size_unsynchronized(__new_size);
}
//! @brief Changes the logical size, reallocating on \p __stream if needed.
//!
//! If reallocation is needed, existing logical elements are copied to the new
//! allocation and newly exposed elements are left uninitialized.
_CCCL_HOST_API void resize(::cuda::stream_ref __stream, size_type __new_size, ::cuda::no_init_t)
{
if (__new_size > __capacity_)
{
__replace_allocation(__stream, __new_size);
}
__base_t::__set_size_unsynchronized(__new_size);
}
//! @brief Changes the logical size, reallocating on \p __stream if needed,
//! without preserving existing contents.
//!
//! All elements in the resulting logical range are left uninitialized.
_CCCL_HOST_API void resize_discard(::cuda::stream_ref __stream, size_type __new_size, ::cuda::no_init_t)
{
if (__new_size > __capacity_)
{
__replace_allocation_discard(__stream, __new_size);
}
__base_t::__set_size_unsynchronized(__new_size);
}
//! @brief Swaps the allocation, logical size, stream, memory resource, and
//! capacity with \p __other.
_CCCL_HOST_API void swap(__resizable_buffer& __other) noexcept
{
__base_t::swap(__other);
::cuda::std::swap(__capacity_, __other.__capacity_);
}
_CCCL_HOST_API friend void swap(__resizable_buffer& __lhs, __resizable_buffer& __rhs) noexcept
{
__lhs.swap(__rhs);
}
//! @brief Destroys the allocation using capacity rather than logical size.
_CCCL_HOST_API void destroy(::cuda::stream_ref __stream) noexcept
{
__base_t::__set_size_unsynchronized(__capacity_);
__base_t::destroy(__stream);
__capacity_ = 0;
}
_CCCL_HOST_API void destroy() noexcept
{
destroy(this->stream());
}
};
_CCCL_END_NAMESPACE_ABI_VER4_BUMP
_CCCL_END_NAMESPACE_CUDA
# include <cuda/std/__cccl/epilogue.h>
#endif // _CCCL_HAS_CTK()
#endif // _CUDA___CONTAINER_RESIZABLE_BUFFER_H

View File

@@ -0,0 +1,477 @@
//===----------------------------------------------------------------------===//
//
// 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_ASYNC_BUFFER_H
#define __CUDAX__CONTAINERS_UNINITIALIZED_ASYNC_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
#if _CCCL_HAS_CTK()
# include <cuda/__memory_resource/allocation_alignment.h>
# include <cuda/__memory_resource/any_resource.h>
# include <cuda/__memory_resource/properties.h>
# include <cuda/__stream/stream_ref.h>
# include <cuda/std/__memory/addressof.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_async_buffer class provides a typed buffer allocated
//! in stream-order from a given memory resource.
_CCCL_BEGIN_NAMESPACE_CUDA
//! @rst
//! .. _libcudacxx-containers-uninitialized-async-buffer:
//!
//! Uninitialized stream-ordered type-safe memory storage
//! ------------------------------------------------------
//!
//! ``__uninitialized_async_buffer`` provides a typed buffer allocated in stream
//! order from a given :ref:`async 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_async_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, only
//! stateless properties can be forwarded. To use a stateful property, implement
//! :ref:`get_property(const __uninitialized_async_buffer&, Property)
//! <libcudacxx-extended-api-memory-resources-properties>`.
//!
//! .. warning::
//!
//! ``__uninitialized_async_buffer`` uses `stream-ordered allocation
//! <https://developer.nvidia.com/blog/using-cuda-stream-ordered-memory-allocator-part-1/>`__.
//! It is the user's responsibility to ensure the lifetime of both the
//! provided async resource and the stream exceed the lifetime of the buffer.
//!
//! @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_async_buffer
{
private:
static_assert(::cuda::mr::__contains_execution_space_property<_Properties...>,
"The properties of cuda::__uninitialized_async_buffer must contain at least one execution space "
"property!");
using __async_resource = ::cuda::mr::any_resource<_Properties...>;
__async_resource __mr_;
::cuda::stream_ref __stream_ = {::cudaStream_t{}};
size_t __count_ = 0;
size_t __alignment_ = alignof(_Tp);
void* __buf_ = nullptr;
template <class, class...>
friend class __uninitialized_async_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_HOST_API size_t __get_allocation_size(const size_t __count) const noexcept
{
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_HOST_API _Tp* __get_data() const noexcept
{
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
//! cuda::launch.
//! @pre The buffer must have the cuda::mr::device_accessible property.
template <class _Tp2 = _Tp>
[[nodiscard]] _CCCL_HOST_API friend auto
transform_launch_argument(::cuda::stream_ref, __uninitialized_async_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
//! cuda::launch
//! @pre The buffer must have the cuda::mr::device_accessible property.
template <class _Tp2 = _Tp>
[[nodiscard]] _CCCL_HOST_API friend auto
transform_launch_argument(::cuda::stream_ref, const __uninitialized_async_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()};
}
# ifndef _CCCL_DOXYGEN_INVOKED
// This is needed to ensure that we do not do a deep copy in
// __replace_allocation
struct __fake_resource_ref
{
__async_resource* __resource_;
void* allocate_sync(std::size_t __size, std::size_t __alignment)
{
return __resource_->allocate_sync(__size, __alignment);
}
void deallocate_sync(void* __ptr, std::size_t __size, std::size_t __alignment) noexcept
{
__resource_->deallocate_sync(__ptr, __size, __alignment);
}
void* allocate(::cuda::stream_ref __stream, std::size_t __size, std::size_t __alignment)
{
return __resource_->allocate(__stream, __size, __alignment);
}
void deallocate(::cuda::stream_ref __stream, void* __ptr, std::size_t __size, std::size_t __alignment) noexcept
{
__resource_->deallocate(__stream, __ptr, __size, __alignment);
}
friend bool operator==(const __fake_resource_ref& __lhs, const __fake_resource_ref& __rhs) noexcept
{
return *__lhs.__resource_ == *__rhs.__resource_;
}
friend bool operator!=(const __fake_resource_ref& __lhs, const __fake_resource_ref& __rhs) noexcept
{
return *__lhs.__resource_ != *__rhs.__resource_;
}
//! @brief Forwards the passed properties
_CCCL_TEMPLATE(class _Property)
_CCCL_REQUIRES(::cuda::std::__is_included_in_v<_Property, _Properties...>)
_CCCL_HOST_API friend constexpr void get_property(const __fake_resource_ref&, _Property) noexcept {}
};
# endif // _CCCL_DOXYGEN_INVOKED
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_async_buffer, allocating
//! sufficient storage for \p __count elements through
//! \p __mr
//! @param __mr The async memory resource to allocate the buffer with.
//! @param __stream The CUDA stream used for stream-ordered allocation.
//! @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)`. Only
//! allocates memory when \p __count > 0
_CCCL_HOST_API __uninitialized_async_buffer(
__async_resource __mr,
const ::cuda::stream_ref __stream,
const size_t __count,
const size_t __alignment = alignof(_Tp))
: __mr_(::cuda::std::move(__mr))
, __stream_(__stream)
, __count_(__count)
, __alignment_(__validate_alignment_param(__alignment))
, __buf_(__count_ == 0 ? nullptr : __mr_.allocate(__stream_, __get_allocation_size(__count_), __alignment_))
{}
private:
static size_t __validate_alignment_param(size_t __a)
{
::cuda::__validate_allocation_alignment(__a, alignof(_Tp));
return __a;
}
public:
__uninitialized_async_buffer(const __uninitialized_async_buffer&) = delete;
__uninitialized_async_buffer& operator=(const __uninitialized_async_buffer&) = delete;
//! @brief Move-constructs a \c __uninitialized_async_buffer from \p __other
//! @param __other Another \c __uninitialized_async_buffer
//! Takes ownership of the allocation in \p __other and resets it
_CCCL_HOST_API __uninitialized_async_buffer(__uninitialized_async_buffer&& __other) noexcept
: __mr_(::cuda::std::move(__other.__mr_))
, __stream_(::cuda::std::exchange(__other.__stream_, ::cuda::stream_ref{::cudaStream_t{}}))
, __count_(::cuda::std::exchange(__other.__count_, 0))
, __alignment_(::cuda::std::exchange(__other.__alignment_, alignof(_Tp)))
, __buf_(::cuda::std::exchange(__other.__buf_, nullptr))
{}
//! @brief Move-constructs a \c __uninitialized_async_buffer from \p __other
//! @param __other Another \c __uninitialized_async_buffer with matching
//! properties Takes ownership of the allocation in \p __other and resets it
_CCCL_TEMPLATE(class... _OtherProperties)
_CCCL_REQUIRES(__properties_match<_OtherProperties...>)
_CCCL_HOST_API __uninitialized_async_buffer(__uninitialized_async_buffer<_Tp, _OtherProperties...>&& __other) noexcept
: __mr_(::cuda::std::move(__other.__mr_))
, __stream_(::cuda::std::exchange(__other.__stream_, ::cuda::stream_ref{::cudaStream_t{}}))
, __count_(::cuda::std::exchange(__other.__count_, 0))
, __alignment_(::cuda::std::exchange(__other.__alignment_, alignof(_Tp)))
, __buf_(::cuda::std::exchange(__other.__buf_, nullptr))
{}
//! @brief Move-assigns a \c __uninitialized_async_buffer from \p __other
//! @param __other Another \c __uninitialized_async_buffer
//! Deallocates the current allocation and then takes ownership of the
//! allocation in \p __other and resets it
_CCCL_HOST_API __uninitialized_async_buffer& operator=(__uninitialized_async_buffer&& __other) noexcept
{
if (this == ::cuda::std::addressof(__other))
{
return *this;
}
if (__buf_)
{
__mr_.deallocate(__stream_, __buf_, __get_allocation_size(__count_), __alignment_);
}
__mr_ = ::cuda::std::move(__other.__mr_);
__stream_ = ::cuda::std::exchange(__other.__stream_, ::cuda::stream_ref{::cudaStream_t{}});
__count_ = ::cuda::std::exchange(__other.__count_, 0);
__alignment_ = ::cuda::std::exchange(__other.__alignment_, alignof(_Tp));
__buf_ = ::cuda::std::exchange(__other.__buf_, nullptr);
return *this;
}
//! @brief Destroys an \c __uninitialized_async_buffer, deallocates the buffer
//! in stream order on the stream that is stored in the buffer and destroys
//! the memory resource.
//! @param __stream The stream to deallocate the buffer on.
//! @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_HOST_API void destroy(::cuda::stream_ref __stream) noexcept
{
if (__buf_)
{
__mr_.deallocate(__stream, __buf_, __get_allocation_size(__count_), __alignment_);
__buf_ = nullptr;
__count_ = 0;
}
// TODO should we make sure we move the mr only once by moving it to the if
// above? It won't work for 0 count buffers, so we would probably need a
// separate bool to track it
auto __tmp_mr = ::cuda::std::move(__mr_);
}
//! @brief Destroys an \c __uninitialized_async_buffer, deallocates the buffer
//! in stream order on the stream that is stored in 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_HOST_API void destroy() noexcept
{
destroy(__stream_);
}
# ifndef _CCCL_DOXYGEN_INVOKED
_CCCL_HOST_API constexpr void __set_size(const size_t __count) noexcept
{
__count_ = __count;
}
# endif // _CCCL_DOXYGEN_INVOKED
//! @brief Destroys an \c __uninitialized_async_buffer and deallocates the
//! buffer in stream order on the stream that was used to create the buffer.
//! @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_HOST_API ~__uninitialized_async_buffer()
{
destroy();
}
//! @brief Returns an aligned pointer to the first element in the buffer
[[nodiscard]] _CCCL_HOST_API constexpr pointer begin() noexcept
{
return __get_data();
}
//! @overload
[[nodiscard]] _CCCL_HOST_API constexpr 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_HOST_API constexpr pointer end() noexcept
{
return __get_data() + __count_;
}
//! @overload
[[nodiscard]] _CCCL_HOST_API constexpr const_pointer end() const noexcept
{
return __get_data() + __count_;
}
//! @brief Returns an aligned pointer to the first element in the buffer
[[nodiscard]] _CCCL_HOST_API constexpr pointer data() noexcept
{
return __get_data();
}
//! @overload
[[nodiscard]] _CCCL_HOST_API constexpr const_pointer data() const noexcept
{
return __get_data();
}
//! @brief Returns the size of the buffer
[[nodiscard]] _CCCL_HOST_API constexpr size_type size() const noexcept
{
return __count_;
}
//! @brief Returns the alignment used for the allocation
[[nodiscard]] _CCCL_HIDE_FROM_ABI constexpr size_type alignment() const noexcept
{
return __alignment_;
}
//! @brief Returns the size of the buffer in bytes
[[nodiscard]] _CCCL_HOST_API constexpr size_type size_bytes() const noexcept
{
return __count_ * sizeof(_Tp);
}
//! @rst
//! Returns a \c const reference to the :ref:`any_resource
//! <cuda-memory-resource-any-async-resource>` that holds the memory resource
//! used to allocate the buffer
//! @endrst
[[nodiscard]] _CCCL_HOST_API const __async_resource& memory_resource() const noexcept
{
return __mr_;
}
//! @brief Returns the stored stream
//! @note Stream used to allocate the buffer is initially stored in the
//! buffer, but can be changed with `set_stream`
[[nodiscard]] _CCCL_HOST_API constexpr ::cuda::stream_ref stream() const noexcept
{
return __stream_;
}
//! @brief Replaces the stored stream
//! @param __new_stream the new stream
//! @note Always synchronizes with the old stream
_CCCL_HOST_API constexpr void set_stream(::cuda::stream_ref __new_stream)
{
if (__new_stream != __stream_)
{
__stream_.sync();
}
__stream_ = __new_stream;
}
//! @brief Replaces the stored stream
//! @param __new_stream the new stream
//! @warning This does not synchronize between \p __new_stream and the current
//! stream. It is the user's responsibility to ensure proper stream order
//! going forward
_CCCL_HOST_API constexpr void set_stream_unsynchronized(::cuda::stream_ref __new_stream) noexcept
{
__stream_ = __new_stream;
}
//! @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_HOST_API friend constexpr void get_property(const __uninitialized_async_buffer&, _Property) noexcept {}
# ifndef _CCCL_DOXYGEN_INVOKED
//! @brief Internal method to grow the allocation to a new size \p __count.
//! @param __stream The stream to allocate the new allocation on.
//! @param __count The new size of the allocation.
//! @return An \c __uninitialized_async_buffer that holds the previous
//! allocation
//! @warning This buffer must outlive the returned buffer
_CCCL_HOST_API __uninitialized_async_buffer __replace_allocation(::cuda::stream_ref __stream, const size_t __count)
{
// Create a new buffer with a reference to the stored memory resource and
// swap allocation information
__uninitialized_async_buffer __ret{
__fake_resource_ref{::cuda::std::addressof(__mr_)}, __stream, __count, __alignment_};
::cuda::std::swap(__count_, __ret.__count_);
::cuda::std::swap(__alignment_, __ret.__alignment_);
::cuda::std::swap(__buf_, __ret.__buf_);
__ret.__stream_ = ::cuda::std::exchange(__stream_, __stream);
return __ret;
}
//! @overload
_CCCL_HOST_API __uninitialized_async_buffer __replace_allocation(const size_t __count)
{
return __replace_allocation(__stream_, __count);
}
_CCCL_HOST_API void
__replace_allocation_discard(::cuda::stream_ref __stream, const size_t __count, const size_t __old_capacity)
{
if (__buf_)
{
__mr_.deallocate(__stream_, __buf_, __get_allocation_size(__old_capacity), __alignment_);
__buf_ = nullptr;
__count_ = 0;
}
__stream_ = __stream;
if (__count != 0)
{
__buf_ = __mr_.allocate(__stream_, __get_allocation_size(__count), __alignment_);
}
__count_ = __count;
}
# endif // _CCCL_DOXYGEN_INVOKED
};
template <class _Tp>
using uninitialized_async_device_buffer = __uninitialized_async_buffer<_Tp, ::cuda::mr::device_accessible>;
_CCCL_END_NAMESPACE_CUDA
# include <cuda/std/__cccl/epilogue.h>
#endif // _CCCL_HAS_CTK()
#endif //__CUDAX__CONTAINERS_UNINITIALIZED_ASYNC_BUFFER_H