#[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
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.
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
impl TensorMemory
Sourcepub const fn code(self) -> u32
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.
Sourcepub fn from_code(code: u32) -> Option<Self>
pub fn from_code(code: u32) -> Option<Self>
Reject an unknown code rather than guessing at one.
Sourcepub fn from_str_code(s: &str) -> Option<Self>
pub fn from_str_code(s: &str) -> Option<Self>
Reject an unknown string rather than guessing at one.
Source§impl TensorMemory
impl TensorMemory
Sourcepub fn is_available(self) -> bool
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 theDmaBufspelling, soDmaBufis the variant that answerstruethere.Pbo– PBO tensors are created byImageProcessor::create_imagewith a GL context current, never byTensor::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 forlibcudawould answertrueon a Jetson while every allocation still failed, which is worse than answeringfalse.
Trait Implementations§
Source§impl Clone for TensorMemory
impl Clone for TensorMemory
Source§fn clone(&self) -> TensorMemory
fn clone(&self) -> TensorMemory
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for TensorMemory
Source§impl Debug for TensorMemory
impl Debug for TensorMemory
impl Eq for TensorMemory
Source§impl From<TensorMemory> for String
impl From<TensorMemory> for String
Source§fn from(memory: TensorMemory) -> Self
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
impl Hash for TensorMemory
Source§impl PartialEq for TensorMemory
impl PartialEq for TensorMemory
impl StructuralPartialEq for TensorMemory
Auto Trait Implementations§
impl Freeze for TensorMemory
impl RefUnwindSafe for TensorMemory
impl Send for TensorMemory
impl Sync for TensorMemory
impl Unpin for TensorMemory
impl UnsafeUnpin for TensorMemory
impl UnwindSafe for TensorMemory
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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