From a2370d7f33760a49c7e8db11726f40d4ae910b7e Mon Sep 17 00:00:00 2001 From: jgrusewski Date: Fri, 10 Apr 2026 08:02:13 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20evaluate=5Fbaseline=20example=20bf16?= =?UTF-8?q?=E2=86=92f32=20closure=20signatures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The evaluate closures now receive &CudaSlice from the backtest evaluator. Updated all 3 closures (DQN, PPO, supervised) to match. Co-Authored-By: Claude Opus 4.6 (1M context) --- crates/ml/examples/evaluate_baseline.rs | 29 ++++++++++++------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/crates/ml/examples/evaluate_baseline.rs b/crates/ml/examples/evaluate_baseline.rs index e5c6239cc..1cb0b8d34 100644 --- a/crates/ml/examples/evaluate_baseline.rs +++ b/crates/ml/examples/evaluate_baseline.rs @@ -1239,11 +1239,12 @@ fn evaluate_dqn_fold_gpu( let eval_stream = stream.clone(); evaluator .evaluate( - &|states_flat: &cudarc::driver::CudaSlice, batch_size: usize, state_dim: usize| -> Result, ml::MLError> { - // Clone CudaSlice into a GpuTensor, forward through DQN, then argmax - let cloned = ml::cuda_pipeline::clone_cuda_slice_f32(states_flat, &eval_stream)?; - let states_tensor = GpuTensor::new(cloned, vec![batch_size, state_dim]) - .map_err(|e| ml::MLError::ModelError(format!("GpuTensor wrap: {e}")))?; + &|states_flat: &cudarc::driver::CudaSlice, batch_size: usize, state_dim: usize| -> Result, ml::MLError> { + // Download f32 states to host, then upload as bf16 GpuTensor for DQN forward + let host_f32 = eval_stream.clone_dtoh(states_flat) + .map_err(|e| ml::MLError::ModelError(format!("DtoH states: {e}")))?; + let states_tensor = GpuTensor::from_host(&host_f32, vec![batch_size, state_dim], &eval_stream) + .map_err(|e| ml::MLError::ModelError(format!("GpuTensor from_host: {e}")))?; let q_values = dqn.q_values_for_batch(&states_tensor)?; let argmax_indices = q_values.argmax(1, &eval_stream) .map_err(|e| ml::MLError::ModelError(format!("argmax: {e}")))?; @@ -1478,14 +1479,13 @@ fn evaluate_ppo_fold_gpu( let eval_ppo_stream = ppo_stream.clone(); let metrics = evaluator .evaluate( - &|states_flat: &cudarc::driver::CudaSlice, batch_size: usize, state_dim: usize| -> Result, ml::MLError> { - // Download bf16 states to host, then convert to f32 for PPO actor forward + &|states_flat: &cudarc::driver::CudaSlice, batch_size: usize, state_dim: usize| -> Result, ml::MLError> { + // Download f32 states to host for PPO actor forward let n_floats = batch_size * state_dim; let view = states_flat.slice(..n_floats); - let mut host_bf16 = vec![bf16::ZERO; n_floats]; - eval_ppo_stream.memcpy_dtoh(&view, &mut host_bf16) + let mut host_states = vec![0.0_f32; n_floats]; + eval_ppo_stream.memcpy_dtoh(&view, &mut host_states) .map_err(|e| ml::MLError::ModelError(format!("DtoH states: {e}")))?; - let host_states: Vec = host_bf16.iter().map(|v| v.to_f32()).collect(); // Get action probabilities [batch * 45] let probs_host = match &ppo.actor { @@ -1650,14 +1650,13 @@ fn evaluate_supervised_fold_gpu( let metrics = evaluator .evaluate( - &|states_flat: &cudarc::driver::CudaSlice, batch_size: usize, state_dim: usize| -> Result, ml::MLError> { - // Download bf16 states to host, then convert to f32 for supervised forward + &|states_flat: &cudarc::driver::CudaSlice, batch_size: usize, state_dim: usize| -> Result, ml::MLError> { + // Download f32 states to host for supervised forward let n_floats = batch_size * state_dim; let view = states_flat.slice(..n_floats); - let mut host_bf16 = vec![bf16::ZERO; n_floats]; - eval_sup_stream.memcpy_dtoh(&view, &mut host_bf16) + let mut host_states = vec![0.0_f32; n_floats]; + eval_sup_stream.memcpy_dtoh(&view, &mut host_states) .map_err(|e| ml::MLError::ModelError(format!("DtoH states: {e}")))?; - let host_states: Vec = host_bf16.iter().map(|v| v.to_f32()).collect(); // Extract market features only (strip portfolio dims) let market_dim = state_dim.saturating_sub(3);