Skip to main content

TrackedCudaSlice

Struct TrackedCudaSlice 

Source
pub struct TrackedCudaSlice<T: DeviceRepr> { /* private fields */ }
Expand description

A CudaSlice that automatically updates GpuMemoryManager allocation tracking on drop. Inner slice is wrapped in ManuallyDrop so the [Backing] enum can choose between cudarc-side free (legacy) and runtime-side deallocate (migrated) without producing a double-free.

Implementations§

Source§

impl<T: DeviceRepr> TrackedCudaSlice<T>

Source

pub fn device_ptr(&self) -> &CUdeviceptr

Source

pub fn device_ptr_value(&self) -> CUdeviceptr

Source

pub fn memory_manager_ptr_value(&self) -> usize

Stable address of the memory manager that owns this allocation.

Source

pub fn runtime_block(&self) -> Option<&DeviceBlock>

Borrow the underlying DeviceBlock for runtime-backed allocations. Returns None for legacy cudarc-backed slices ([Backing::Cudarc]) — those are not tracked by the v0.6 device runtime and therefore have no runtime-side block to record uses against.

Callers (notably crate::launch::LaunchRecorder) use this to attach cross-stream uses via crate::device_runtime::XlogDeviceRuntime::record_block_use. A None return signals that the slice is on the legacy path and the recorder cannot track its lifetime — callers must either route the allocation through GpuMemoryManager::with_runtime or accept that no cross-stream safety applies to this buffer.

Source

pub fn into_bytes(self) -> TrackedCudaSlice<u8>

Reinterpret this typed allocation as a raw byte allocation.

This is a zero-copy conversion used by XLOG’s columnar CudaBuffer representation, which stores device memory as untyped bytes + a schema. The conversion preserves the underlying [Backing] — runtime-routed slices remain runtime-routed, legacy cudarc slices remain cudarc-routed — so deallocation continues to match the original allocator.

Methods from Deref<Target = CudaSlice<T>>§

pub fn len(&self) -> usize

The number of elements of T in this object.

pub fn num_bytes(&self) -> usize

The number of bytes in this object.

pub fn is_empty(&self) -> bool

True if there are no elements in the object.

pub fn ordinal(&self) -> usize

The device ordinal this belongs to

pub fn context(&self) -> &Arc<CudaContext>

The context this belongs to

pub fn stream(&self) -> &Arc<CudaStream>

The stream this object was allocated on and later will be dropped on.

pub fn try_clone(&self) -> Result<CudaSlice<T>, DriverError>

Allocates copy of self and schedules a device to device copy of memory.

pub fn as_view(&self) -> CudaView<'_, T>

pub fn as_view_mut(&mut self) -> CudaViewMut<'_, T>

pub fn slice(&self, bounds: impl RangeBounds<usize>) -> CudaView<'_, T>

Creates a CudaView at the specified offset from the start of self.

Panics if range.start >= self.len.

§Example
let mut slice = stream.alloc_zeros::<u8>(100).unwrap();
let mut view = slice.slice(0..50);
do_something(&view);

Like a normal slice, borrow checking prevents the underlying CudaSlice from being dropped.

let view = {
    let mut slice = stream.alloc_zeros::<u8>(100).unwrap();
    // cannot return view, since it borrows from slice
    slice.slice(0..50)
};
do_something(&view);

pub fn try_slice( &self, bounds: impl RangeBounds<usize>, ) -> Option<CudaView<'_, T>>

Fallible version of CudaSlice::slice().

pub fn slice_mut( &mut self, bounds: impl RangeBounds<usize>, ) -> CudaViewMut<'_, T>

Creates a CudaViewMut at the specified offset from the start of self.

Panics if range and 0...self.len() are not overlapping.

§Example
let mut slice = stream.alloc_zeros::<u8>(100).unwrap();
let mut view = slice.slice_mut(0..50);
do_something(&mut view);

Like a normal mutable slice, borrow checking prevents the underlying CudaSlice from being dropped.

let mut view = {
    let mut slice = stream.alloc_zeros::<u8>(100).unwrap();
    // cannot return view, since it borrows from slice
    slice.slice_mut(0..50)
};
do_something(&mut view);

Like with normal mutable slices, one cannot mutably slice twice into the same CudaSlice:

let mut slice = stream.alloc_zeros::<u8>(100).unwrap();
let mut view1 = slice.slice_mut(0..50);
// cannot borrow twice from slice
let mut view2 = slice.slice_mut(50..100);
do_something(view1, view2);

If you need non-overlapping mutable views into a CudaSlice, you can use CudaSlice::split_at_mut().

pub fn try_slice_mut( &mut self, bounds: impl RangeBounds<usize>, ) -> Option<CudaViewMut<'_, T>>

Fallible version of CudaSlice::slice_mut

pub unsafe fn transmute<S>(&self, len: usize) -> Option<CudaView<'_, S>>

Reinterprets the slice of memory into a different type. len is the number of elements of the new type S that are expected. If not enough bytes are allocated in self for the view, then this returns None.

§Safety

This is unsafe because not the memory for the view may not be a valid interpretation for the type S.

pub unsafe fn transmute_mut<S>( &mut self, len: usize, ) -> Option<CudaViewMut<'_, S>>

Reinterprets the slice of memory into a different type. len is the number of elements of the new type S that are expected. If not enough bytes are allocated in self for the view, then this returns None.

§Safety

This is unsafe because not the memory for the view may not be a valid interpretation for the type S.

pub fn split_at(&self, mid: usize) -> (CudaView<'_, T>, CudaView<'_, T>)

pub fn try_split_at( &self, mid: usize, ) -> Option<(CudaView<'_, T>, CudaView<'_, T>)>

Fallible version of CudaSlice::split_at. Returns None if mid > self.len.

pub fn split_at_mut( &mut self, mid: usize, ) -> (CudaViewMut<'_, T>, CudaViewMut<'_, T>)

Splits the CudaSlice into two at the given index, returning two CudaViewMut for the two halves.

Panics if mid > self.len.

This method can be used to create non-overlapping mutable views into a CudaSlice.

let mut slice = stream.alloc_zeros::<u8>(100).unwrap();
// split the slice into two non-overlapping, mutable views
let (mut view1, mut view2) = slice.split_at_mut(50);
do_something(view1, view2);

pub fn try_split_at_mut( &mut self, mid: usize, ) -> Option<(CudaViewMut<'_, T>, CudaViewMut<'_, T>)>

Fallible version of CudaSlice::split_at_mut.

Returns None if mid > self.len.

Trait Implementations§

Source§

impl<T: DeviceRepr> AsKernelParam for &TrackedCudaSlice<T>

Source§

impl<T: DeviceRepr> AsKernelParam for &mut TrackedCudaSlice<T>

Source§

impl<T: DeviceRepr> Deref for TrackedCudaSlice<T>

Source§

type Target = CudaSlice<T>

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl<T: DeviceRepr> DerefMut for TrackedCudaSlice<T>

Source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
Source§

impl<T: DeviceRepr> DevicePtr<T> for TrackedCudaSlice<T>

Source§

fn device_ptr<'a>( &'a self, stream: &'a CudaStream, ) -> (CUdeviceptr, SyncOnDrop<'a>)

Retrieve the device pointer with the intent to read the device memory associated with it. Read more
Source§

impl<T: DeviceRepr> DevicePtrMut<T> for TrackedCudaSlice<T>

Source§

fn device_ptr_mut<'a>( &'a mut self, stream: &'a CudaStream, ) -> (CUdeviceptr, SyncOnDrop<'a>)

Retrieve the device pointer with the intent to modify the device memory associated with it. Read more
Source§

impl<T: DeviceRepr> DeviceSlice<T> for TrackedCudaSlice<T>

Source§

fn len(&self) -> usize

Source§

fn stream(&self) -> &Arc<CudaStream>

§

fn num_bytes(&self) -> usize

§

fn is_empty(&self) -> bool

Source§

impl<T: DeviceRepr> Drop for TrackedCudaSlice<T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl From<TrackedCudaSlice<u8>> for CudaColumn

Source§

fn from(value: TrackedCudaSlice<u8>) -> Self

Converts to this type from the input type.
Source§

impl<'a, T: DeviceRepr> IntoKernelParamStorage for &'a TrackedCudaSlice<T>

Source§

impl<T: DeviceRepr> IntoKernelParamStorage for &mut TrackedCudaSlice<T>

Auto Trait Implementations§

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, 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<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
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.
§

impl<T> Allocation for T
where T: RefUnwindSafe + Send + Sync,