Sarek_cuda.Cuda_apiexception Cuda_error of Cuda_types.cu_result * stringDeprecated: no longer raised. check below now raises the canonical Cuda_error.Cuda_error (a Backend_error alias) via the shared Sarek_backend_error.Backend_error.Make.check funnel, so every handler in the codebase can catch one exception shape across backends. This declaration is kept only so that out-of-tree code matching on Cuda_api.Cuda_error (code, ctx) still compiles (this library is opam-published).
val check : string -> Cuda_types.cu_result -> unitCheck CUDA result and raise a canonical Backend_error on failure.
One launch's argument blocks: slots holds the argument values, one 8-byte slot each, and params the array of pointers into it that cuLaunchKernel receives. Both are ctypes allocations owned by the GC, so they must stay reachable (see retain_kernargs) until the launch has been consumed.
val pending_kernargs : (int * nativeint * kernargs) list Stdlib.refHost-side kernel-argument buffers (the array of argument pointers plus the value slots) for launches that may still be in flight, keyed by device id.
cuLaunchKernel is asynchronous. The NVIDIA driver snapshots the kernel parameters synchronously before returning, so a caller may free them right after the call — but the ZLUDA/HIP stack reads them later, at dispatch time. Freeing them when Kernel.launch returns is therefore a use-after-free once the OCaml GC reclaims the blocks: the GPU then reads recycled host memory as the kernel's arguments (observed as an intermittent GPU page fault at a host-range address on ZLUDA).
We retain the buffers here until the stream that ran the launch is drained. Each entry is keyed by (device_id, stream_key) where stream_key is the raw address of the stream handle (0 for the default/null stream, which is what SPOC uses). The buffers are held purely for liveness and are never inspected. A mutex guards the list so launches/retires from different OCaml domains cannot lose an entry (drop = use-after-free) or a removal.
val retain_kernargs : int -> nativeint -> kernargs -> unitRelease buffers for one stream — use after draining exactly that stream (its synchronize, or a blocking op known to run on it).
Release all buffers for a device — use only after a full-context synchronize (drains every stream) or context destruction.
TEST INSTRUMENTATION: number of launches whose argument blocks are still retained for (device_id, stream_key).
Raw address of a stream handle; the default (null) stream is 0.
Key of the default/null stream (what SPOC's blocking memcpys run on).
module Device : sig ... endmodule Memory : sig ... endmodule Stream : sig ... endmodule Event : sig ... endmodule Async : sig ... endmodule Kernel : sig ... endDriver-only availability: libcuda is loadable and reports at least one device. Sufficient for the PTX backend, which never calls NVRTC — this is what makes SPOC work on non-NVIDIA CUDA implementations such as ZLUDA, which ship the driver API without libnvrtc.
val memory_info : Device.t -> int64 * int64