OpenVDB 13.1.0
Loading...
Searching...
No Matches
Buffer< T, R > Class Template Reference

Owning, typed container of T elements allocated from a memory resource R held by value. More...

#include <nanovdb/cuda/Buffer.h>

Public Types

using ElementType = T
 Element and resource types, for generic code that rebinds one or constructs sibling buffers over the same resource.
using ResourceType = R
template<typename U>
using rebind = Buffer<U, R>
 Alias for a sibling buffer over the same resource with a different element type.

Public Member Functions

 Buffer ()=default
 Default c-tor of an empty buffer; performs no allocation.
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
 Buffer (cudaStream_t stream, R resource, size_t count, NoInit)
 C-tor allocating count uninitialized elements, stream-ordered on stream. Parameter order follows cuda::buffer: (stream, resource, count, no_init).
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
 Buffer (cudaStream_t stream, size_t count, NoInit)
 Convenience c-tor using a default-constructed resource.
template<typename S = R, std::enable_if_t<!is_async_resource< S >::value &&is_resource< S >::value, int > = 0>
 Buffer (R resource, size_t count, NoInit)
 C-tor allocating count uninitialized elements from a synchronous resource: the stream-less analog of (stream, resource, count, no_init).
template<typename S = R, std::enable_if_t<!is_async_resource< S >::value &&is_resource< S >::value, int > = 0>
 Buffer (size_t count, NoInit)
 Convenience c-tor using a default-constructed resource.
 Buffer (const Buffer &)=delete
 Explicitly disallow copy construction and assignment operation.
Bufferoperator= (const Buffer &)=delete
 Buffer (Buffer &&other) noexcept
 Move c-tor; steals the allocation (and retained stream, if any) and leaves other empty.
Bufferoperator= (Buffer &&other) noexcept
 Move assignment; frees the current allocation first, then steals from other and leaves it empty. Self-move is a no-op.
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
Buffer copy (cudaStream_t stream) const
 Returns a deep copy of this buffer, allocated from a copy of the resource; the allocation and element copy are ordered on stream, which becomes the copy's retained stream.
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
Buffer copy () const
 Returns a deep copy of this buffer ordered on the retained stream, i.e. copy(this->stream()).
template<typename S = R, std::enable_if_t<!is_async_resource< S >::value &&is_resource< S >::value, int > = 0>
Buffer copy () const
 Returns a deep copy of this buffer, allocated from a copy of the synchronous resource.
 ~Buffer ()
 D-tor. A stream-ordered resource frees on the retained stream; a synchronous resource frees immediately.
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
cudaStream_t stream () const
 Returns the retained stream, i.e. the stream the buffer's memory will be freed on.
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
void set_stream (cudaStream_t stream)
 Replaces the retained stream without synchronizing; subsequent deallocation (and destruction) is ordered on stream instead.
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
void resize (size_t count, cudaStream_t stream)
 Resizes the buffer to count elements, preserving the leading min(old, new) elements. Every operation — the new allocation, the prefix copy, and the free of the old block — is ordered on stream, which becomes the retained stream: the prefix copy is the old block's last use, so that is the stream its free must be ordered on.
template<typename S = R, std::enable_if_t<!is_async_resource< S >::value &&is_resource< S >::value, int > = 0>
void resize (size_t count)
 Resizes the buffer to count elements through the synchronous resource, preserving the leading min(old, new) elements.
T * data ()
 Returns a pointer to the elements, or nullptr if empty.
const T * data () const
resource () const
 Returns a copy of the resource; for a ResourceRef this refers to the same underlying instance.
size_t size () const
 Returns the number of elements.
size_t size_bytes () const
 Returns the size of the buffer's allocation in bytes.
bool empty () const
 Returns true if this buffer manages no memory.
void destroy ()
 Frees the buffer memory (if any) and resets to the empty state. A stream-ordered resource frees on the retained stream.
void clear ()
 Frees the buffer memory (if any) and resets to the empty state.
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
void destroy (cudaStream_t stream)
 Frees the buffer memory (if any) on stream and resets to the empty state. stream becomes the retained stream.
void swap (Buffer &other) noexcept
 Exchanges the contents of this buffer with other. Neither buffer allocates, frees, or copies element data.

Detailed Description

template<typename T, typename R = DeviceResource>
class nanovdb::cuda::Buffer< T, R >

Owning, typed container of T elements allocated from a memory resource R held by value.

Template Parameters
Telement type; sizes are expressed in elements, not bytes
Rmemory resource, either stream-ordered (AsyncResource concept, see is_async_resource) or synchronous (Resource concept, see is_resource). When R provides both interfaces the stream-ordered one is used.

With a stream-ordered resource the Buffer retains the stream of the most recent allocation (or the one supplied via set_stream) and orders its deallocation on that stream. Buffer is move-only.

Note
Cross-stream ordering is the caller's, expressed with ordinary CUDA events – the buffer deliberately tracks nothing. To hand a buffer's contents to work on another stream (a consumer library, a wrapped tensor), record after the last write and make the consumer wait:
cudaEvent_t ready;
cudaEventCreateWithFlags(&ready, cudaEventDisableTiming);
cudaEventRecord(ready, producerStream); // after the last write
cudaStreamWaitEvent(consumerStream, ready); // before the first read
and order the buffer's destruction (which frees on its retained stream) after all consumers the same way, or synchronize.

Member Typedef Documentation

◆ ElementType

template<typename T, typename R = DeviceResource>
using ElementType = T

Element and resource types, for generic code that rebinds one or constructs sibling buffers over the same resource.

◆ rebind

template<typename T, typename R = DeviceResource>
template<typename U>
using rebind = Buffer<U, R>

Alias for a sibling buffer over the same resource with a different element type.

◆ ResourceType

template<typename T, typename R = DeviceResource>
using ResourceType = R

Constructor & Destructor Documentation

◆ Buffer() [1/7]

template<typename T, typename R = DeviceResource>
Buffer ( )
default

Default c-tor of an empty buffer; performs no allocation.

◆ Buffer() [2/7]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
Buffer ( cudaStream_t stream,
R resource,
size_t count,
NoInit  )
inlineexplicit

C-tor allocating count uninitialized elements, stream-ordered on stream. Parameter order follows cuda::buffer: (stream, resource, count, no_init).

Parameters
streamcuda stream the allocation is ordered on
resourceresource instance the buffer takes ownership of
countnumber of elements

◆ Buffer() [3/7]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
Buffer ( cudaStream_t stream,
size_t count,
NoInit  )
inline

Convenience c-tor using a default-constructed resource.

Parameters
streamcuda stream the allocation is ordered on
countnumber of elements
Note
There is deliberately no count c-tor without NoInit: implicit initialization of freshly allocated memory costs a hidden fill pass that the dominant allocate-then-overwrite pattern wastes, so initialization is always explicit (matching cuda::buffer, whose count c-tor likewise requires cuda::no_init).

◆ Buffer() [4/7]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t<!is_async_resource< S >::value &&is_resource< S >::value, int > = 0>
Buffer ( R resource,
size_t count,
NoInit  )
inlineexplicit

C-tor allocating count uninitialized elements from a synchronous resource: the stream-less analog of (stream, resource, count, no_init).

Parameters
resourceresource instance the buffer takes ownership of
countnumber of elements

◆ Buffer() [5/7]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t<!is_async_resource< S >::value &&is_resource< S >::value, int > = 0>
Buffer ( size_t count,
NoInit  )
inline

Convenience c-tor using a default-constructed resource.

Parameters
countnumber of elements

◆ Buffer() [6/7]

template<typename T, typename R = DeviceResource>
Buffer ( const Buffer< T, R > & )
delete

Explicitly disallow copy construction and assignment operation.

◆ Buffer() [7/7]

template<typename T, typename R = DeviceResource>
Buffer ( Buffer< T, R > && other)
inlinenoexcept

Move c-tor; steals the allocation (and retained stream, if any) and leaves other empty.

◆ ~Buffer()

template<typename T, typename R = DeviceResource>
~Buffer ( )
inline

D-tor. A stream-ordered resource frees on the retained stream; a synchronous resource frees immediately.

Member Function Documentation

◆ clear()

template<typename T, typename R = DeviceResource>
void clear ( )
inline

Frees the buffer memory (if any) and resets to the empty state.

Deprecated
Use destroy(): the handles now dispatch to it directly.

◆ copy() [1/3]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
Buffer copy ( ) const
inline

Returns a deep copy of this buffer ordered on the retained stream, i.e. copy(this->stream()).

◆ copy() [2/3]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t<!is_async_resource< S >::value &&is_resource< S >::value, int > = 0>
Buffer copy ( ) const
inline

Returns a deep copy of this buffer, allocated from a copy of the synchronous resource.

◆ copy() [3/3]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
Buffer copy ( cudaStream_t stream) const
inline

Returns a deep copy of this buffer, allocated from a copy of the resource; the allocation and element copy are ordered on stream, which becomes the copy's retained stream.

Parameters
streamcuda stream the allocation and element copy are ordered on

◆ data() [1/2]

template<typename T, typename R = DeviceResource>
T * data ( )
inline

Returns a pointer to the elements, or nullptr if empty.

◆ data() [2/2]

template<typename T, typename R = DeviceResource>
const T * data ( ) const
inline

◆ destroy() [1/2]

template<typename T, typename R = DeviceResource>
void destroy ( )
inline

Frees the buffer memory (if any) and resets to the empty state. A stream-ordered resource frees on the retained stream.

Note
Spelled destroy to match cuda::buffer. This is the name to use.

◆ destroy() [2/2]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
void destroy ( cudaStream_t stream)
inline

Frees the buffer memory (if any) on stream and resets to the empty state. stream becomes the retained stream.

Parameters
streamcuda stream the deallocation is ordered on
Warning
The caller is responsible for ordering stream after any in-flight work that uses the buffer's memory.

◆ empty()

template<typename T, typename R = DeviceResource>
bool empty ( ) const
inline

Returns true if this buffer manages no memory.

◆ operator=() [1/2]

template<typename T, typename R = DeviceResource>
Buffer & operator= ( Buffer< T, R > && other)
inlinenoexcept

Move assignment; frees the current allocation first, then steals from other and leaves it empty. Self-move is a no-op.

◆ operator=() [2/2]

template<typename T, typename R = DeviceResource>
Buffer & operator= ( const Buffer< T, R > & )
delete

◆ resize() [1/2]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t<!is_async_resource< S >::value &&is_resource< S >::value, int > = 0>
void resize ( size_t count)
inline

Resizes the buffer to count elements through the synchronous resource, preserving the leading min(old, new) elements.

Parameters
countnumber of elements

◆ resize() [2/2]

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
void resize ( size_t count,
cudaStream_t stream )
inline

Resizes the buffer to count elements, preserving the leading min(old, new) elements. Every operation — the new allocation, the prefix copy, and the free of the old block — is ordered on stream, which becomes the retained stream: the prefix copy is the old block's last use, so that is the stream its free must be ordered on.

Parameters
countnumber of elements
streamcuda stream the reallocation is ordered on
Warning
The caller is responsible for ordering stream after any in-flight work on the previously retained stream that uses the buffer's memory.

◆ resource()

template<typename T, typename R = DeviceResource>
R resource ( ) const
inline

Returns a copy of the resource; for a ResourceRef this refers to the same underlying instance.

Note
Requires R to be copy-constructible (the cuda::mr convention: resources are cheap handles). A resource that owns its pool by value hands the caller an independent copy of that pool.

◆ set_stream()

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
void set_stream ( cudaStream_t stream)
inline

Replaces the retained stream without synchronizing; subsequent deallocation (and destruction) is ordered on stream instead.

Parameters
streamcuda stream subsequent deallocation is ordered on
Warning
The caller is responsible for ordering stream after any in-flight work that uses the buffer's memory. This deliberately does not synchronize, matching cuda::buffer's set_stream, which avoids implicit synchronization in fundamental primitives.

◆ size()

template<typename T, typename R = DeviceResource>
size_t size ( ) const
inline

Returns the number of elements.

◆ size_bytes()

template<typename T, typename R = DeviceResource>
size_t size_bytes ( ) const
inline

Returns the size of the buffer's allocation in bytes.

◆ stream()

template<typename T, typename R = DeviceResource>
template<typename S = R, std::enable_if_t< is_async_resource< S >::value, int > = 0>
cudaStream_t stream ( ) const
inline

Returns the retained stream, i.e. the stream the buffer's memory will be freed on.

◆ swap()

template<typename T, typename R = DeviceResource>
void swap ( Buffer< T, R > & other)
inlinenoexcept

Exchanges the contents of this buffer with other. Neither buffer allocates, frees, or copies element data.

Parameters
otherbuffer to exchange contents with