Place, compute, read back
sf.asarray(..., device=...) quantizes on the host and uploads; .to("host") downloads; .numpy() downloads and converts. Only sf16 is accepted on Atreides.
What runs where
Two operands on different devices, or one on the host and one on a device, raise
SFTypeError; move one side with .to(...).
Before the launch
Every heavy operation passes the pre-flight gate. In order: static checks (shape, dtype, limits), known answers (a divisor with a zero, a NaN), the range bound, and the golden-vector probe. See Host and device for the reasoning; here is what you observe:sf.config(preflight="warn") the second one launches with a warning instead.
After the launch
The result’sstatus says what the runtime knows. When the host proved the operation safe, exact=True and saturated=0. Otherwise, for an elementwise op the count is an upper bound from scanning the output; for a reduction it is unknown. Reading status →
The policy is applied to the status after the launch, in catalogue order. An exact count honours over="raise"; an upper bound only warns (SFDeviceOverflowWarning); an unknown count says nothing.
<=2 and a warning rather than an exception.
Offloading host work automatically
sf.config(offload_threshold=n) sends host operations with more than n elements to the default device, so a large host computation gets the device path (and a status) without changing the code:
Choosing a target
atreides is the v1 mock (no flags). atreides-flags reports sticky flags, so statuses are exact and over="raise" works for heavy ops. atreides-sim is the kernel simulator, which also runs the built-ins. atreides-hw waits for the real driver. Devices reference →