diff --git a/crates/ml-features/src/alpha_pipeline.rs b/crates/ml-features/src/alpha_pipeline.rs index ebfc4404c..7b9f09733 100644 --- a/crates/ml-features/src/alpha_pipeline.rs +++ b/crates/ml-features/src/alpha_pipeline.rs @@ -143,20 +143,30 @@ pub fn extract_alpha_features( // ── Chunk the emit range ── let n_chunks = rayon::current_num_threads().max(1).min(n_output); let chunk_size = n_output.div_ceil(n_chunks); - let chunks: Vec<(usize, usize)> = (0..n_chunks) + let chunks: Vec<(usize, usize, usize)> = (0..n_chunks) .map(|k| { let emit_start = k * chunk_size; let emit_end = ((k + 1) * chunk_size).min(n_output); - (emit_start, emit_end) + (k, emit_start, emit_end) }) - .filter(|(s, e)| s < e) + .filter(|(_, s, e)| s < e) .collect(); + tracing::info!( + "alpha pipeline: dispatching {} chunks (rayon threads={}, chunk_size={}, warmup_bars={})", + chunks.len(), + rayon::current_num_threads(), + chunk_size, + WARMUP_BARS + ); + let t_pipeline_start = std::time::Instant::now(); + // Parallel per-chunk computation; flatten into the final contiguous Vec. - chunks + let features: Vec> = chunks .par_iter() - .flat_map_iter(|&(emit_start, emit_end)| { + .flat_map_iter(|&(chunk_idx, emit_start, emit_end)| { process_chunk( + chunk_idx, bars, snapshots, trades, @@ -167,12 +177,20 @@ pub fn extract_alpha_features( ) .into_iter() }) - .collect() + .collect(); + + tracing::info!( + "alpha pipeline: all chunks complete, {} rows emitted in {:.1}s", + features.len(), + t_pipeline_start.elapsed().as_secs_f64() + ); + features } /// Process one chunk [emit_start..emit_end) with fresh aggregator state, /// pre-rolling [`WARMUP_BARS`] leading bars to saturate stateful blocks. fn process_chunk( + chunk_idx: usize, bars: &[OHLCVBar], snapshots: &[Mbp10Snapshot], trades: &[Mbp10Trade], @@ -182,6 +200,14 @@ fn process_chunk( emit_end: usize, ) -> Vec> { let warmup_start = emit_start.saturating_sub(WARMUP_BARS); + let t_chunk_start = std::time::Instant::now(); + tracing::info!( + "alpha chunk[{}] start: emit=[{}..{}) warmup_start={}", + chunk_idx, + emit_start, + emit_end, + warmup_start + ); // ── Stateful aggregators (persistent across bars) ── // Block A-E factory aggregators @@ -494,6 +520,12 @@ fn process_chunk( } } + tracing::info!( + "alpha chunk[{}] done: rows={} elapsed={:.1}s", + chunk_idx, + features.len(), + t_chunk_start.elapsed().as_secs_f64() + ); features }