* perf(pi052): sync-free denoise loop (precompute timesteps, device masks, KV crop)
Remove the per-denoise-step CPU->GPU syncs and the per-step KV-cache deepcopy
from action sampling:
- precompute the timestep schedule once instead of rebuilding a tensor from a
Python float every step (torch.tensor(time, device=cuda) is a host sync);
- build the constant [1, 0, ...] suffix attention mask on-device instead of
torch.tensor(python_list, device=cuda);
- drop the per-step copy.deepcopy of the prefix KV cache: the expert forward
appends the suffix K/V in place, so crop back to the prefix length afterwards
(prefix K/V are read-only, so this is exact and the loop stays one graph).
Bit-exact: action max|delta|=0 vs the previous implementation; no API change.
* feat(pi052): optional FlashRT FP8 Gemma/SigLIP MLP swap (opt-in)
Opt-in (config use_flashrt_fp8_mlp) swap of the Gemma GeGLU + SigLIP GELU MLPs
to the FlashRT FP8 Hub kernels. When the flag is set, the first inference
calibrates static activation scales on that observation and swaps the MLP
modules in place (re-entry guarded); graceful BF16 fallback if the kernels are
unavailable.
Calibration follows the FlashRT contract: the FP8 modules are swapped in first,
then a single forward measures each GEMM's input/hidden amax on the
already-quantized (FP8-propagated) activations, with the preceding fixed
RMSNorm weight (1+w) folded into the GEMM and scale = amax/448 * 1.05.
On pi05_libero_pytorch (RTX 5090, torch.compile): ~1.91x end-to-end
(89.4 -> 46.7 ms) with the sync-free loop, action cos vs BF16 ~0.999
(maxdiff ~0.03) over real LIBERO frames.