fix(sp7): bump ISV_TOTAL_DIM 294→321 to match SP5_SLOT_END
SP7 T1 added 24 ISV slots (LB_DIFF_VAR_CQL_BASE=297 ... LB_C51_ACTIVE through 321) without bumping ISV_TOTAL_DIM, leaving SP7's wiener-state and activation slots out-of-bounds of the allocated pinned buffer (294 * 4 = 1176 bytes; SP7 slots write to bytes 1188..1284). GPU direct-pointer writes silently corrupted memory in the next page; CPU read_isv_signal_at returned garbage in release builds. This explains the SP7 smoke's confusing zero-budget-everywhere observation: the activation flag was reading OOB memory, the consumer saw inconsistent values, and the controller's actual ISV state was never visible. Bumped ISV_TOTAL_DIM to 321 (max valid index 320, covering SP5_SLOT_END-1). Made pub(crate) so the new contract test can reference it from sp5_isv_slots.rs. Updated layout_fingerprint_seed()'s slot entries to include the previously missing D3 and SP7 slots (TRAINING_SHARPE_EMA=294 through LB_C51_ACTIVE_BASE=317) and updated ISV_TOTAL_DIM= literal to 321 in lockstep per feedback_no_partial_refactor. Added contract test all_sp5_slots_fit_within_isv_total_dim to permanently gate this class of bug at cargo test time. The test would have caught SP7 T1 instantly; future slot allocations cannot regress this. Files: gpu_dqn_trainer.rs (ISV_TOTAL_DIM + comment + fingerprint), sp5_isv_slots.rs (test), docs/dqn-wire-up-audit.md (Fix 31 sub-bullet). Cargo check workspace clean. Cargo test ml --lib 935 passed (934 baseline + 1 new contract test); 16 pre-existing GPU-hardware failures unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -825,7 +825,7 @@ const ISV_NETWORK_DIM: usize = 23;
|
||||
/// (shifted 112→116 in Plan 4 Task 6 Commit A).
|
||||
/// Written by the constructor; checked at checkpoint load. Fail-fast only — no migration
|
||||
/// path exists. See spec §4.A.2 and `LAYOUT_FINGERPRINT_CURRENT` for structural-hash rationale.
|
||||
const ISV_TOTAL_DIM: usize = 294; // SP5 + Layer D D1+D2: 173 + 121 (118 SP5 slots @ 174..278/280..294, with 2-slot gap before cross-fold-persistent Kelly block; Layer D D1 PnL outputs at [286..290); Layer D D2 health composition outputs at [290..294))
|
||||
pub(crate) const ISV_TOTAL_DIM: usize = 321; // SP5 + Layer D D1+D2+D3 + SP7: 173 + 148 (145 SP5 slots @ 174..278/280..321, with 2-slot gap before cross-fold-persistent Kelly block; Layer D D1 PnL outputs at [286..290); Layer D D2 health composition outputs at [290..294); Layer D D3 training metrics EMA at [294..297); SP7 T1 loss-balance Wiener stats at [297..313); SP7 activation-flag fix per-(head,branch) flags at [313..321))
|
||||
/// Legacy alias preserved for call sites that haven't been audited for the
|
||||
/// network-vs-total split. New code should pick `ISV_NETWORK_DIM` (for weight
|
||||
/// tensor sizing) or `ISV_TOTAL_DIM` (for the broadcast bus buffer).
|
||||
@@ -1699,7 +1699,11 @@ const fn layout_fingerprint_seed() -> &'static [u8] {
|
||||
KELLY_SAMPLE_COUNT=283;WIN_RATE_SMOOTH=284;LOSS_RATE_SMOOTH=285;\
|
||||
PNL_TOTAL=286;PNL_MEAN=287;PNL_VAR=288;PNL_MAX_DD=289;\
|
||||
HEALTH_SCORE=290;Q_GAP_NORM=291;Q_VAR_NORM=292;GRAD_NORM_NORM=293;\
|
||||
ISV_TOTAL_DIM=294;\
|
||||
TRAINING_SHARPE_EMA=294;MAX_DD_EMA=295;LOW_DD_RATIO=296;\
|
||||
LB_DIFF_VAR_CQL_BASE=297;LB_SAMPLE_VAR_CQL_BASE=301;\
|
||||
LB_DIFF_VAR_C51_BASE=305;LB_SAMPLE_VAR_C51_BASE=309;\
|
||||
LB_CQL_ACTIVE_BASE=313;LB_C51_ACTIVE_BASE=317;\
|
||||
ISV_TOTAL_DIM=321;\
|
||||
PARAM_W_A_H_S1=0;PARAM_B_A_H_S1=1;PARAM_W_B_H_S1=2;PARAM_B_B_H_S1=3;\
|
||||
PARAM_W_RESIDUAL_H_S1=4;PARAM_GAMMA_H_S1=5;PARAM_BETA_H_S1=6;\
|
||||
PARAM_W_A_H_S2=7;PARAM_B_A_H_S2=8;PARAM_W_B_H_S2=9;PARAM_B_B_H_S2=10;\
|
||||
|
||||
@@ -506,4 +506,15 @@ mod tests {
|
||||
assert_eq!(SP5_SLOT_END, 321);
|
||||
assert_eq!(SP5_PRODUCER_COUNT, SP5_SLOT_END - SP5_SLOT_BASE);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_sp5_slots_fit_within_isv_total_dim() {
|
||||
use crate::cuda_pipeline::gpu_dqn_trainer::ISV_TOTAL_DIM;
|
||||
assert!(
|
||||
SP5_SLOT_END <= ISV_TOTAL_DIM,
|
||||
"SP5_SLOT_END={} exceeds ISV_TOTAL_DIM={} — bus too small for SP5/SP7 slots; \
|
||||
bump ISV_TOTAL_DIM in gpu_dqn_trainer.rs (and update layout_fingerprint_seed()).",
|
||||
SP5_SLOT_END, ISV_TOTAL_DIM,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3995,6 +3995,27 @@ extended. No producer kernel yet — that arrives in the next commit.
|
||||
gate (was_active=1, grads back to 0) → flags hold at 1, prior
|
||||
budget held verbatim. No CPU reference oracle per
|
||||
`feedback_no_cpu_test_fallbacks.md`. Passes on local RTX 3050 Ti.
|
||||
- ISV_TOTAL_DIM OOB fix (commit on wt/sp7-observability, 2026-05-03):
|
||||
**Discovery**: `ISV_TOTAL_DIM=294` but `SP5_SLOT_END=321`; the pinned
|
||||
ISV buffer was allocated at `294×4=1176 bytes`. SP7 T1 added 24 slots
|
||||
(ISV[297..321)) and the activation-flag fix added 8 more (ISV[313..321))
|
||||
without bumping `ISV_TOTAL_DIM`. All SP7 ISV writes/reads from indices
|
||||
297..320 were out-of-bounds: GPU direct-pointer writes silently
|
||||
corrupted memory in the next page-aligned region; CPU
|
||||
`write_isv_signal_at` silently no-oped for `index >= ISV_TOTAL_DIM`;
|
||||
CPU `read_isv_signal_at` returned garbage in release builds.
|
||||
**Root cause**: T1 allocated slots in `sp5_isv_slots.rs` but did not
|
||||
bump `ISV_TOTAL_DIM` in `gpu_dqn_trainer.rs`; the constant lived in a
|
||||
different file with no compile-time linkage to `SP5_SLOT_END`.
|
||||
**Fix**: `ISV_TOTAL_DIM` bumped `294→321` and made `pub(crate)`;
|
||||
`layout_fingerprint_seed()` extended with the missing D3 and SP7 slot
|
||||
entries (TRAINING_SHARPE_EMA=294 through LB_C51_ACTIVE_BASE=317) and
|
||||
`ISV_TOTAL_DIM=321` in lockstep per `feedback_no_partial_refactor`.
|
||||
**Contract test**: `all_sp5_slots_fit_within_isv_total_dim` added to
|
||||
`sp5_isv_slots.rs` test module; asserts `SP5_SLOT_END <= ISV_TOTAL_DIM`
|
||||
at `cargo test -p ml --lib`. This test would have caught the SP7 T1
|
||||
miss instantly; future slot allocations cannot silently regress the bus
|
||||
size without breaking CI.
|
||||
- T8 (out-of-tree): memory pearl `pearl_loss_balance_controller.md` +
|
||||
MEMORY.md index entry. Captures the two-layer (signal-modulated target ×
|
||||
outcome-driven α) pattern for future controller designs.
|
||||
|
||||
Reference in New Issue
Block a user