feat: ZERO unannotated GPU→CPU downloads — every memcpy_dtoh accounted for
Eliminated 7 downloads:
- dqn.rs dead neuron: GPU abs→le→sum (test-only, marked #[cold])
- ppo.rs compute_losses: GPU gather_rows kernel for per-action log-prob
(eliminated 3 full-batch downloads)
- ppo.rs update_gpu: GPU gather_rows + GpuTensor::symlog()
(sign(x)*ln(|x|+1) via 6 elementwise GPU kernels)
- Test assertions: annotated with // test-only readback
Marked #[cold] + annotated 8 checkpoint/API methods:
- CudaLinear::get_weights(), CudaVec::to_vec(), GpuTensor::to_host(),
GpuVarStore::{all_vars,flatten,export_to_host},
GpuLinear::{weight_to_vec,bias_to_vec}
New GPU infrastructure:
- ElementwiseKernels: gather_rows + gather_rows_u32 CUDA kernels
- GpuTensor::symlog() — fully GPU-native sign*log transform
Every remaining memcpy_dtoh is annotated: // gpu-exit: or // test-only readback
Verification: `rg "memcpy_dtoh" | grep -v "gpu-exit\|test.*readback"` = 0
1,116 tests pass across 5 sub-crates. Zero failures.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>