fix(sp13): B0 cascade gap — 5 unaudited insert_batch call sites
The B0 audit (commit 62ab8ed85) under-counted insert_batch test
callers as 2 (1 production + 1 in-file unit test). Surfaced during
B1.0 implementation when cargo check --workspace --tests failed
with 5 arity-mismatch errors after B0's signature change.
Root cause: B0 audit's grep filter was `grep -v test` and didn't
enumerate crates/ml/src/trainers/dqn/smoke_tests/ (compiled as
part of the lib's test binary, not behind #[cfg(test)]) nor
crates/ml/tests/.
Sites fixed (zero-init i32 alloc, threaded through):
- crates/ml/src/trainers/dqn/smoke_tests/training_stability.rs:152, 196
- crates/ml/src/trainers/dqn/smoke_tests/performance.rs:142
- crates/ml/src/trainers/dqn/smoke_tests/gpu_residency.rs:75
- crates/ml/tests/gpu_per_integration_test.rs:125
No behavior change — the column carries zero data and no consumer
reads it pre-B1.1. B1.1 lands the producer kernel that fills with
-1/0/1 from the 30-bar price trajectory.
Process correction documented in docs/dqn-wire-up-audit.md
"B0.1 cascade-gap fix-up" subsection: future B-series audits must
run cargo check --workspace --tests before claiming cardinality
completeness.
Build: cargo check --workspace --tests clean.
Tests: cargo test -p ml --lib compiles + passes (GPU tests
#[ignore]-gated).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -72,7 +72,8 @@ fn insert_random_batch(
|
||||
let actions = zeros_cuda_u32(n, stream)?;
|
||||
let rewards = random_cuda_f32(n, stream)?;
|
||||
let dones = zeros_cuda_f32(n, stream)?;
|
||||
buf.insert_batch(&states, &next_states, &actions, &rewards, &dones, n)?;
|
||||
let aux_sign = stream.alloc_zeros::<i32>(n).map_err(|e| anyhow::anyhow!("aux_sign alloc: {e}"))?;
|
||||
buf.insert_batch(&states, &next_states, &actions, &rewards, &dones, &aux_sign, n)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,8 @@ fn test_per_sample_latency() -> anyhow::Result<()> {
|
||||
let actions = stream.alloc_zeros::<u32>(batch_insert).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
let rewards = stream.clone_htod(&host_rewards).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
let dones = stream.alloc_zeros::<f32>(batch_insert).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
buf.insert_batch(&states, &next_states, &actions, &rewards, &dones, batch_insert)?;
|
||||
let aux_sign = stream.alloc_zeros::<i32>(batch_insert).map_err(|e| anyhow::anyhow!("aux_sign alloc: {e}"))?;
|
||||
buf.insert_batch(&states, &next_states, &actions, &rewards, &dones, &aux_sign, batch_insert)?;
|
||||
}
|
||||
assert_eq!(buf.len(), fill_count);
|
||||
|
||||
|
||||
@@ -149,7 +149,8 @@ fn test_per_weights_valid() -> anyhow::Result<()> {
|
||||
let actions = stream.alloc_zeros::<u32>(1).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
let rewards = stream.clone_htod(&[0.5_f32]).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
let dones = stream.alloc_zeros::<f32>(1).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
buf.insert_batch(&states, &next_states, &actions, &rewards, &dones, 1)?;
|
||||
let aux_sign = stream.alloc_zeros::<i32>(1).map_err(|e| anyhow::anyhow!("aux_sign alloc: {e}"))?;
|
||||
buf.insert_batch(&states, &next_states, &actions, &rewards, &dones, &aux_sign, 1)?;
|
||||
}
|
||||
|
||||
buf.sample_proportional(16)?;
|
||||
@@ -193,7 +194,8 @@ fn test_per_indices_valid() -> anyhow::Result<()> {
|
||||
let actions = stream.alloc_zeros::<u32>(1).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
let rewards = stream.clone_htod(&[0.5_f32]).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
let dones = stream.alloc_zeros::<f32>(1).map_err(|e| anyhow::anyhow!("{e}"))?;
|
||||
buf.insert_batch(&states, &next_states, &actions, &rewards, &dones, 1)?;
|
||||
let aux_sign = stream.alloc_zeros::<i32>(1).map_err(|e| anyhow::anyhow!("aux_sign alloc: {e}"))?;
|
||||
buf.insert_batch(&states, &next_states, &actions, &rewards, &dones, &aux_sign, 1)?;
|
||||
}
|
||||
|
||||
buf.sample_proportional(16)?;
|
||||
|
||||
@@ -121,8 +121,9 @@ fn fill_buffer(buf: &mut GpuReplayBuffer, n: usize, state_dim: usize) {
|
||||
let af: CudaSlice<u32> = stream.clone_htod(&actions_host).unwrap();
|
||||
let rf = stream.clone_htod(&rewards_host).unwrap();
|
||||
let df = stream.clone_htod(&dones_host).unwrap();
|
||||
let aux_sign: CudaSlice<i32> = stream.alloc_zeros::<i32>(n).unwrap();
|
||||
|
||||
buf.insert_batch(&sf, &nsf, &af, &rf, &df, n).unwrap();
|
||||
buf.insert_batch(&sf, &nsf, &af, &rf, &df, &aux_sign, n).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -5884,7 +5884,7 @@ The P0a Hold-pricing controller wired the per-bar Hold cost in `experience_kerne
|
||||
| Site | Count | Action |
|
||||
|---|---|---|
|
||||
| `insert_batch` production callers | 1 | `training_loop.rs:2032` updated |
|
||||
| `insert_batch` test callers | 1 | in-file `gpu_replay_buffer::tests` updated |
|
||||
| `insert_batch` test callers | 6 | in-file `gpu_replay_buffer::tests` + 5 missed (`training_stability`, `performance`, `gpu_residency` smoke_tests + `gpu_per_integration_test`) |
|
||||
| `GpuBatchPtrs` construction sites | 2 | both inside `sample_proportional` (direct-to-trainer + fallback paths) |
|
||||
| `GpuExperienceBatch` construction sites | 1 | `collect_experiences_gpu` end |
|
||||
|
||||
@@ -5908,6 +5908,10 @@ Build: `cargo check --workspace` clean in 21s. Only pre-existing warnings (Devic
|
||||
- `crates/ml/src/cuda_pipeline/gpu_experience_collector.rs` (+17) — GpuExperienceBatch field + alloc_zeros producer
|
||||
- `crates/ml/src/trainers/dqn/trainer/training_loop.rs` (+1) — caller threads through
|
||||
|
||||
### B0.1 cascade-gap fix-up (2026-05-05)
|
||||
|
||||
The original B0 audit (commit `62ab8ed85`) under-counted `insert_batch` test callers as 2 (1 production + 1 in-file unit test). Surfaced during B1.0 implementation when `cargo check --workspace --tests` failed with 5 arity-mismatch errors. Root cause: the B0 grep filter was `grep -v test` and the audit didn't enumerate `crates/ml/src/trainers/dqn/smoke_tests/` (compiled as part of the lib's test binary, not behind `#[cfg(test)]`) nor `crates/ml/tests/`. **Process gap:** future B-series audits must run `cargo check --workspace --tests` before claiming cardinality completeness. Fixed in commit `<TBD>` by adding zero-init `CudaSlice<i32>` allocs at all 5 missed sites. No behavior change — column carries zero data; B1.1 lands the producer kernel that fills with -1/0/1.
|
||||
|
||||
### Next: B1 (separate atomic commit, fresh-implementer dispatch)
|
||||
|
||||
B1 covers: aux head 1→2 dim, MSE→CE loss, `aux_dir_acc` reads softmax, `aux_pred_to_isv_tanh` rewrite as logit-diff, ISV[117]=AUX_LABEL_SCALE_EMA_INDEX retirement, `dqn_param_layout` fingerprint bump, kernel that populates `aux_sign_labels` with real -1/0/1 labels from the 30-bar price trajectory, `aux_b1_diag` HEALTH_DIAG metric, 17+ GPU oracle unit tests. Brief written from B0's audit findings (this section) — no implementer should re-derive call site cardinality.
|
||||
|
||||
Reference in New Issue
Block a user