pub mod pipeline;
pub mod tensor_parallel;
pub mod sharding;
pub mod speculative;
pub mod protocol;
pub mod coordinator;
pub mod fastgrnn_router;
pub mod massive_scale;
pub mod medium_scale;
pub use pipeline::{PipelineNode, PipelineConfig, PipelineRole};
pub use tensor_parallel::{TensorParallelNode, TPConfig};
pub use sharding::{ShardedEmbedding, ShardConfig};
pub use speculative::{SpeculativeDecoder, DraftVerifyConfig};
pub use protocol::{FederationMessage, MessageType, ChipId};
pub use coordinator::{FederationCoordinator, ClusterTopology};
pub use fastgrnn_router::{MicroFastGRNN, MicroGRNNConfig, RoutingFeatures};
pub use massive_scale::{
MassiveTopology, MassiveScaleConfig, MassiveScaleSimulator, ScaleProjection,
DistributedCoordinator, GossipProtocol, FaultTolerance,
};
pub use medium_scale::{
MediumClusterConfig, ScaleComparison, MediumScaleAnalyzer,
ModelCategory, HardwareConfig, BusType,
MEDIUM_SCALE_MIN, MEDIUM_SCALE_MAX, MEDIUM_SCALE_OPTIMAL,
};
pub const MAX_FEDERATION_SIZE: usize = 8;
pub const MAX_MASSIVE_SCALE: usize = 1_000_000;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum FederationMode {
Standalone,
Pipeline,
TensorParallel,
Hybrid,
Speculative,
MixtureOfExperts,
}
#[derive(Debug, Clone)]
pub struct FederationConfig {
pub num_chips: usize,
pub chip_id: ChipId,
pub mode: FederationMode,
pub bus: CommunicationBus,
pub layers_per_chip: usize,
pub heads_per_chip: usize,
pub enable_pipelining: bool,
}
impl Default for FederationConfig {
fn default() -> Self {
Self {
num_chips: 5,
chip_id: ChipId(0),
mode: FederationMode::Pipeline,
bus: CommunicationBus::Spi,
layers_per_chip: 2,
heads_per_chip: 1,
enable_pipelining: true,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum CommunicationBus {
Spi,
I2c,
Uart,
EspNow,
Parallel,
}
impl CommunicationBus {
pub const fn bandwidth_bytes_per_sec(&self) -> usize {
match self {
Self::Spi => 10_000_000, Self::I2c => 100_000, Self::Uart => 500_000, Self::EspNow => 125_000, Self::Parallel => 20_000_000, }
}
pub const fn latency_us(&self) -> usize {
match self {
Self::Spi => 10,
Self::I2c => 50,
Self::Uart => 20,
Self::EspNow => 500, Self::Parallel => 5,
}
}
}
pub fn calculate_optimal_config(
model_size_bytes: usize,
num_layers: usize,
num_heads: usize,
num_chips: usize,
per_chip_ram: usize,
) -> FederationConfig {
let model_per_chip = model_size_bytes / num_chips;
if model_per_chip <= per_chip_ram {
let layers_per_chip = (num_layers + num_chips - 1) / num_chips;
return FederationConfig {
num_chips,
chip_id: ChipId(0),
mode: FederationMode::Pipeline,
bus: CommunicationBus::Spi,
layers_per_chip,
heads_per_chip: num_heads,
enable_pipelining: true,
};
}
let heads_per_chip = (num_heads + num_chips - 1) / num_chips;
FederationConfig {
num_chips,
chip_id: ChipId(0),
mode: FederationMode::TensorParallel,
bus: CommunicationBus::Spi,
layers_per_chip: num_layers,
heads_per_chip,
enable_pipelining: false,
}
}
pub fn estimate_speedup(config: &FederationConfig) -> FederationSpeedup {
let n = config.num_chips as f32;
match config.mode {
FederationMode::Standalone => FederationSpeedup {
throughput_multiplier: 1.0,
latency_reduction: 1.0,
memory_per_chip_reduction: 1.0,
},
FederationMode::Pipeline => FederationSpeedup {
throughput_multiplier: n * 0.85, latency_reduction: 1.0 / (1.0 + 0.1 * (n - 1.0)), memory_per_chip_reduction: n,
},
FederationMode::TensorParallel => FederationSpeedup {
throughput_multiplier: n * 0.7, latency_reduction: n * 0.7,
memory_per_chip_reduction: n * 0.8, },
FederationMode::Hybrid => FederationSpeedup {
throughput_multiplier: n * 0.75,
latency_reduction: (n / 2.0) * 0.8,
memory_per_chip_reduction: n * 0.9,
},
FederationMode::Speculative => FederationSpeedup {
throughput_multiplier: 2.5,
latency_reduction: 2.0,
memory_per_chip_reduction: 1.0, },
FederationMode::MixtureOfExperts => FederationSpeedup {
throughput_multiplier: n * 0.9, latency_reduction: 1.5,
memory_per_chip_reduction: n,
},
}
}
#[derive(Debug, Clone)]
pub struct FederationSpeedup {
pub throughput_multiplier: f32,
pub latency_reduction: f32,
pub memory_per_chip_reduction: f32,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_optimal_config() {
let config = calculate_optimal_config(
500 * 1024, 10, 4, 5, 120 * 1024, );
assert_eq!(config.mode, FederationMode::Pipeline);
assert_eq!(config.layers_per_chip, 2);
}
#[test]
fn test_speedup_estimate() {
let config = FederationConfig {
num_chips: 5,
mode: FederationMode::Pipeline,
..Default::default()
};
let speedup = estimate_speedup(&config);
assert!(speedup.throughput_multiplier > 4.0);
assert!(speedup.memory_per_chip_reduction >= 5.0);
}
}