Struct custos_math::custos::Buffer
source · pub struct Buffer<'a, T = f32, D = CPU, S = ()>where
D: Device,
S: Shape,{
pub ptr: <D as Device>::Ptr<T, S>,
pub device: Option<&'a D>,
pub node: Node,
}Expand description
The underlying non-growable array structure. A Buffer may be encapsulated in other structs.
By default, the Buffer is a f32 CPU Buffer.
Example
use custos::prelude::*;
fn buffer_f32_cpu(buf: &Buffer) {}
fn buffer_generic<T, D: Device>(buf: &Buffer<T, D>) {}
let device = CPU::new();
let buf = Buffer::from((&device, [0.5, 1.3, 3.2, 2.43]));
buffer_f32_cpu(&buf);
buffer_generic(&buf);Fields§
§ptr: <D as Device>::Ptr<T, S>§device: Option<&'a D>§node: NodeImplementations§
source§impl<'a, T> Buffer<'a, T, (), ()>
impl<'a, T> Buffer<'a, T, (), ()>
source§impl<'a, T, D, S> Buffer<'a, T, D, S>where
D: Device,
S: Shape,
impl<'a, T, D, S> Buffer<'a, T, D, S>where D: Device, S: Shape,
sourcepub fn new(device: &'a D, len: usize) -> Buffer<'a, T, D, S>where
D: Alloc<'a, T, S>,
pub fn new(device: &'a D, len: usize) -> Buffer<'a, T, D, S>where D: Alloc<'a, T, S>,
Creates a zeroed (or values set to default) Buffer with the given length on the specified device.
This Buffer can’t outlive the device specified as a parameter.
use custos::{CPU, Buffer};
let device = CPU::new();
let mut buffer = Buffer::<i32>::new(&device, 6);
// this only works with CPU or unified memory buffers (this creates a slice with the host pointer)
for value in &mut buffer {
*value = 2;
}
assert_eq!(buffer.as_slice(), &[2; 6]);
sourcepub fn deviceless<'b>(device: &'b D, len: usize) -> Buffer<'a, T, D, S>where
D: DevicelessAble<'b, T, S>,
pub fn deviceless<'b>(device: &'b D, len: usize) -> Buffer<'a, T, D, S>where D: DevicelessAble<'b, T, S>,
Buffers created with this method can outlive the device used to create this Buffer.
No operations can be invoked on this Buffer as [get_device!] will panic.
Examples
use custos::{CPU, Buffer};
let mut buf = {
let device = CPU::new();
Buffer::<u8>::deviceless(&device, 5)
};
// buf.read(); // panics
for (idx, element) in buf.iter_mut().enumerate() {
*element = idx as u8;
}
assert_eq!(buf.as_slice(), &[0, 1, 2, 3, 4]);pub fn device(&self) -> &'a D
pub fn read(&'a self) -> <D as Read<T, D, S>>::Read<'a>where T: Clone + Default, D: Read<T, D, S>,
sourcepub fn read_to_vec(&self) -> Vec<T, Global>where
D: Read<T, D, S>,
T: Default + Clone,
pub fn read_to_vec(&self) -> Vec<T, Global>where D: Read<T, D, S>, T: Default + Clone,
Reads the contents of the buffer and writes them into a vector.
If it is certain whether a CPU, or an unified CPU + OpenCL Buffer, is used, calling .as_slice() (or deref/mut to &/mut [&T]) is probably preferred.
Example
use custos::{CPU, Buffer};
let device = CPU::new();
let buf = Buffer::from((&device, [1, 2, 3, 4]));
assert_eq!(buf.read_to_vec(), vec![1, 2, 3, 4]);sourcepub fn write(&mut self, data: &[T])where
T: Clone,
D: WriteBuf<T, D, S>,
pub fn write(&mut self, data: &[T])where T: Clone, D: WriteBuf<T, D, S>,
Writes a slice to the Buffer. With a CPU buffer, the slice is just copied to the slice of the buffer.
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of elements contained in Buffer.
Example
use custos::{CPU, Buffer};
let device = CPU::new();
let a = Buffer::<i32, _>::new(&device, 10);
assert_eq!(a.len(), 10)sourcepub unsafe fn shallow(&self) -> Buffer<'a, T, D, S>where
<D as Device>::Ptr<T, S>: ShallowCopy,
pub unsafe fn shallow(&self) -> Buffer<'a, T, D, S>where <D as Device>::Ptr<T, S>: ShallowCopy,
Creates a shallow copy of &self.
Safety
Itself, this function does not need to be unsafe.
However, declaring this function as unsafe highlights the violation of creating two or more owners for one resource.
Furthermore, the resulting Buffer can outlive self.
sourcepub unsafe fn shallow_or_clone(&self) -> Buffer<'a, T, D, S>where
<D as Device>::Ptr<T, S>: ShallowCopy,
T: Clone,
D: CloneBuf<'a, T, S>,
pub unsafe fn shallow_or_clone(&self) -> Buffer<'a, T, D, S>where <D as Device>::Ptr<T, S>: ShallowCopy, T: Clone, D: CloneBuf<'a, T, S>,
Returns a shallow copy of &self, if the realloc feature is deactivated.
If the realloc feature is activated, it returns a deep copy / clone.
Safety
Itself, this function does not need to be unsafe.
However, declaring this function as unsafe highlights the violation of possibly creating two or more owners for one resource.
Furthermore, the resulting Buffer can outlive self.
pub fn id(&self) -> Ident
source§impl<'a, T, D, S> Buffer<'a, T, D, S>where
D: IsShapeIndep,
S: Shape,
impl<'a, T, D, S> Buffer<'a, T, D, S>where D: IsShapeIndep, S: Shape,
source§impl<'a, T, D, S> Buffer<'a, T, D, S>where
D: Device,
S: Shape,
<D as Device>::Ptr<T, S>: CommonPtrs<T>,
impl<'a, T, D, S> Buffer<'a, T, D, S>where D: Device, S: Shape, <D as Device>::Ptr<T, S>: CommonPtrs<T>,
source§impl<'a, T> Buffer<'a, T, CPU, ()>
impl<'a, T> Buffer<'a, T, CPU, ()>
sourcepub unsafe fn from_raw_host(ptr: *mut T, len: usize) -> Buffer<'a, T, CPU, ()>
pub unsafe fn from_raw_host(ptr: *mut T, len: usize) -> Buffer<'a, T, CPU, ()>
Constructs a deviceless Buffer out of a host pointer and a length.
Example
use custos::{Buffer, Alloc, CPU, Read, flag::AllocFlag};
use std::ffi::c_void;
let device = CPU::new();
let mut ptr = Alloc::<f32>::alloc(&device, 10, AllocFlag::None);
let mut buf = unsafe {
Buffer::from_raw_host(ptr.ptr, 10)
};
for (idx, value) in buf.iter_mut().enumerate() {
*value += idx as f32;
}
assert_eq!(buf.as_slice(), &[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.,]);
Safety
The pointer must be valid.
The Buffer does not manage deallocation of the allocated memory.
sourcepub unsafe fn from_raw_host_device(
device: &'a CPU,
ptr: *mut T,
len: usize
) -> Buffer<'a, T, CPU, ()>
pub unsafe fn from_raw_host_device( device: &'a CPU, ptr: *mut T, len: usize ) -> Buffer<'a, T, CPU, ()>
Constructs a Buffer out of a host pointer and a length.
The provided device can be used to shorten operation calls.
Safety
The pointer must be valid.
The Buffer does not manage deallocation of the allocated memory.
source§impl<'a, T, D, S> Buffer<'a, T, D, S>where
D: MainMemory,
S: Shape,
impl<'a, T, D, S> Buffer<'a, T, D, S>where D: MainMemory, S: Shape,
source§impl<'a, T, D, S> Buffer<'a, T, D, S>where
D: MainMemory,
S: Shape,
<D as Device>::Ptr<T, S>: CommonPtrs<T>,
impl<'a, T, D, S> Buffer<'a, T, D, S>where D: MainMemory, S: Shape, <D as Device>::Ptr<T, S>: CommonPtrs<T>,
source§impl<'a, T> Buffer<'a, T, CPU, ()>where
T: Clone,
impl<'a, T> Buffer<'a, T, CPU, ()>where T: Clone,
sourcepub fn to_dev<D>(self) -> Buffer<'static, T, D, ()>where
D: StaticGPU + Alloc<'static, T, ()> + IsShapeIndep,
<D as Device>::Ptr<T, ()>: Default,
pub fn to_dev<D>(self) -> Buffer<'static, T, D, ()>where D: StaticGPU + Alloc<'static, T, ()> + IsShapeIndep, <D as Device>::Ptr<T, ()>: Default,
Moves the buffer Buffer to a static device.
This device is chosen via the type parameter D -> [OpenCL], [CUDA].
It is recommended to use the to_gpu() method of Buffer.
Example
use custos::prelude::*;
let cpu_buffer = Buffer::from(&[1., 2., 3.]);
let cl_buf = cpu_buffer.to_dev::<OpenCL>();
assert_eq!(cl_buf.read(), vec![1., 2., 3.]);sourcepub fn to_gpu(self) -> Buffer<'a, T, CUDA, ()>
pub fn to_gpu(self) -> Buffer<'a, T, CUDA, ()>
Converts a Buffer to a CUDA device buffer.
This method depends on the feature configuration.
If the ‘cuda’ feature is disabled, this function will return an OpenCL device buffer.
Example
use custos::prelude::*;
let cpu_buf = Buffer::from(&[4., 3., 5.]);
let cuda_buf = cpu_buf.to_gpu();
assert_eq!(cuda_buf.read(), vec![4., 3., 5.]);Trait Implementations§
source§impl<'a, T> AsCudaCvoidPtr for &Buffer<'a, T, CUDA, ()>
impl<'a, T> AsCudaCvoidPtr for &Buffer<'a, T, CUDA, ()>
fn as_cvoid_ptr(&self) -> *mut c_void
source§impl<'a, T> AsCudaCvoidPtr for Buffer<'a, T, CUDA, ()>
impl<'a, T> AsCudaCvoidPtr for Buffer<'a, T, CUDA, ()>
fn as_cvoid_ptr(&self) -> *mut c_void
source§impl<'a, T, D, S> Clone for Buffer<'a, T, D, S>where
T: Clone,
D: CloneBuf<'a, T, S> + Device,
S: Shape,
impl<'a, T, D, S> Clone for Buffer<'a, T, D, S>where T: Clone, D: CloneBuf<'a, T, S> + Device, S: Shape,
source§impl<'a, T, D> Debug for Buffer<'a, T, D, ()>where
T: Debug + Default + Clone + 'a,
D: Read<T, D, ()> + Device + 'a,
<D as Read<T, D, ()>>::Read<'b>: for<'b> Debug,
<D as Device>::Ptr<T, ()>: CommonPtrs<T>,
impl<'a, T, D> Debug for Buffer<'a, T, D, ()>where T: Debug + Default + Clone + 'a, D: Read<T, D, ()> + Device + 'a, <D as Read<T, D, ()>>::Read<'b>: for<'b> Debug, <D as Device>::Ptr<T, ()>: CommonPtrs<T>,
source§impl<'a, T, D, S> Default for Buffer<'a, T, D, S>where
D: Device,
S: Shape,
<D as Device>::Ptr<T, S>: Default,
impl<'a, T, D, S> Default for Buffer<'a, T, D, S>where D: Device, S: Shape, <D as Device>::Ptr<T, S>: Default,
source§impl<T, D, S> Deref for Buffer<'_, T, D, S>where
D: MainMemory,
S: Shape,
impl<T, D, S> Deref for Buffer<'_, T, D, S>where D: MainMemory, S: Shape,
A Buffer dereferences into a slice.
Examples
use custos::{Buffer, CPU};
let device = CPU::new();
let a = Buffer::from((&device, [1., 2., 3., 4.,]));
let b = Buffer::from((&device, [2., 3., 4., 5.,]));
let mut c = Buffer::from((&device, [0.; 4]));
let slice_add = |a: &[f64], b: &[f64], c: &mut [f64]| {
for i in 0..c.len() {
c[i] = a[i] + b[i];
}
};
slice_add(&a, &b, &mut c);
assert_eq!(c.as_slice(), &[3., 5., 7., 9.,]);source§impl<T, D, S> DerefMut for Buffer<'_, T, D, S>where
D: MainMemory,
S: Shape,
impl<T, D, S> DerefMut for Buffer<'_, T, D, S>where D: MainMemory, S: Shape,
A Buffer dereferences into a slice.
Examples
use custos::{Buffer, CPU};
let device = CPU::new();
let a = Buffer::from((&device, [4., 2., 3., 4.,]));
let b = Buffer::from((&device, [2., 3., 6., 5.,]));
let mut c = Buffer::from((&device, [0.; 4]));
let slice_add = |a: &[f64], b: &[f64], c: &mut [f64]| {
for i in 0..c.len() {
c[i] = a[i] + b[i];
}
};
slice_add(&a, &b, &mut c);
assert_eq!(c.as_slice(), &[6., 5., 9., 9.,]);