Module Spoc_core.Vector

include module type of struct include Vector_types end

Element Types

type (_, _) scalar_kind = (_, _) Vector_types.scalar_kind =
  1. | Float32 : (float, Stdlib.Bigarray.float32_elt) scalar_kind
  2. | Float64 : (float, Stdlib.Bigarray.float64_elt) scalar_kind
  3. | Int32 : (int32, Stdlib.Bigarray.int32_elt) scalar_kind
  4. | Int64 : (int64, Stdlib.Bigarray.int64_elt) scalar_kind
  5. | Char : (char, Stdlib.Bigarray.int8_unsigned_elt) scalar_kind
  6. | Complex32 : (Stdlib.Complex.t, Stdlib.Bigarray.complex32_elt) scalar_kind

Standard numeric kinds backed by Bigarray

type 'a custom_type = 'a Vector_types.custom_type = {
  1. elem_size : int;
    (*

    Size of each element in bytes

    *)
  2. get : unit Ctypes.ptr -> int -> 'a;
    (*

    Read element at index

    *)
  3. set : unit Ctypes.ptr -> int -> 'a -> unit;
    (*

    Write element at index

    *)
  4. name : string;
    (*

    Type name for debugging

    *)
}

Custom type descriptor for ctypes-based structures

module Custom_helpers = Vector_types.Custom_helpers

Helper functions for custom type implementations. These wrap Ctypes operations to provide simpler APIs for PPX-generated code.

type (_, _) kind = (_, _) Vector_types.kind =
  1. | Scalar : ('a, 'b) scalar_kind -> ('a, 'b) kind
  2. | Custom : 'a custom_type -> ('a, unit) kind

Unified kind type supporting both scalar and custom types

Kind Helpers

val to_bigarray_kind : 'a 'b. ('a, 'b) scalar_kind -> ('a, 'b) Stdlib.Bigarray.kind

Convert scalar kind to Bigarray.kind

val scalar_elem_size : 'a 'b. ('a, 'b) scalar_kind -> int

Element size in bytes

val elem_size : 'a 'b. ('a, 'b) kind -> int
val scalar_kind_name : 'a 'b. ('a, 'b) scalar_kind -> string

Kind name for debugging

val kind_name : 'a 'b. ('a, 'b) kind -> string

Host Storage (GADT)

type (_, _) host_storage = (_, _) Vector_types.host_storage =
  1. | Bigarray_storage : ('a, 'b, Stdlib.Bigarray.c_layout) Stdlib.Bigarray.Array1.t -> ('a, 'b) host_storage
  2. | Custom_storage : {
    1. ptr : unit Ctypes.ptr;
    2. custom : 'a custom_type;
    3. length : int;
    } -> ('a, unit) host_storage

CPU-side storage - either Bigarray or raw ctypes pointer

Location Tracking

type location = Vector_types.location =
  1. | CPU
    (*

    Data only on host

    *)
  2. | GPU of Device.t
    (*

    Data only on specific device

    *)
  3. | Both of Device.t
    (*

    Synced on host and device

    *)
  4. | Stale_CPU of Device.t
    (*

    GPU is authoritative, CPU outdated

    *)
  5. | Stale_GPU of Device.t
    (*

    CPU is authoritative, GPU outdated

    *)

Where the authoritative copy of data resides

Device Buffer Abstraction

module type DEVICE_BUFFER = Vector_types.DEVICE_BUFFER

Device buffer reuses Memory.BUFFER module type. We use the raw module type here (not the phantom-typed Memory.buffer) because the hashtable stores buffers for a single vector type, and the type safety comes from the Vector's ('a, 'b) t type parameter.

type device_buffer = (module DEVICE_BUFFER)
type device_buffers = (int, device_buffer) Stdlib.Hashtbl.t

Device buffer storage - maps device ID to buffer

Vector Type

type ('a, 'b) t = ('a, 'b) Vector_types.t = {
  1. host : ('a, 'b) host_storage;
  2. device_buffers : device_buffers;
  3. length : int;
  4. kind : ('a, 'b) kind;
  5. mutable location : location;
  6. mutable auto_sync : bool;
    (*

    Enable automatic CPU sync on get

    *)
  7. id : int;
    (*

    Unique vector ID for debugging

    *)
}

High-level vector with location tracking

val create_scalar : ('a, 'b) Vector_types.scalar_kind -> ?dev:Device.t -> int -> ('a, 'b) Vector_types.t
val create : ('a, 'b) Vector_types.kind -> ?dev:Device.t -> int -> ('a, 'b) Vector_types.t
val create_custom : 'a Vector_types.custom_type -> ?dev:Device.t -> int -> ('a, unit) Vector_types.t
val of_bigarray : ('a, 'b) Vector_types.scalar_kind -> ('a, 'b, Stdlib.Bigarray.c_layout) Stdlib.Bigarray.Array1.t -> ('a, 'b) Vector_types.t
val of_ctypes_ptr : 'a Vector_types.custom_type -> unit Ctypes.ptr -> int -> ('a, unit) Vector_types.t

Accessors

val length : ('a, 'b) t -> int
val kind : ('a, 'b) t -> ('a, 'b) kind
val location : ('a, 'b) t -> location
val id : ('a, 'b) t -> int
val device : ('a, 'b) t -> Device.t option

Get device if vector has GPU data

Raw Data Access

val to_bigarray : 'a 'b. ('a, 'b) t -> ('a, 'b, Stdlib.Bigarray.c_layout) Stdlib.Bigarray.Array1.t

Get underlying Bigarray (only for scalar vectors)

Sync and host pointer helpers (delegated)

type sync_callback = Vector_transfer.sync_callback = {
  1. sync : 'a 'b. ('a, 'b) t -> bool;
}
val to_ctypes_ptr : ('a, 'b) Vector_types.t -> unit Ctypes.ptr
val host_ptr : ('a, 'b) Vector_types.t -> nativeint
val register_sync_callback : Vector_transfer.sync_callback -> unit
val ensure_cpu_sync : ('a, 'b) Vector_types.t -> unit

Element Access

val get : 'a 'b. ('a, 'b) t -> int -> 'a

Get element (works for both storage types). Auto-syncs from GPU if location is Stale_CPU and auto_sync is enabled.

val set : 'a 'b. ('a, 'b) t -> int -> 'a -> unit

Set element (works for both storage types)

val (.%[]) : ('a, 'b) t -> int -> 'a

Indexing operators

val (.%[]<-) : ('a, 'b) t -> int -> 'a -> unit

Unsafe Access (no bounds check)

val unsafe_get : 'a 'b. ('a, 'b) t -> int -> 'a
val unsafe_set : 'a 'b. ('a, 'b) t -> int -> 'a -> unit
val kernel_set : 'a 'b. ('a, 'b) t -> int -> 'a -> unit

Kernel-safe set: no bounds check, no location update. Use this in parallel kernel execution where:

  • Bounds are guaranteed by kernel logic
  • Location tracking is not needed (data stays on same device)
  • Multiple threads may write to different indices concurrently

Auto-sync Control

val set_auto_sync : ('a, 'b) t -> bool -> unit
val auto_sync : ('a, 'b) t -> bool

Location Queries

val is_on_cpu : ('a, 'b) t -> bool
val is_on_gpu : ('a, 'b) t -> bool
val is_synced : ('a, 'b) t -> bool
val needs_gpu_update : ('a, 'b) t -> bool
val needs_cpu_update : ('a, 'b) t -> bool

Device Buffer Management

val has_buffer : ('a, 'b) Vector_types.t -> Device.t -> bool

Check if vector has buffer on specific device

val get_buffer : ('a, 'b) Vector_types.t -> Device.t -> Vector_types.device_buffer option

Get device buffer if allocated

Pretty Printing

val location_to_string : location -> string
val to_string : ('a, 'b) t -> string

Convenience Constructors for Scalar Types

val float32 : (float, Stdlib.Bigarray.float32_elt) kind
val float64 : (float, Stdlib.Bigarray.float64_elt) kind
val int32 : (int32, Stdlib.Bigarray.int32_elt) kind
val int64 : (int64, Stdlib.Bigarray.int64_elt) kind
val char : (char, Stdlib.Bigarray.int8_unsigned_elt) kind
val complex32 : (Stdlib.Complex.t, Stdlib.Bigarray.complex32_elt) kind
val create_float32 : ?dev:Device.t -> int -> (float, Stdlib.Bigarray.float32_elt) Vector_types.t
val create_float64 : ?dev:Device.t -> int -> (float, Stdlib.Bigarray.float64_elt) Vector_types.t
val create_int32 : ?dev:Device.t -> int -> (int32, Stdlib.Bigarray.int32_elt) Vector_types.t
val create_int64 : ?dev:Device.t -> int -> (int64, Stdlib.Bigarray.int64_elt) Vector_types.t

Initialization Helpers

val fill : 'a 'b. ('a, 'b) t -> 'a -> unit

Fill vector with a value

val init : 'a 'b. ('a, 'b) kind -> int -> (int -> 'a) -> ('a, 'b) t

Initialize with a function

val copy : 'a 'b. ('a, 'b) t -> ('a, 'b) t

Copy vector (CPU data only, auto-syncs source if needed)

Subvector Support

type sub_meta = Vector_storage.sub_meta
val is_sub : ('a, 'b) Vector_types.t -> bool
val get_sub_meta : ('a, 'b) Vector_types.t -> Vector_storage.sub_meta option
val sub_vector : ('a, 'b) t -> start:int -> len:int -> ?ok_range:int -> ?ko_range:int -> unit -> ('a, 'b) t

Create a subvector that shares CPU memory with parent.

  • parameter vec

    Parent vector

  • parameter start

    Starting index in parent

  • parameter len

    Length of subvector

  • parameter ok_range

    Elements safe to read (default: len)

  • parameter ko_range

    Elements to avoid writing (default: 0)

Multi-GPU Helpers

val partition : ('a, 'b) t -> Device.t array -> ('a, 'b) t array

Partition a vector across multiple devices. Creates subvectors, one per device, that together cover the full vector.

val gather : ('a, 'b) t array -> unit

Gather subvectors back to parent (sync all to CPU). Assumes subvectors were created by partition and don't overlap.

Subvector Queries

val depth : ('a, 'b) t -> int

Get subvector depth (0 = root, 1 = child, 2 = grandchild, ...)

val parent_id : ('a, 'b) t -> int option

Get parent vector ID if this is a subvector

val sub_start : ('a, 'b) t -> int option

Get start offset relative to immediate parent

val sub_ok_range : ('a, 'b) t -> int option

Get ok_range (safe read range)

val sub_ko_range : ('a, 'b) t -> int option

Get ko_range (unsafe write range)

Phase 6: Vector Utilities

Iteration

val iter : 'a 'b. ('a -> unit) -> ('a, 'b) t -> unit

Iterate over all elements (CPU-side, auto-syncs if needed)

val iteri : 'a 'b. (int -> 'a -> unit) -> ('a, 'b) t -> unit

Iterate with index

Mapping

val map : 'a 'b 'c 'd. ('a -> 'c) -> ('c, 'd) kind -> ('a, 'b) t -> ('c, 'd) t

Map function over vector, creating new vector with given kind

val mapi : 'a 'b 'c 'd. (int -> 'a -> 'c) -> ('c, 'd) kind -> ('a, 'b) t -> ('c, 'd) t

Map with index

val map_inplace : 'a 'b. ('a -> 'a) -> ('a, 'b) t -> unit

In-place map (same type)

Folding

val fold_left : 'a 'b 'acc. ('acc -> 'a -> 'acc) -> 'acc -> ('a, 'b) t -> 'acc

Fold left

val fold_right : 'a 'b 'acc. ('a -> 'acc -> 'acc) -> ('a, 'b) t -> 'acc -> 'acc

Fold right

Predicates

val for_all : 'a 'b. ('a -> bool) -> ('a, 'b) t -> bool

Check if all elements satisfy predicate

val exists : 'a 'b. ('a -> bool) -> ('a, 'b) t -> bool

Check if any element satisfies predicate

val find : 'a 'b. ('a -> bool) -> ('a, 'b) t -> 'a option

Find first element satisfying predicate

val find_index : 'a 'b. ('a -> bool) -> ('a, 'b) t -> int option

Find index of first element satisfying predicate

Aggregation

val sum : zero:'a -> add:('a -> 'a -> 'a) -> ('a, 'b) t -> 'a

Sum elements (requires + operation via fold)

val min_elt : compare:('a -> 'a -> int) -> ('a, 'b) t -> 'a option

Find minimum element

val max_elt : compare:('a -> 'a -> int) -> ('a, 'b) t -> 'a option

Find maximum element

Conversion

val to_list : 'a 'b. ('a, 'b) t -> 'a list

Convert to OCaml list

val of_list : ('a, 'b) Vector_types.kind -> 'a list -> ('a, 'b) Vector_types.t

Create from OCaml list

val to_array : 'a 'b. ('a, 'b) t -> 'a array

Convert to OCaml array

val of_array : ('a, 'b) Vector_types.kind -> 'a array -> ('a, 'b) Vector_types.t

Create from OCaml array

Blitting

val blit : 'a 'b. src:('a, 'b) t -> src_off:int -> dst:('a, 'b) t -> dst_off:int -> len:int -> unit

Copy elements from one vector to another