diff --git a/crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs b/crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs index 55a713ac3..44aa51971 100644 --- a/crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs +++ b/crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs @@ -8219,9 +8219,13 @@ impl GpuDqnTrainer { 12 * std::mem::size_of::(), self.stream.cu_stream(), ).map_err(|e| MLError::ModelError(format!("q_out sample0 DtoD: {e}")))?; } - // No sync — CPU reads previous step's values from pinned host pointer. + // Sync: populate_q_out + q_stats_reduce just launched — must wait for + // pinned memory writes to complete before CPU reads. + unsafe { + let rc = cudarc::driver::sys::cuStreamSynchronize(self.stream.cu_stream()); + assert_eq!(rc, cudarc::driver::sys::cudaError_enum::CUDA_SUCCESS, "q_stats stream sync"); + } - // Q-mean EMA update — AFTER stream sync so pinned memory has the GPU-written value. self.update_q_mean_ema(); // Read from pinned buffer — host[0..7] = q_stats, host[7..19] = q_out sample 0