Light and heavy
Every array has a placement:"host" or the name of a device. An operation is light when all its inputs are on the host, and heavy when any input is on a device.
- Light operations run on the host, using the same bit-exact reference the simulator and the mock device use. They go through the error policy and carry no status.
- Heavy operations (
+ - * /,fma,sqrt,sum,dot,@,addmm) run on the device and return an array with a.status. - Selection and data movement (
maximum,minimum,clip,where,cast, indexing, reshape) always run on the host, even on device arrays, because they cannot produce an event.
.to(...).
The rule: decide on the host, launch only the undecidable
The chip is for work whose answer the host does not know. Before any heavy operation is launched, the host runs a gate, in this order:1
Static checks
Shapes, dtype (only sf16 on Atreides), size limits. A mismatch raises
SFShapeError or SFTypeError; nothing is launched.2
Known answers
A divisor array that contains a zero, a divide where every
|a| >= |b|, a NaN: these are events the host can see in the inputs. They are reported through the policy before the launch, and the chip never sees them.3
Range bound
The host carries the inputs’ magnitudes through the arithmetic rules. If no element can possibly saturate, the launch is marked safe and the result’s status is exact without any scan. If every element must saturate, the operation is refused (
sf.config(preflight="raise"), the default).4
Golden-vector probe
For the band in between, a small sample of the real inputs is run through the host reference. A hit is a suspicion, never a proof: by default it warns (
SFPreflightWarning) and launches. sf.config(suspect="raise") refuses instead; suspect="verify" replays the whole operation on the host and refuses only on proof.What status can and cannot tell you
Atreides v1 has no saturation flag the host can read back.sf is honest about that:
status.outputs_at_max always holds the raw count of outputs sitting at ±max. status.ok is True, False, or None when unknown.
Two ways to get an exact count without flags:
sf.config(status="replay")recomputes the events on the host, at the cost of doing the work twice.- Use a target that reports flags.
"atreides-flags"is a mock that does; a real target withsticky_flags=Truewould too. With exact counts,over="raise"is honoured for heavy ops.
The targets
sf.devices() lists them; sf.register_device(...) adds your own. Devices reference →