use numkong::UnifiedAllocator;use numkong::Global;use numkong::tensor::*;8.0.0-rc.1 · b1f866ab
Views wrap raw pointers without ownership, owned containers accept custom allocators, and the scalar trait API works on any &[T] regardless of how the memory was allocated.
VectorView::from_raw_parts and TensorView::from_raw_parts wrap device-accessible or externally allocated memory.
The mutable counterparts VectorSpan::from_raw_parts and TensorSpan::from_raw_parts work the same way with *mut T.
Owned containers accept any core::alloc::Allocator.
A CUDA unified memory allocator looks like this:
use core::alloc::{AllocError, Allocator, Layout};use core::ptr::NonNull;use numkong::Vector;struct CudaAllocator;unsafe impl Allocator for CudaAllocator { fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { let raw = unsafe { cuda_malloc_managed(layout.size()) }; let base = NonNull::new(raw).ok_or(AllocError)?; Ok(NonNull::slice_from_raw_parts(base, layout.size())) } unsafe fn deallocate(&self, block: NonNull<u8>, _layout: Layout) { cuda_free(block.as_ptr()); }}let queries = Vector::<f32, CudaAllocator>::zeros_in(1024, CudaAllocator).unwrap();
core also implements the trait for &A, so an allocator that is not Clone — a bump arena holding a cursor, say — goes in by reference and the container borrows it:
The trait-based scalar API works on any &[T] — Vec, mmap, arena, or pinned buffer:
use numkong::Dot;let weights: &[f32] = /* any contiguous slice */;let similarity = f32::dot(weights, weights).unwrap();
API
StructUnifiedAllocatorMemory the host and the devices of one capability group both address, for the packs and outputs of their verbs: managed memory on CUDA and ROCm, a shared buffer on Metal, and the heap on the CPU.2
The Allocator trait itself is core's, so an arena, a pool, or a pinned-memory allocator
written against it — including by reference, through impl Allocator for &A — drops into
Tensor and the packed containers with no adapter. This type only names the default, and
stays separate from alloc::alloc::Global so the heapless build still has one.
Without the alloc feature there is no heap to forward to and every request fails. That is a
supported configuration rather than a broken one: the borrowed API — the scalar traits over
&[T], the *_into verbs writing into caller-provided spans, and the from_raw_parts views —
never allocates, so only the owning containers become unusable.
Implements
Debug, Clone, Copy, Default, Allocator
Constants
DEFAULT_ALIGNMENTByte boundary every owned allocation and pack starts on, the C library's NUMKONG_DEFAULT_ALIGNMENT for the same target.