Skip to main content

TensorMemory

Enum TensorMemory 

Source
#[non_exhaustive]
#[repr(u32)]
pub enum TensorMemory { Mem = 0, Shm = 1, DmaBuf = 2, IoSurface = 3, Pbo = 4, Cuda = 5, }
Expand description

Which memory backend a tensor is (or should be) allocated from.

Pass Some(..) to a constructor to pin the backend, or None to auto-select. Auto-selection differs by constructor: Tensor::new tries DmaBuf → Mem, while the image constructors try DmaBuf → Mem and skip Shm. EDGEFIRST_TENSOR_FORCE_MEM=1 short-circuits either chain to Mem, which is how tests run on hosts without DMA-heap permissions.

A pinned request has no fallback: if the backend cannot serve it, the constructor fails rather than quietly giving you something slower. TensorTrait::memory reports what a tensor actually ended up with.

§Every variant exists on every platform

This is a namespace of codes, not a list of what this build can allocate – TensorMemory::is_available answers the latter, at runtime. Shm used to be #[cfg(unix)], which shifted every variant declared after it on a non-unix build and made the numbering a compile-time detail of the host. It also made a cross-platform recording unreadable: a blob captured on Linux carries "dmabuf", and a macOS consumer has to be able to NAME that backing in order to report “cannot materialise here” instead of failing with an unrecognised code.

§#[non_exhaustive]

Match this with a wildcard arm. The variant list is expected to keep growing – IoSurface and Cuda were added here, Windows backings and a real CUDA device backing are named as coming – and this attribute is what keeps a closed-source consumer’s match memory { .. } compiling across those additions. It protects DOWNSTREAM, not this crate: inside edgefirst-tensor the matches stay exhaustive and compile-enforced. Same rule as DType, Compression and PixelFormat, which TensorMemory was the lone exception to.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Mem = 0

Regular system memory allocation. Available everywhere; the floor every auto-selection chain ends on.

§

Shm = 1

POSIX Shared Memory allocation. Suitable for inter-process communication, but not for hardware acceleration. Only allocatable on unix; nameable everywhere.

§

DmaBuf = 2

Platform-native zero-copy GPU buffer.

On Linux this is a DMA-BUF (DmaTensor in crates/tensor/src/dma.rs) allocated via the DRM/dma-heap subsystem. On macOS/iOS it is currently also this variant that yields an IOSurface, and on Android an AHardwareBuffer: they share the TensorStorage::Dma slot at the trait level, and the public C API discriminant (HAL_TENSOR_MEMORY_DMA = 1) covers all three with no ABI break. IoSurface below is the code for naming that backing specifically; no backend reports it yet.

Allows hardware-accelerated paths (OpenGL backend on Linux via EGL_EXT_image_dma_buf_import; macOS via EGL_ANGLE_iosurface_client_buffer). CPU access via map() incurs cache-coherency overhead on Linux DMA-BUF and is similar in cost on IOSurface; SHM/Mem are cheaper for CPU-only workloads.

On Windows it is an ID3D11Texture2D on the process D3D11 device (crates/tensor/src/d3d11/), allocated only through Tensor::image; CPU access goes through a staging copy. The first such allocation creates the process device, so a host supplying its own device must call d3d11::use_external_device before it – and before crate::is_gpu_buffer_available, which creates the device too.

§

IoSurface = 3

Apple IOSurface, named specifically rather than through the portable DmaBuf spelling.

Defined as a code so a descriptor or recording that names an IOSurface is parseable on every platform. No backend produces or accepts it yet – macOS/iOS allocate and report DmaBuf. Pinning a request to it fails with NotImplemented.

§

Pbo = 4

OpenGL Pixel Buffer Object memory. Created by ImageProcessor when DMA-buf is unavailable but OpenGL is present – never by Tensor::new, which has no GL context to create it in.

§

Cuda = 5

CUDA device memory: a device pointer, not host-addressable.

Defined as a code for the same reason as IoSurface. No backend produces or accepts it yet; pinning a request to it fails with NotImplemented.

Implementations§

Source§

impl TensorMemory

Source

pub const fn code(self) -> u32

The shared code for this variant. Identical on every surface.

const, deliberately: a downstream binding that cannot write Variant = OtherEnum::Variant.code() in a #[pyclass] discriminant position (PyO3 requires a literal there) can still pin that literal to this value with a const _: () = assert!(...) – a build-time check instead of a hand-synced comment. See PyTensorMemory/PyPixelFormat in crates/python-common/src/tensor.rs for the consumer.

Source

pub fn from_code(code: u32) -> Option<Self>

Reject an unknown code rather than guessing at one.

Source

pub fn as_str(self) -> &'static str

The wire string form – stable, unlike Debug.

Source

pub fn from_str_code(s: &str) -> Option<Self>

Reject an unknown string rather than guessing at one.

Source

pub fn all() -> &'static [Self]

Every variant, for exhaustive cross-surface tests.

Source§

impl TensorMemory

Source

pub fn is_available(self) -> bool

Whether this backing can actually be allocated in this process, now.

A runtime question, not a compile-time one, which is why it is a method on the vocabulary rather than a cfg on the variant: DmaBuf needs /dev/dma_heap to exist and this process to have permission on it (a container, a user outside the video/render groups, and a stock desktop give three different answers on the same kernel), and Shm needs a writable /dev/shm. Each probe allocates once and caches.

Reports what can be allocated, which is not the same as what can be named: every variant is nameable on every platform (that is the point of the vocabulary), and the ones this build cannot serve say so here rather than by being absent from the enum.

Three variants answer false unconditionally today, for reasons worth stating rather than hiding behind a probe that cannot fail:

  • IoSurface – no backend produces or accepts it yet; macOS/iOS serve IOSurface under the DmaBuf spelling, so DmaBuf is the variant that answers true there.
  • Pbo – PBO tensors are created by ImageProcessor::create_image with a GL context current, never by Tensor::new. This crate holds no GL context and cannot see one; ask the image crate whether a GL backend is live.
  • Cuda – there is no CUDA backing in this crate at all. Probing for libcuda would answer true on a Jetson while every allocation still failed, which is worse than answering false.

One variant answers true for a narrower constructor than the rest: on Windows DmaBuf is an ID3D11Texture2D, which is image-formatted, so true there means Tensor::image can serve it and Tensor::new with Some(DmaBuf) still answers NotImplemented. is_gpu_buffer_available, which this forwards to, states the same split.

Trait Implementations§

Source§

impl Clone for TensorMemory

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for TensorMemory

Source§

impl Debug for TensorMemory

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for TensorMemory

Source§

impl From<TensorMemory> for String

Source§

fn from(memory: TensorMemory) -> Self

The wire string, via TensorMemory::as_str – one spelling, not a second one maintained alongside it.

DmaBuf renders as "dmabuf", not the "dma" this impl used to emit. TryFrom<&str> still accepts "dma" so anything that persisted the old spelling keeps parsing; the benchmark result keys in .github/scripts spell it "dma" but build that string themselves and never went through this impl.

Source§

impl Hash for TensorMemory

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for TensorMemory

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for TensorMemory

Source§

impl TryFrom<&str> for TensorMemory

Source§

fn try_from(s: &str) -> Result<Self>

Parses TensorMemory::as_str’s spelling, plus the legacy "dma" alias for DmaBuf.

Source§

type Error = Error

The type returned in the event of a conversion error.

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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