Module Spoc_core.Kernel

Kernel Module Type

module type KERNEL = sig ... end

A compiled kernel packages backend-specific kernel with its operations

type t =
  1. | Kernel : (module KERNEL) -> t

Args Module Type

module type ARGS = sig ... end

Kernel arguments builder packages backend-specific args with setters

type args =
  1. | Args : (module ARGS) -> args

Compilation

val compile : Device.t -> name:string -> source:string -> t

Compile a kernel from source

val compile_cached : Device.t -> name:string -> source:string -> t

Compile with caching

Arguments

val create_args : Device.t -> args

Create an arguments object

val set_arg_buffer : args -> int -> 'a Memory.buffer -> unit

Set buffer argument

val set_arg_int32 : args -> int -> int32 -> unit

Set int32 argument

val set_arg_int64 : args -> int -> int64 -> unit

Set int64 argument

val set_arg_float32 : args -> int -> float -> unit

Set float32 argument

val set_arg_float64 : args -> int -> float -> unit

Set float64 argument

val set_arg_ptr : args -> int -> nativeint -> unit

Set raw device pointer argument (CUDA only)

Execution

val launch : t -> args:args -> grid:Spoc_framework.Framework_sig.dims -> block:Spoc_framework.Framework_sig.dims -> ?shared_mem:int -> unit -> unit

Launch a kernel

Cache Management

val clear_cache : Device.t -> unit

Clear all kernel caches.

The layers ABOVE this one are dropped first: B.Kernel.clear_cache releases the backend handles (clReleaseKernel / cuModuleUnload / ...), and any outer memo — notably Runtime.kernel_cache — holds Kernel.t closures over exactly those handles. Leaving them in place means the next lookup hits the outer memo and launches through a released handle (segfault).

The notification is fired on BOTH sides of the backend clear, and both are load-bearing — see Spoc_framework.Cache_hooks.around_clear, which owns that discipline and the listener-isolation that goes with it.

B.Kernel.clear_cache is itself wrapped in around_clear, so a caller that resolves the backend through Framework_registry and calls it directly is equally covered; around_clear collapses the nesting so this path still notifies exactly twice. The wrapper here is not therefore redundant: it is what covers the None branch, where no backend resolves and there is no inner around_clear to fire. The outer memos are cross-backend, so they must be dropped even when the framework name resolves to nothing.

Accessors

val device : t -> Device.t

Get kernel device

val name : t -> string

Get kernel name

val args_device : args -> Device.t

Get args device

Get wrapped kargs for direct backend use