caliper.device.v1¶
Service id caliper.device.v1 — the host's negotiated compute device (PLATFORM.md §7.3). This page embeds the header verbatim; the docs build fails if the file moves.
#pragma once
/* caliper.device.v1 — the host's negotiated compute device (PLATFORM.md
* §7.3). IMMUTABLE once published. Kinds name the MEMORY/API DOMAIN, not a
* framework backend: METAL covers torch-MPS, MLX, and ggml-Metal alike. The
* host detects without linking any ML framework (D11); applets map the kind
* to their framework's device (torch: METAL -> torch::kMPS). */
#include <stdint.h>
#define CALIPER_DEVICE_V1 "caliper.device.v1"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum CaliperDeviceKind {
CALIPER_DEV_CPU = 0,
CALIPER_DEV_CUDA = 1,
CALIPER_DEV_METAL = 2
} CaliperDeviceKind;
typedef struct CaliperDeviceV1 {
uint32_t struct_size;
CaliperDeviceKind (*kind)(void);
int32_t (*index)(void); /* 0 for CPU/METAL */
const char* (*name)(void); /* host-owned, e.g. "Apple M3 Max" */
uint64_t (*free_memory_hint)(void); /* bytes, best-effort; 0 = unknown */
} CaliperDeviceV1;
#ifdef __cplusplus
}
#endif
Semantics¶
The host negotiates; the applet maps. The host detects one compute device
and vends it through this service. The applet reads the kind and maps it to
its own framework's device — the host stays framework-agnostic. This is a hard
architectural rule (PLATFORM.md D11): the host never links torch, DuckDB-for-ML, or
any ML framework. On Apple the detection is Metal-API-only; CUDA detection
lands with real hardware in Phase 4.
Kinds name the memory/API domain, not a backend. The enum is
CALIPER_DEV_CPU = 0, CALIPER_DEV_CUDA = 1, CALIPER_DEV_METAL = 2.
METAL deliberately does not say "MPS": it names the Metal memory/API
domain, which covers torch-MPS, MLX, and ggml-Metal alike (spec §7.2). "MPS" is
a torch-specific backend name and must never appear in the ABI. An applet that
uses libtorch maps CALIPER_DEV_METAL → torch::kMPS itself:
torch::Device dev =
device.kind == CALIPER_DEV_METAL && torch::hasMPS()
? torch::Device(torch::kMPS)
: torch::Device(torch::kCPU);
Note the torch::hasMPS() check: the host reports the memory domain it
detected, but the applet still confirms its own framework can use it, and falls
back to CPU otherwise. The kind is a negotiation input, not a promise that every
framework is built for it.
Fields. index is 0 for CPU and METAL (it carries a CUDA device ordinal
when that lands). name is a host-owned string valid for the process
lifetime — do not free it, and do not assume it outlives the host. free_memory_hint
is a best-effort byte count; 0 means "unknown", not "no memory". Any function
pointer may be null on an older host; the caliper::Device
sugar null-guards each one and defaults the whole snapshot to CPU when the host
does not vend the service.