Skip to main content

DeviceBuffer

Struct DeviceBuffer 

Source
pub struct DeviceBuffer<T: Copy> { /* private fields */ }
Expand description

A contiguous buffer of T elements allocated in GPU device memory.

The buffer owns the underlying CUdeviceptr allocation and frees it on drop. All copy operations validate that source and destination lengths match, returning CudaError::InvalidValue on mismatch.

Implementations§

Source§

impl<T: Copy> DeviceBuffer<T>

Source

pub fn view_as<U: Copy>(&self) -> CudaResult<BufferView<'_, U>>

Reinterprets this buffer as a different element type U (immutable).

The total byte size of the buffer must be evenly divisible by size_of::<U>(). The resulting view has byte_size / size_of::<U>() elements.

§Errors

Returns CudaError::InvalidValue if:

  • size_of::<U>() is zero (ZST).
  • The buffer’s byte size is not divisible by size_of::<U>().
  • The buffer’s device pointer is not aligned to align_of::<U>().
Source

pub fn view_as_mut<U: Copy>(&mut self) -> CudaResult<BufferViewMut<'_, U>>

Reinterprets this buffer as a different element type U (mutable).

The total byte size of the buffer must be evenly divisible by size_of::<U>(). The resulting view has byte_size / size_of::<U>() elements.

§Errors

Returns CudaError::InvalidValue if:

  • size_of::<U>() is zero (ZST).
  • The buffer’s byte size is not divisible by size_of::<U>().
  • The buffer’s device pointer is not aligned to align_of::<U>().
Source§

impl<T: Copy> DeviceBuffer<T>

Source

pub fn alloc(n: usize) -> CudaResult<Self>

Allocates a device buffer capable of holding n elements of type T.

§Errors
Source

pub fn zeroed(n: usize) -> CudaResult<Self>

Allocates a device buffer of n elements and zero-initialises every byte.

This is equivalent to alloc followed by a cuMemsetD8_v2 call that writes 0 to every byte.

The zero-fill is fully completed on the device before this function returns: cuMemsetD8_v2 is issued on the legacy default stream and is asynchronous with respect to the host for device memory, so the returned buffer would otherwise not be guaranteed zeroed relative to work later submitted on a CU_STREAM_NON_BLOCKING stream (which does not implicitly synchronise with the default stream). A context synchronise after the memset makes the “every byte is 0” postcondition hold for any consumer stream, closing a data race where a kernel on a non-blocking stream could read/overwrite this buffer concurrently with the pending zero-fill.

§Errors

Same as alloc, plus any error from cuMemsetD8_v2 or the context synchronise.

Source

pub fn from_host(data: &[T]) -> CudaResult<Self>

Allocates a device buffer and copies the contents of data into it.

The resulting buffer has the same length as the input slice.

§Errors
Source

pub unsafe fn from_raw(ptr: CUdeviceptr, len: usize) -> Self

Wraps an externally-owned device pointer in a non-owning DeviceBuffer view without allocating.

The returned buffer points at the existing allocation described by ptr and len, and exposes the full DeviceBuffer API (copies, slicing, as_device_ptr, and use as a matrix operand in oxicuda-blas) over that memory. Because the view does not own the allocation, its Drop is a no-op: it will not call cuMemFree_v2. Ownership and the lifetime of the underlying memory remain entirely with the original owner (e.g. another CUDA library, cudarc, or a foreign allocator).

This enables zero-copy interop: a consumer that already holds a resident device allocation can wrap it here and run OxiCUDA operations in place, with no host round-trip and no extra device allocation.

§Safety

The caller must guarantee all of the following:

  • ptr is a valid CUDA device pointer into an allocation of at least len * size_of::<T>() bytes, correctly aligned for T, and associated with the CUDA context that subsequent OxiCUDA operations run under.
  • The pointed-to memory contains a valid, initialised [T; len] (or is only used as a write target before being read).
  • The underlying allocation outlives this DeviceBuffer view: the original owner must not free, reallocate, or invalidate ptr while this view (or any DeviceSlice borrowed from it) is alive.
  • No other live DeviceBuffer owns the same ptr (to avoid a double-free) and aliasing rules are respected when the view is used mutably (e.g. as a MatrixDescMut output operand).

A zero len is permitted (unlike alloc) since no allocation is performed; a ptr of 0 is also permitted for a zero-length view, but pointer/length validity is the caller’s responsibility.

§Example
// `raw` is a device pointer owned elsewhere (e.g. obtained from another
// CUDA library) pointing at `n` resident `f32` elements.
// SAFETY: `raw` is valid for `n` f32s and outlives `view`.
let view = unsafe { DeviceBuffer::<f32>::from_raw(raw, n) };
// `view` can now be used with oxicuda-blas / copies; dropping it does
// NOT free `raw`.
assert_eq!(view.len(), n);
Source

pub fn copy_from_host(&mut self, src: &[T]) -> CudaResult<()>

Copies data from a host slice into this device buffer (synchronous).

The slice length must exactly match the buffer length.

§Errors
Source

pub fn copy_to_host(&self, dst: &mut [T]) -> CudaResult<()>

Copies this device buffer’s contents into a host slice (synchronous).

The slice length must exactly match the buffer length.

§Errors
Source

pub fn copy_from_device(&mut self, src: &DeviceBuffer<T>) -> CudaResult<()>

Copies the entire contents of another device buffer into this one.

Both buffers must have the same length.

§Errors
Source

pub fn copy_from_host_async( &mut self, src: &[T], stream: &Stream, ) -> CudaResult<()>

Asynchronously copies data from a host slice into this device buffer.

The copy is enqueued on stream and may not be complete when this function returns. The caller must ensure that src remains valid (i.e., is not moved or dropped) until the stream has been synchronised. For guaranteed correctness, prefer using a PinnedBuffer as the source.

§Errors
Source

pub fn copy_to_host_async( &self, dst: &mut [T], stream: &Stream, ) -> CudaResult<()>

Asynchronously copies this device buffer’s contents into a host slice.

The copy is enqueued on stream and may not be complete when this function returns. The caller must ensure that dst remains valid and is not read until the stream has been synchronised. For guaranteed correctness, prefer using a PinnedBuffer as the destination.

§Errors
Source

pub fn len(&self) -> usize

Returns the number of T elements in this buffer.

Source

pub fn is_empty(&self) -> bool

Returns true if the buffer contains zero elements.

In practice this is always false because alloc rejects zero-length allocations.

Source

pub fn byte_size(&self) -> usize

Returns the total size of the allocation in bytes.

Source

pub fn as_device_ptr(&self) -> CUdeviceptr

Returns the raw CUdeviceptr handle for this buffer.

This is useful when passing the pointer to kernel launch parameters or other low-level driver calls.

Source

pub fn slice(&self, offset: usize, len: usize) -> CudaResult<DeviceSlice<'_, T>>

Returns a borrowed DeviceSlice referencing a sub-range of this buffer starting at element offset and spanning len elements.

§Errors

Returns CudaError::InvalidValue if the requested range exceeds the buffer bounds (i.e., offset + len > self.len()).

Trait Implementations§

Source§

impl<T: Copy> Drop for DeviceBuffer<T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl<T: Copy + Send> Send for DeviceBuffer<T>

Source§

impl<T: Copy + Sync> Sync for DeviceBuffer<T>

Auto Trait Implementations§

§

impl<T> Freeze for DeviceBuffer<T>

§

impl<T> RefUnwindSafe for DeviceBuffer<T>
where T: RefUnwindSafe,

§

impl<T> Unpin for DeviceBuffer<T>
where T: Unpin,

§

impl<T> UnsafeUnpin for DeviceBuffer<T>

§

impl<T> UnwindSafe for DeviceBuffer<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more