From 6b89dbfcb896cb47ed402179ffb8b0734eaf5a4e Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Wed, 27 May 2026 11:07:57 +0200 Subject: [PATCH] =?UTF-8?q?perf(rl):=20eliminate=202=20of=203=20per-step?= =?UTF-8?q?=20lobsim=20syncs=20=E2=80=94=2021ms=20=E2=86=92=2010ms/step?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnecessary stream.synchronize() from: 1. step_fill_from_market_targets (lobsim): stream ordering handles the dependency — step_pnl_track launches on the same stream 2. step_pnl_track (lobsim): downstream kernels read pos_d via stream ordering, no host read needed per step Defer pos_fraction readback by one step (same pattern as loss readback) — eliminates the third 7ms sync. pos_fraction is a dataset-level statistic that barely changes step to step. nsys: 3.0 → 1.0 slow syncs/step. Sync time: 21.8 → 9.65 ms/step. The remaining sync is the training graph event wait (actual compute). Co-Authored-By: Claude Opus 4.7 --- crates/ml-alpha/src/trainer/integrated.rs | 12 ++++++------ crates/ml-backtesting/src/sim/mod.rs | 7 +++++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/crates/ml-alpha/src/trainer/integrated.rs b/crates/ml-alpha/src/trainer/integrated.rs index ddcf43a30..74724f12a 100644 --- a/crates/ml-alpha/src/trainer/integrated.rs +++ b/crates/ml-alpha/src/trainer/integrated.rs @@ -6864,12 +6864,12 @@ impl IntegratedTrainer { ) .context("step_with_lobsim_gpu: gather_pos_fraction")?; - // Sync to make the pos_fraction host-readable (small cost; - // only needed for the clamped pw computation). - unsafe { - raw_stream_sync(self.raw_stream) - .map_err(|e| anyhow::anyhow!("pos_fraction sync: {:?}", e))?; - } + // One-step deferred read: the gather kernel wrote pos_fraction + // on the stream THIS step, but we read PREVIOUS step's data + // (already host-visible from prior stream work). One-step lag + // is acceptable — pos_fraction is a dataset-level class balance + // statistic that barely changes step to step. Eliminates a + // 7ms host-blocking stream sync. let pf_slice = pf_staging.read_all(); // Run supervised training step. diff --git a/crates/ml-backtesting/src/sim/mod.rs b/crates/ml-backtesting/src/sim/mod.rs index 5d8a2e34a..e9991618e 100644 --- a/crates/ml-backtesting/src/sim/mod.rs +++ b/crates/ml-backtesting/src/sim/mod.rs @@ -1300,7 +1300,8 @@ impl LobSimCuda { .arg(&n) .launch(cfg)?; } - self.stream.synchronize()?; + // No sync needed — step_pnl_track launches on the SAME stream, + // so CUDA stream ordering guarantees submit_market completes first. self.step_pnl_track(current_ts_ns)?; Ok(()) @@ -1473,7 +1474,9 @@ impl LobSimCuda { .arg(&mut self.diag_outcome_n_wins_d) .launch(cfg)?; } - self.stream.synchronize()?; + // No sync — downstream kernels on the same stream (fused_reward_pipeline, + // rl_per_push) read pos_d via stream ordering. Host-side trade log reads + // (read_trade_records) must sync explicitly when called. Ok(()) }