Files
foxhunt/crates
jgrusewski 19bb3bc3c8 fix(sp22-vnext): aux_outcome CF half mirror on-policy (NOT all -1)
Smoke train-k95mj epoch 0 + epoch 1 printed
`trade_outcome_ce=0.000e0` — K=3 CE EMA stuck at Pearl A sentinel
across all training steps.

Root cause chain:

  1. insert_batch is called with bs = total = 4_096_000 (cf-mult-
     expanded), replay cap = 300_000 (L40S GpuProfile). Tail-clip:
     off = 3_796_000, slice(off..) takes the last 300K elements.
  2. Prior fix (256a5fa5a) filled CF half [base_total, total) with
     -1 mask via cuMemsetD32Async. Last 300K elements at
     [3_796_000, 4_096_000) are entirely in this CF half → 100%
     mask.
  3. Replay ring fills with 300K mask labels. PER gather samples
     batches → every batch has label == -1 for all samples →
     aux_trade_outcome_loss_reduce returns
     loss = 0 / fmaxf(valid=0, 1) = 0 every step.
  4. aux_outcome_ce_ema_update bootstrap requires `loss > 0.0f`;
     never fires → ISV[538] pinned at 0.0 sentinel.

Fix: CF half mirrors the on-policy half (matches K=2 sibling
aux_sign_labels which writes the same bar-resolved label to both
halves). Replace cuMemsetD32Async(-1) + single memcpy with TWO
memcpy_dtod calls (on-policy half + CF half), both sourced from
the same exp_aux_to_label_per_sample[base_total].

Semantic justification: the K=3 outcome label depends on the bar's
trade-close event, not the action. The CF action's hypothetical
trade outcome at the same bar approximates to the same label. The
B4b-1 kernel writes -1 to non-close slots (~97%) and 0/1/2 to
close slots (~3%); duplicating into CF preserves this sparsity →
ring tail retains ~7-9K real labels per 300K-element fill →
Pearl A bootstraps → K=3 head trains.

Lib suite 1016/0 green. Bug was runtime-only (small-batch lib
tests don't trigger the off > 0 tail-clip path). Audit doc
updated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 16:19:15 +02:00
..