perf(rl): DiagStaging snapshot_async takes raw u64 ptrs — zero device_ptr() calls
Replaces 15 `&CudaSlice` parameters with pre-extracted `u64` device pointers (`CudaSlice::raw_ptr()`). Each prior `device_ptr()` call triggered cudarc's inter-stream event tracking (`cuStreamWaitEvent` + `cuEventRecord`), adding sync overhead on every step. The raw pointers are stable for the trainer's lifetime (all buffers pre-allocated at init), so the event tracking was unnecessary. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -599,21 +599,21 @@ fn main() -> Result<()> {
|
||||
// sync_and_swap completes the copy).
|
||||
diag_staging
|
||||
.snapshot_async(
|
||||
&trainer.isv_d,
|
||||
&trainer.rewards_d,
|
||||
&trainer.dones_d,
|
||||
&trainer.actions_d,
|
||||
&trainer.raw_rewards_d,
|
||||
&trainer.trade_duration_emit_d,
|
||||
&trainer.outcome_ema_d,
|
||||
&trainer.prev_position_lots_d,
|
||||
&trainer.pyramid_units_count_d,
|
||||
&trainer.unit_entry_price_d,
|
||||
&trainer.unit_entry_step_d,
|
||||
&trainer.unit_lots_d,
|
||||
&trainer.unit_trail_distance_d,
|
||||
&trainer.close_unit_index_d,
|
||||
&trainer.frd_logits_d,
|
||||
trainer.isv_d.raw_ptr(),
|
||||
trainer.rewards_d.raw_ptr(),
|
||||
trainer.dones_d.raw_ptr(),
|
||||
trainer.actions_d.raw_ptr(),
|
||||
trainer.raw_rewards_d.raw_ptr(),
|
||||
trainer.trade_duration_emit_d.raw_ptr(),
|
||||
trainer.outcome_ema_d.raw_ptr(),
|
||||
trainer.prev_position_lots_d.raw_ptr(),
|
||||
trainer.pyramid_units_count_d.raw_ptr(),
|
||||
trainer.unit_entry_price_d.raw_ptr(),
|
||||
trainer.unit_entry_step_d.raw_ptr(),
|
||||
trainer.unit_lots_d.raw_ptr(),
|
||||
trainer.unit_trail_distance_d.raw_ptr(),
|
||||
trainer.close_unit_index_d.raw_ptr(),
|
||||
trainer.frd_logits_d.raw_ptr(),
|
||||
)
|
||||
.context("diag snapshot_async")?;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use cudarc::driver::{CudaSlice, CudaStream, DevicePtr};
|
||||
use cudarc::driver::CudaStream;
|
||||
use ml_core::device::MlDevice;
|
||||
|
||||
use crate::pinned_mem::MappedF32Buffer;
|
||||
@@ -133,30 +133,38 @@ impl DiagStaging {
|
||||
}
|
||||
|
||||
/// Launch async DtoD copies from device buffers into the CURRENT staging
|
||||
/// buffer. Non-blocking on the training stream — runs on the diag_stream.
|
||||
/// buffer. Non-blocking on the training stream -- runs on the diag_stream.
|
||||
///
|
||||
/// The cudarc v0.19 `device_ptr()` call on a `CudaSlice` with a different
|
||||
/// stream automatically inserts inter-stream event waits: the diag_stream
|
||||
/// will wait for any prior writes to the source slice before the copy
|
||||
/// begins. This ensures correctness without explicit event management.
|
||||
/// Accepts pre-extracted raw `u64` device pointers (`CudaSlice::raw_ptr()`)
|
||||
/// instead of `&CudaSlice` references. This bypasses cudarc's
|
||||
/// `device_ptr()` event-tracking path which internally does
|
||||
/// `cuStreamWaitEvent` + `cuEventRecord` per call -- eliminating 15
|
||||
/// inter-stream sync events per step.
|
||||
///
|
||||
/// Safety contract: callers must pass pointers from `CudaSlice` fields
|
||||
/// whose device addresses are stable for the trainer's lifetime (all
|
||||
/// pre-allocated at init). The training stream must have completed
|
||||
/// writing to these buffers before the diag_stream reads them; this is
|
||||
/// guaranteed by CUDA's same-context stream ordering when the training
|
||||
/// stream's prior kernel launches have been enqueued before this call.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn snapshot_async(
|
||||
&mut self,
|
||||
isv_d: &CudaSlice<f32>,
|
||||
rewards_d: &CudaSlice<f32>,
|
||||
dones_d: &CudaSlice<f32>,
|
||||
actions_d: &CudaSlice<i32>,
|
||||
raw_rewards_d: &CudaSlice<f32>,
|
||||
trade_duration_d: &CudaSlice<f32>,
|
||||
outcome_ema_d: &CudaSlice<f32>,
|
||||
position_lots_d: &CudaSlice<i32>,
|
||||
pyramid_count_d: &CudaSlice<i32>,
|
||||
unit_entry_price_d: &CudaSlice<f32>,
|
||||
unit_entry_step_d: &CudaSlice<i32>,
|
||||
unit_lots_d: &CudaSlice<i32>,
|
||||
unit_trail_d: &CudaSlice<f32>,
|
||||
close_unit_index_d: &CudaSlice<i32>,
|
||||
frd_logits_d: &CudaSlice<f32>,
|
||||
isv_ptr: u64,
|
||||
rewards_ptr: u64,
|
||||
dones_ptr: u64,
|
||||
actions_ptr: u64,
|
||||
raw_rewards_ptr: u64,
|
||||
trade_duration_ptr: u64,
|
||||
outcome_ema_ptr: u64,
|
||||
position_lots_ptr: u64,
|
||||
pyramid_count_ptr: u64,
|
||||
unit_entry_price_ptr: u64,
|
||||
unit_entry_step_ptr: u64,
|
||||
unit_lots_ptr: u64,
|
||||
unit_trail_ptr: u64,
|
||||
close_unit_index_ptr: u64,
|
||||
frd_logits_ptr: u64,
|
||||
) -> Result<()> {
|
||||
let buf = &self.bufs[self.current];
|
||||
let s = self.diag_stream.cu_stream();
|
||||
@@ -164,150 +172,135 @@ impl DiagStaging {
|
||||
|
||||
unsafe {
|
||||
// ISV
|
||||
let (src, _g) = isv_d.device_ptr(&self.diag_stream);
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr,
|
||||
src,
|
||||
isv_ptr,
|
||||
self.isv_len * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot isv")?;
|
||||
|
||||
// rewards
|
||||
let (src, _g) = rewards_d.device_ptr(&self.diag_stream);
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.rewards_offset * 4) as u64,
|
||||
src,
|
||||
rewards_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot rewards")?;
|
||||
|
||||
// dones
|
||||
let (src, _g) = dones_d.device_ptr(&self.diag_stream);
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.dones_offset * 4) as u64,
|
||||
src,
|
||||
dones_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot dones")?;
|
||||
|
||||
// actions (i32 → same byte width as f32, reinterpret on host)
|
||||
let (src, _g) = actions_d.device_ptr(&self.diag_stream);
|
||||
// actions (i32 -- same byte width as f32, reinterpret on host)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.actions_offset * 4) as u64,
|
||||
src,
|
||||
actions_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot actions")?;
|
||||
|
||||
// raw_rewards
|
||||
let (src, _g) = raw_rewards_d.device_ptr(&self.diag_stream);
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.raw_rewards_offset * 4) as u64,
|
||||
src,
|
||||
raw_rewards_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot raw_rewards")?;
|
||||
|
||||
// trade_duration
|
||||
let (src, _g) = trade_duration_d.device_ptr(&self.diag_stream);
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.trade_duration_offset * 4) as u64,
|
||||
src,
|
||||
trade_duration_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot trade_duration")?;
|
||||
|
||||
// outcome_ema
|
||||
let (src, _g) = outcome_ema_d.device_ptr(&self.diag_stream);
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.outcome_ema_offset * 4) as u64,
|
||||
src,
|
||||
outcome_ema_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot outcome_ema")?;
|
||||
|
||||
// position_lots (i32 → raw bytes into f32 slot)
|
||||
let (src, _g) = position_lots_d.device_ptr(&self.diag_stream);
|
||||
// position_lots (i32 -- raw bytes into f32 slot)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.position_lots_offset * 4) as u64,
|
||||
src,
|
||||
position_lots_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot position_lots")?;
|
||||
|
||||
// pyramid_count (i32 → raw bytes into f32 slot)
|
||||
let (src, _g) = pyramid_count_d.device_ptr(&self.diag_stream);
|
||||
// pyramid_count (i32 -- raw bytes into f32 slot)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.pyramid_count_offset * 4) as u64,
|
||||
src,
|
||||
pyramid_count_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot pyramid_count")?;
|
||||
|
||||
// unit_entry_price (f32, B×4)
|
||||
let (src, _g) = unit_entry_price_d.device_ptr(&self.diag_stream);
|
||||
// unit_entry_price (f32, B x 4)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.unit_entry_price_offset * 4) as u64,
|
||||
src,
|
||||
unit_entry_price_ptr,
|
||||
b * 4 * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot unit_entry_price")?;
|
||||
|
||||
// unit_entry_step (i32, B×4 → raw bytes)
|
||||
let (src, _g) = unit_entry_step_d.device_ptr(&self.diag_stream);
|
||||
// unit_entry_step (i32, B x 4 -- raw bytes)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.unit_entry_step_offset * 4) as u64,
|
||||
src,
|
||||
unit_entry_step_ptr,
|
||||
b * 4 * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot unit_entry_step")?;
|
||||
|
||||
// unit_lots (i32, B×4 → raw bytes)
|
||||
let (src, _g) = unit_lots_d.device_ptr(&self.diag_stream);
|
||||
// unit_lots (i32, B x 4 -- raw bytes)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.unit_lots_offset * 4) as u64,
|
||||
src,
|
||||
unit_lots_ptr,
|
||||
b * 4 * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot unit_lots")?;
|
||||
|
||||
// unit_trail (f32, B×4)
|
||||
let (src, _g) = unit_trail_d.device_ptr(&self.diag_stream);
|
||||
// unit_trail (f32, B x 4)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.unit_trail_offset * 4) as u64,
|
||||
src,
|
||||
unit_trail_ptr,
|
||||
b * 4 * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot unit_trail")?;
|
||||
|
||||
// close_unit_index (i32, B → raw bytes)
|
||||
let (src, _g) = close_unit_index_d.device_ptr(&self.diag_stream);
|
||||
// close_unit_index (i32, B -- raw bytes)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.close_unit_index_offset * 4) as u64,
|
||||
src,
|
||||
close_unit_index_ptr,
|
||||
b * 4,
|
||||
s,
|
||||
)
|
||||
.context("diag snapshot close_unit_index")?;
|
||||
|
||||
// frd_logits (f32, B×FRD_OUT_DIM)
|
||||
let (src, _g) = frd_logits_d.device_ptr(&self.diag_stream);
|
||||
// frd_logits (f32, B x FRD_OUT_DIM)
|
||||
cudarc::driver::result::memcpy_dtod_async(
|
||||
buf.dev_ptr + (self.frd_logits_offset * 4) as u64,
|
||||
src,
|
||||
frd_logits_ptr,
|
||||
b * FRD_OUT_DIM * 4,
|
||||
s,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user