Cuda

Explicit CUDA device-buffer API (Driver API wrapper). Separate from ``Gpu`` — never imported by ``@gpu``. ``ReadyBuffer`` and ``Pending`` are linear: every upload, kernel, sync, download, or discard must happen exactly once. Surface ``Float`` is CUDA float64 throughout. Narrative guide: ``docs/cuda.md``. HTML reference: ``aeon --doc libraries/Cuda.ae``. ── Opaque descriptors ───────────────────────────────────────────────── CUDA device handle. Selected by index or ``default_device``.
Imports
open Array;
Table of Contents

Types

Device

(type)
CUDA device handle. Selected by index or ``default_device``.
type Device

Launch1D

(type)
One-dimensional launch configuration: logical item count and block size.
type Launch1D

Stream

(type)
CUDA stream for ordered kernel enqueue on one device.
type Stream

ReadyBuffer

(type) linear
Device allocation ready for kernels, download, or ``free``.
linear type ReadyBuffer a

Pending

(type) linear
In-flight kernel output; promote with ``synchronize`` or abandon with ``discard``.
linear type Pending a

I32Download

(type) linear
Linear download token: host snapshot plus the live device buffer it was read from.
linear type I32Download

Float64Download

(type) linear
linear type Float64Download

I32DownloadPair

(type)
Unrestricted pair after ``unpack_*`` (values + buffer projections).
type I32DownloadPair

Float64DownloadPair

(type)
type Float64DownloadPair

Functions

num_devices

Number of visible CUDA devices.
def num_devices (_ : Unit) : {n : Int | n > 0}

device

Select a device by zero-based index.
def device (id : Int | id ≥ 0 && id < num_devices unit) : {d : Device | device_id d = id && max_threads_per_block d > 0}

default_device

Default CUDA device (device 0 when present).
def default_device (_ : Unit) : {d : Device | device_id d ≥ 0 && max_threads_per_block d > 0}

default_stream

Default stream on ``device``.
def default_stream (device : Device) : {stream : Stream | stream_device stream = device_id device}

launch_1d

Describe a non-empty 1-D launch on ``device``.
def launch_1d (device : Device) (items : Int | items > 0) (threads : Int | threads > 0 && (threads ≤ items && threads ≤ max_threads_per_block device)) : { launch : Launch1D | launch_device launch = device_id device && ( launch_items launch = items && (launch_threads launch = threads && launch_grid_size launch * launch_threads launch ≥ launch_items launch) ) }

upload_i32

Upload a non-empty ``Int`` array; consumes the host buffer.
def upload_i32 (device : Device) (1 values : Array Int | Array.size values > 0) : { buffer : ReadyBuffer Int | buffer_device buffer = device_id device && ( buffer_size buffer = Array.size values && ( buffer_elem_size buffer = 4 && (buffer_bytes buffer = buffer_size buffer * buffer_elem_size buffer && buffer_bytes buffer ≤ max_allocation device) ) ) }

upload_float64

Upload a non-empty ``Float`` array as float64; consumes the host buffer.
def upload_float64 (device : Device) (1 values : Array Float | Array.size values > 0) : { buffer : ReadyBuffer Float | buffer_device buffer = device_id device && ( buffer_size buffer = Array.size values && ( buffer_elem_size buffer = 8 && (buffer_bytes buffer = buffer_size buffer * buffer_elem_size buffer && buffer_bytes buffer ≤ max_allocation device) ) ) }

add_i32

Elementwise ``Int`` vector add on ``launch``'s device via ``stream``. left, right: equal-sized buffers on the launch device, covering ``launch_items``.
def add_i32 (launch : Launch1D) (stream : Stream | stream_device stream = launch_device launch) ( 1 left : ReadyBuffer Int | buffer_size left > 0 && ( buffer_elem_size left = 4 && ( buffer_device left = launch_device launch && (buffer_size left = launch_items launch && launch_grid_size launch * launch_threads launch ≥ buffer_size left) ) ) ) ( 1 right : ReadyBuffer Int | buffer_size right = buffer_size left && (buffer_elem_size right = buffer_elem_size left && buffer_device right = buffer_device left) ) : { pending : Pending Int | pending_device pending = launch_device launch && (pending_size pending = launch_items launch && pending_stream pending = stream_id stream) }

add_float64

Elementwise ``Float`` (float64) vector add; same size/device rules as ``add_i32``.
def add_float64 (launch : Launch1D) (stream : Stream | stream_device stream = launch_device launch) ( 1 left : ReadyBuffer Float | buffer_size left > 0 && ( buffer_elem_size left = 8 && ( buffer_device left = launch_device launch && (buffer_size left = launch_items launch && launch_grid_size launch * launch_threads launch ≥ buffer_size left) ) ) ) ( 1 right : ReadyBuffer Float | buffer_size right = buffer_size left && (buffer_elem_size right = buffer_elem_size left && buffer_device right = buffer_device left) ) : { pending : Pending Float | pending_device pending = launch_device launch && (pending_size pending = launch_items launch && pending_stream pending = stream_id stream) }

synchronize

Block until ``pending`` completes; recover a ``ReadyBuffer``.
def synchronize (1 pending : Pending a) : { buffer : ReadyBuffer a | buffer_device buffer = pending_device pending && (buffer_size buffer = pending_size pending && buffer_bytes buffer = buffer_size buffer * buffer_elem_size buffer) }

download_i32

Copy device ``Int`` data to a fresh host array; consumes ``buffer``.
def download_i32 (1 buffer : ReadyBuffer Int) : { result : I32Download | i32_download_device result = buffer_device buffer && i32_download_size result = buffer_size buffer }

download_float64

Copy device float64 data to a fresh host array; consumes ``buffer``.
def download_float64 (1 buffer : ReadyBuffer Float) : { result : Float64Download | float64_download_device result = buffer_device buffer && float64_download_size result = buffer_size buffer }

unpack_i32_download

Split ``I32Download`` into an unrestricted pair (values tuple + buffer).
def unpack_i32_download (1 p : I32Download) : { pair : I32DownloadPair | i32_download_pair_device pair = i32_download_device p && i32_download_pair_size pair = i32_download_size p }

unpack_float64_download

Split ``Float64Download`` into an unrestricted pair.
def unpack_float64_download (1 p : Float64Download) : { pair : Float64DownloadPair | float64_download_pair_device pair = float64_download_device p && float64_download_pair_size pair = float64_download_size p }

download_values_i32

Host snapshot from an ``I32DownloadPair`` (linear ``Array Int``).
def download_values_i32 (p : I32DownloadPair) : {xs : Array Int | Array.size xs = i32_download_pair_size p}

download_buffer_i32

Live GPU buffer from an ``I32DownloadPair``; ``free`` when done.
def download_buffer_i32 (p : I32DownloadPair) : { b : ReadyBuffer Int | buffer_device b = i32_download_pair_device p && ( buffer_size b = i32_download_pair_size p && (buffer_elem_size b = 4 && buffer_bytes b = buffer_size b * buffer_elem_size b) ) }

download_values_float64

Host snapshot from a ``Float64DownloadPair``.
def download_values_float64 (p : Float64DownloadPair) : {xs : Array Float | Array.size xs = float64_download_pair_size p}

download_buffer_float64

Live GPU buffer from a ``Float64DownloadPair``.
def download_buffer_float64 (p : Float64DownloadPair) : { b : ReadyBuffer Float | buffer_device b = float64_download_pair_device p && ( buffer_size b = float64_download_pair_size p && (buffer_elem_size b = 8 && buffer_bytes b = buffer_size b * buffer_elem_size b) ) }

free

Release a completed device allocation.
def free (1 buffer : ReadyBuffer a) : Unit

discard

Abandon in-flight work without reading results.
def discard (1 pending : Pending a) : Unit

Uninterpreted

Functions declared as def f ... = uninterpreted: only their signature is known to the verifier; they have no body.

device_id

uninterpreted
def device_id : (d : Device) → Int

num_devices

uninterpreted
def num_devices : (_ : Unit) → Int

max_threads_per_block

uninterpreted
def max_threads_per_block : (d : Device) → Int

max_allocation

uninterpreted
def max_allocation : (d : Device) → Int

launch_device

uninterpreted
def launch_device : (launch : Launch1D) → Int

launch_items

uninterpreted
def launch_items : (launch : Launch1D) → Int

launch_threads

uninterpreted
def launch_threads : (launch : Launch1D) → Int

launch_grid_size

uninterpreted
def launch_grid_size : (launch : Launch1D) → Int

stream_device

uninterpreted
def stream_device : (stream : Stream) → Int

stream_id

uninterpreted
def stream_id : (stream : Stream) → Int

pending_stream

uninterpreted
def pending_stream : (pending : Pending a) → Int

buffer_device

uninterpreted
def buffer_device : (buffer : ReadyBuffer a) → Int

buffer_size

uninterpreted
def buffer_size : (buffer : ReadyBuffer a) → Int

buffer_elem_size

uninterpreted
def buffer_elem_size : (buffer : ReadyBuffer a) → Int

buffer_bytes

uninterpreted
def buffer_bytes : (buffer : ReadyBuffer a) → Int

pending_device

uninterpreted
def pending_device : (pending : Pending a) → Int

pending_size

uninterpreted
def pending_size : (pending : Pending a) → Int

i32_download_device

uninterpreted
def i32_download_device : (p : I32Download) → Int

i32_download_size

uninterpreted
def i32_download_size : (p : I32Download) → Int

i32_download_pair_device

uninterpreted
def i32_download_pair_device : (p : I32DownloadPair) → Int

i32_download_pair_size

uninterpreted
def i32_download_pair_size : (p : I32DownloadPair) → Int

float64_download_device

uninterpreted
def float64_download_device : (p : Float64Download) → Int

float64_download_size

uninterpreted
def float64_download_size : (p : Float64Download) → Int

float64_download_pair_device

uninterpreted
def float64_download_pair_device : (p : Float64DownloadPair) → Int

float64_download_pair_size

uninterpreted
def float64_download_pair_size : (p : Float64DownloadPair) → Int