Module Spoc_core.Device

type t = Spoc_framework.Device_type.t = {
  1. id : int;
  2. backend_id : int;
  3. name : string;
  4. framework : string;
  5. capabilities : Spoc_framework.Framework_sig.capabilities;
}

Device type from SDK

val devices : t array Stdlib.ref

Device initialization state

val initialized : bool Stdlib.ref
val resolve_framework : string -> string list

Resolve a requested framework name to registered backend names. An exact name matches itself; a family name ("CUDA") matches every backend registered as "<family>/<variant>" ("CUDA/PTX", "CUDA/C"), highest priority first. Keeps callers written against the historical family names working after the plugin split.

val init : ?frameworks:string list -> unit -> t array

Initialize all available backends and enumerate devices

val all : unit -> t array

Get all initialized devices

val count : unit -> int

Get device count

val get : int -> t option

Get device by global ID

val first : unit -> t option

Get first available device (if any)

val by_framework : string -> t array

Filter devices by framework

val with_fp64 : unit -> t array

Filter devices by capability

val is_cuda_framework : string -> bool

CUDA backends register as "CUDA/PTX" and "CUDA/C"; match the family name or its slash-separated variants (not arbitrary "CUDA*" names).

val best : unit -> t option

Get the best device (first CUDA, then OpenCL, then Native)

val reset : unit -> unit

Reset initialization state (for testing).

Retires the global id space, so every cache keyed on it must be dropped in the same breath. init restarts global_id at 0 over whichever frameworks it is handed, so the same id routinely denotes a DIFFERENT physical device after a reset: with ~frameworks:["OpenCL"] then ~frameworks:["Native"; "OpenCL"], the single Native device shifts OpenCL down one and id 1 moves from the second OpenCL device to the first. A surviving entry keyed on id 1 is then served to the wrong device, silently — a compiled kernel carries no device check — which is exactly the aliasing class this cache was keyed by device to prevent.

Only Sarek.Runtime's outer memo is affected: it keys on the global Device.t.id, while every per-backend cache keys on its own backend-local device index, which a reset does not perturb. So the notification here is enough, and it releases nothing — the listeners drop memoization only (see Spoc_framework.Cache_hooks), so unlike Kernel.clear_cache this cannot invalidate a handle a caller still holds.

val to_string : t -> string

Pretty-print device info

val print_all : unit -> unit

Print all devices

Phase 4: Extended Device Queries

Type Predicates

val is_cuda : t -> bool
val is_opencl : t -> bool
val is_native : t -> bool
val is_cpu : t -> bool
val is_gpu : t -> bool

Capability Queries

val provides : t -> Sarek_ir_analysis.feature -> bool
val allows_fp64 : t -> bool
val allows_int64 : t -> bool
val allows_fp16 : t -> bool
val supports_atomics : t -> bool
val compute_capability : t -> int * int
val warp_size : t -> int
val max_threads_per_block : t -> int
val max_block_dims : t -> int * int * int
val max_grid_dims : t -> int * int * int
val shared_mem_per_block : t -> int
val total_memory : t -> int64
val multiprocessor_count : t -> int
val clock_rate_khz : t -> int
val max_registers_per_block : t -> int

Finders

val find_cuda : t array -> t option
val find_opencl : t array -> t option
val find_native : t array -> t option
val find_by_name : t array -> string -> t option
val find_by_id : t array -> int -> t option

Filters

val filter_cuda : unit -> t array
val filter_opencl : unit -> t array
val filter_native : unit -> t array
val with_atomics : unit -> t array
val with_min_memory : int64 -> t array
val with_compute_capability : major:int -> minor:int -> t array

Runtime Memory Query

val free_memory : t -> int64 option

Query current free memory on device (if supported by backend)

Synchronization

val synchronize : t -> unit
val set_current : t -> unit