hawk.runtime#
The thin Python face over hawk._core — descriptor, bind, launch.
This module splits the host path by LIFETIME: everything a launch pays
for is C++ (the void*[], the mirror marshal, the entry cache, the
serial driver), and what stays in Python happens once per kernel —
turning a slot’s declared role into the by-value ABI shape it rides as,
and handing the descriptor to hawk._core.ArgBlock. It is not a
runtime; it is the last mile of the DEFINITION.
The descriptor is derived, never re-tabulated: a slot’s kind comes from
the same role -> mirror map the emitter generated the entry signature
from (hawk.emit.aether.MIRROR_OF), so a slot cannot be described
one way to the compiler and another to the marshal — the failure mode
being a 32-byte handle where the kernel reads a 40-byte mirror, which
is deterministic garbage, not a crash.
No numpy, and no allocation: planes cross through the buffer protocol,
so a numpy array, a torch CPU tensor and a plain array.array
all bind the same way. Output planes are the caller’s.
The crossing budget is visible in the method split:
HostKernel.bind_all() is per bind, HostKernel.rebind() is
bulk (one crossing for the whole changed set), and
HostKernel.launch() is the single per-launch crossing.
Every bound argument is validated against the declaration in
HostKernel.bind_all(), before any address is taken
(_check_bind()), since a wrong dtype or size used to run silently
and return garbage or segfault. Dtype is exact and fixed by role (every
integer-valued role rides a 64-bit wire regardless of how it was
declared in Python, and Terminated is always bool); shape
requires a per-sample plane at least n_samples long (shorter is
always the bug) and a Reduce(op) output one slot per sample; every
plane must be C-contiguous and a sink role’s plane writable, except a
sample-major plane whose transpose is C-contiguous, which binds
zero-copy (plane_layout()). A (w, w) plane reads both ways and is
refused unless layout="samples_first"/"samples_last" (per call) or
hawk.samples_first(x)/hawk.samples_last(x) (per array, which wins) says
which axis holds the samples. HostKernel.rebind() takes raw
pointers, which carry none of this, and is the unchecked fast path over
an already-validated bind.
Threading. Two HostKernel (or ArgBlock) objects are
independent and run freely in parallel. ONE object shared across threads is
memory-safe but caller-ordered: its calls serialise on the object’s own lock,
so concurrent bind and launch on it never tear an argument block, but which
call lands first is the caller’s to order. Module-level state (the build
counters, the primitive registry, the unit publisher) is always safe to use
from any thread.
Module Attributes
The DLPack CPU device code every host plane's mirror carries. |
Functions
The per-slot kind list for a DEPLOYED artifact, from its sidecar alone. |
|
|
The |
|
Load |
|
Bind |
Classes
The contiguous void*[] of by-value mirror PODs one kernel DEFINITION binds through. |
|
One HAWK host artifact's entry, self-checked at load and bound once. |