pub fn f32_to_bf16(val: f32) -> u16Expand description
Convert f32 to BF16 with IEEE-754 round-to-nearest-even.
Must stay byte-identical to PyTorch’s torch.float32 -> torch.bfloat16
cast: reference activations and the dequanted-weight snapshots Atlas is
scored against are produced that way, so any drift here shows up as an
accuracy regression with no other symptom.
Phase 2b (FP8 dequant audit, 2026-05-24) replaced truncation
(bits >> 16) with ties-to-even. Truncation is biased toward zero and
the bias accumulated across the 31745 dequanted tensors of
Qwen3.6-35B-FP8 to a mean per-layer cosine of 0.969.
NaN maps to the canonical quiet-NaN pattern with the sign preserved, which is also what PyTorch does.
ATLAS_DISABLE_RNE is a bisect escape hatch that reverts to
truncation. It is a PRESENCE check, not a value check — =0 disables
RNE just as =1 does.
★ THE ESCAPE HATCH IS READ ONCE PER PROCESS. This is a scalar primitive —
five arithmetic operations, #[inline(always)] — called ONCE PER ELEMENT
over whole weight tensors (weight_map::quant_helpers iterates every byte
of an FP8 tensor; fp8_lut walks every NVFP4 group). A std::env::var
here allocates a String and takes the process-wide environment lock, and
dominated the arithmetic by roughly three orders of magnitude. The
dequantisation path this serves has a MEASURED cost of ~80 s
(weight_map/fp8_dequant.rs), which is ~1.4e8 elements at the per-read
rate — so the getenv plausibly accounted for most of it.
Caching is safe here specifically because the test that varies this
re-execs the test binary as a CHILD PROCESS with the variable set
(disable_rne_presence_uses_truncation below), so each process resolves it
once at its own start. Do NOT convert that test to set_var in-process.