Advanced.PinnedPage-locked host memory, explicit and opt-in: nothing in SPOC pins memory unless you call this module. A thin owner-handle over Transfer.alloc_pinned and Transfer.register_host, which hold the mechanics (per-backend behaviour, measured pitfalls on HIP, the in-flight copy check).
The memory is a Bigarray, not a Vector.t: a vector's host mirror is garbage collected, pinned memory is released only explicitly (sub-arrays could outlive a finaliser's decision). Use it as the host side of Transfer.copy_to_device / Transfer.copy_to_host with ~stream, or as the destination of pread/O_DIRECT reads.
Release a handle only through Pinned.release: freeing or unregistering its array directly with Transfer leaves the handle believing it is live, and a later Pinned.release could then act on a different allocation at the same address.
A live-or-released pinned buffer. Abstract: its state changes only through release.
val is_available : Device.t -> booltrue iff dev's backend supports page-locked memory. Probes with a one-byte alloc and release, which costs a driver allocation and free per call on GPU backends and flushes pending deferred launches (the free does). Native, Interpreter and Metal answer true (their pinned memory is plain host memory). Only the backend's Feature_not_supported refusal means false; any other error (driver out-of-memory, unknown framework) propagates.
Allocate n elements of page-locked memory for DMA with the device. Raises Invalid_argument for n < 1 or Bigarray.float16 (use a char buffer and Transfer.copy_bytes_to_device), and the backend's Feature_not_supported where unsupported (see is_available). On HIP the allocation can be slow for multi-GiB sizes: measure, or use register.
val register :
Device.t ->
('a, 'b, Stdlib.Bigarray.c_layout) Stdlib.Bigarray.Array1.t ->
('a, 'b) tPage-lock an array you already own. The array stays yours and usable after release; the handle roots it until then. Raises Invalid_argument if it is empty or already pinned or registered, and Feature_not_supported where the backend cannot register host memory. See Transfer.register_host for the measured pitfalls (copies right after registering, registrations spanning two regions).
val is_live : ('a, 'b) t -> boolval bigarray :
('a, 'b) t ->
('a, 'b, Stdlib.Bigarray.c_layout) Stdlib.Bigarray.Array1.tval release : ('a, 'b) t -> unitval with_alloc :
?stream:Transfer.stream ->
Device.t ->
('a, 'b) Stdlib.Bigarray.kind ->
int ->
(('a, 'b) t -> 'r) ->
'rwith_alloc ?stream dev kind n f runs f on a fresh alloc, then synchronizes stream (if given) and releases the handle. If f raises, its exception is re-raised after a best-effort release. f must not let the array escape. Stream-ordered copies f enqueued must be on stream, or synchronized by f: otherwise the release is refused, the refusal (Invalid_argument) is raised when f returned normally, and the handle is unreachable, so the allocation stays pinned for the process lifetime.