Initial commit

This commit is contained in:
redclawsystems
2026-03-04 00:08:42 +00:00
commit 4d88dc0584
4449 changed files with 1556714 additions and 0 deletions
@@ -0,0 +1,193 @@
//! Pipeline scheduler for generating execution schedules.
use parking_lot::RwLock;
use super::config::{PipelineConfig, PipelineSchedule};
/// Scheduled operation in the pipeline
#[derive(Debug, Clone)]
pub enum PipelineOp {
/// Forward pass on a stage
Forward { stage: usize, micro_batch_id: u64 },
/// Backward pass on a stage
Backward { stage: usize, micro_batch_id: u64 },
/// Send activations to next stage
SendActivation {
from_stage: usize,
to_stage: usize,
micro_batch_id: u64,
},
/// Receive activations from previous stage
RecvActivation {
from_stage: usize,
to_stage: usize,
micro_batch_id: u64,
},
/// Send gradients to previous stage
SendGradient {
from_stage: usize,
to_stage: usize,
micro_batch_id: u64,
},
/// Receive gradients from next stage
RecvGradient {
from_stage: usize,
to_stage: usize,
micro_batch_id: u64,
},
/// Barrier synchronization
Barrier,
}
/// Pipeline schedule generator
pub struct PipelineScheduler {
/// Configuration
config: PipelineConfig,
/// Generated schedule
schedule: RwLock<Vec<Vec<PipelineOp>>>,
}
impl PipelineScheduler {
/// Create a new scheduler
pub fn new(config: PipelineConfig) -> Self {
let scheduler = Self {
config,
schedule: RwLock::new(Vec::new()),
};
scheduler.generate_schedule();
scheduler
}
/// Generate the pipeline schedule
fn generate_schedule(&self) {
let schedule = match self.config.schedule {
PipelineSchedule::GPipe => self.generate_gpipe_schedule(),
PipelineSchedule::OneFOneBAsync => self.generate_1f1b_schedule(),
PipelineSchedule::Interleaved => self.generate_interleaved_schedule(),
PipelineSchedule::Chimera => self.generate_chimera_schedule(),
};
*self.schedule.write() = schedule;
}
/// Generate GPipe schedule (all forwards, then all backwards)
fn generate_gpipe_schedule(&self) -> Vec<Vec<PipelineOp>> {
let num_stages = self.config.num_stages;
let num_micro_batches = self.config.num_micro_batches;
let mut schedule = Vec::new();
// Forward passes
for mb in 0..num_micro_batches {
for stage in 0..num_stages {
let mut step = vec![PipelineOp::Forward {
stage,
micro_batch_id: mb as u64,
}];
if stage < num_stages - 1 {
step.push(PipelineOp::SendActivation {
from_stage: stage,
to_stage: stage + 1,
micro_batch_id: mb as u64,
});
}
schedule.push(step);
}
}
// Backward passes (reverse order)
for mb in (0..num_micro_batches).rev() {
for stage in (0..num_stages).rev() {
let mut step = vec![PipelineOp::Backward {
stage,
micro_batch_id: mb as u64,
}];
if stage > 0 {
step.push(PipelineOp::SendGradient {
from_stage: stage,
to_stage: stage - 1,
micro_batch_id: mb as u64,
});
}
schedule.push(step);
}
}
schedule.push(vec![PipelineOp::Barrier]);
schedule
}
/// Generate 1F1B schedule (one forward, one backward in steady state)
fn generate_1f1b_schedule(&self) -> Vec<Vec<PipelineOp>> {
let num_stages = self.config.num_stages;
let num_micro_batches = self.config.num_micro_batches;
let mut schedule = Vec::new();
// Warmup: fill the pipeline with forwards
for mb in 0..num_stages {
for stage in 0..=mb.min(num_stages - 1) {
schedule.push(vec![PipelineOp::Forward {
stage,
micro_batch_id: mb as u64,
}]);
}
}
// Steady state: 1F1B
for mb in num_stages..num_micro_batches {
// Backward for earlier micro-batch
let backward_mb = (mb - num_stages) as u64;
for stage in (0..num_stages).rev() {
schedule.push(vec![PipelineOp::Backward {
stage,
micro_batch_id: backward_mb,
}]);
}
// Forward for current micro-batch
for stage in 0..num_stages {
schedule.push(vec![PipelineOp::Forward {
stage,
micro_batch_id: mb as u64,
}]);
}
}
// Cooldown: drain remaining backwards
for mb in (num_micro_batches - num_stages)..num_micro_batches {
for stage in (0..num_stages).rev() {
schedule.push(vec![PipelineOp::Backward {
stage,
micro_batch_id: mb as u64,
}]);
}
}
schedule.push(vec![PipelineOp::Barrier]);
schedule
}
/// Generate interleaved schedule (reduced bubble)
fn generate_interleaved_schedule(&self) -> Vec<Vec<PipelineOp>> {
// Simplified interleaved - in practice would have virtual stages
self.generate_1f1b_schedule()
}
/// Generate Chimera schedule (bidirectional)
fn generate_chimera_schedule(&self) -> Vec<Vec<PipelineOp>> {
// Simplified - in practice would have bidirectional pipelines
self.generate_1f1b_schedule()
}
/// Get the generated schedule
pub fn schedule(&self) -> Vec<Vec<PipelineOp>> {
self.schedule.read().clone()
}
/// Get number of steps in schedule
pub fn num_steps(&self) -> usize {
self.schedule.read().len()
}
}