fix: ISV+plan kernels run pre-mega-replay, not inside graph_mega
NVRTC-compiled ISV kernels conflict with cuBLAS GEMM internal stream scheduling when captured in the same CUDA Graph as cuBLAS ops. Moving ISV+plan to pre-replay phase: they run BEFORE graph_mega replay on every training step. Their outputs (gamma_mod_buf, branch_gate_buf, gated_h_s2_buf, predicted_error_buf, plan_params_buf) are stable device buffers consumed by the captured graph. Same result, no deadlock. ISV updates every step (not every 50). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7877,17 +7877,13 @@ impl GpuDqnTrainer {
|
||||
// ── 1. Forward (cuBLAS SGEMM — Pass 1 + 2, no Pass 3) ──────────
|
||||
self.launch_cublas_forward()?;
|
||||
|
||||
// ── 1b. ISV + plan heads inside graph capture.
|
||||
// Pinned device-mapped pointers are stable (address captured, values change).
|
||||
// Same pattern as total_loss_dev_ptr, grad_norm_dev_ptr, etc.
|
||||
{
|
||||
let batch_size = self.config.batch_size;
|
||||
self.launch_isv_forward()?;
|
||||
self.launch_isv_feature_gate(batch_size)?;
|
||||
self.launch_recursive_confidence_forward(batch_size)?;
|
||||
self.launch_trade_plan_forward(batch_size)?;
|
||||
self.launch_plan_noise_inject(batch_size)?;
|
||||
}
|
||||
// ── 1b. ISV + plan heads run BEFORE graph_mega replay (pre-replay phase
|
||||
// in fused_training.rs). Their outputs (gamma_mod_buf, branch_gate_buf,
|
||||
// gated_h_s2_buf, predicted_error_buf, plan_params_buf) are stable device
|
||||
// buffers consumed by kernels inside the graph.
|
||||
// NOT captured inside graph_mega — ISV kernel + cuBLAS backward interaction
|
||||
// causes graph replay deadlock (investigated, root cause: graph node scheduling
|
||||
// conflict between ISV NVRTC kernels and cuBLAS GEMM internal streams).
|
||||
|
||||
// ── 2+3. Loss + gradient (blended MSE + C51 via c51_alpha ramp) ─
|
||||
self.launch_curiosity_inference()?;
|
||||
|
||||
@@ -875,6 +875,25 @@ impl FusedTrainingCtx {
|
||||
// Adam step counter update (outside graph — value captured by address)
|
||||
self.trainer.adam_step_async();
|
||||
|
||||
// ISV + plan heads: run BEFORE graph_mega replay, AFTER batch upload.
|
||||
// Their outputs are stable device buffers consumed by the graph.
|
||||
// Running these outside graph_mega avoids NVRTC-cuBLAS graph scheduling conflict.
|
||||
{
|
||||
let bs = self.batch_size;
|
||||
self.trainer.launch_isv_forward()
|
||||
.map_err(|e| anyhow::anyhow!("ISV forward (pre-mega): {e}"))?;
|
||||
self.trainer.launch_isv_feature_gate(bs)
|
||||
.map_err(|e| anyhow::anyhow!("ISV feature gate (pre-mega): {e}"))?;
|
||||
self.trainer.launch_recursive_confidence_forward(bs)
|
||||
.map_err(|e| anyhow::anyhow!("Recursive confidence (pre-mega): {e}"))?;
|
||||
self.trainer.launch_trade_plan_forward(bs)
|
||||
.map_err(|e| anyhow::anyhow!("Trade plan forward (pre-mega): {e}"))?;
|
||||
self.trainer.launch_plan_noise_inject(bs)
|
||||
.map_err(|e| anyhow::anyhow!("Plan noise (pre-mega): {e}"))?;
|
||||
self.trainer.fill_gamma_buf()
|
||||
.map_err(|e| anyhow::anyhow!("Fill gamma buf (pre-mega): {e}"))?;
|
||||
}
|
||||
|
||||
// HER donor computation (outside graph — indices vary per step)
|
||||
if let Some(ref mut her) = self.gpu_her {
|
||||
use crate::cuda_pipeline::gpu_her::HerGpuStrategy;
|
||||
|
||||
Reference in New Issue
Block a user