use crate::common::enums::{CommQuantMode, DatabaseMode};
use crate::common::error::AicError;
use crate::common::system_spec::SystemSpec;
use crate::operators::base::{PerformanceResult, SolComponents, Source};
use crate::operators::util_empirical::{self, UtilGrid};
use crate::perf_database::PerfDatabase;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct CustomAllReduceOp {
pub name: String,
pub scale_factor: f64,
pub hidden_size: u32,
pub tp_size: u32,
pub quant: CommQuantMode,
#[serde(default = "crate::operators::gemm::default_seq_split")]
pub seq_split: u32,
}
impl CustomAllReduceOp {
pub fn new(name: impl Into<String>, scale_factor: f64, hidden_size: u32, tp_size: u32) -> Self {
Self {
name: name.into(),
scale_factor,
hidden_size,
tp_size,
quant: CommQuantMode::Half,
seq_split: 1,
}
}
pub fn query(&self, db: &PerfDatabase, num_tokens: u32) -> Result<PerformanceResult, AicError> {
if self.tp_size <= 1 {
return Ok(PerformanceResult::new(0.0, Source::Empirical));
}
let per_rank_tokens = num_tokens.div_ceil(self.seq_split.max(1)); let message_size = (per_rank_tokens as f64) * (self.hidden_size as f64);
let result = query_custom_allreduce_table(db, self.quant, self.tp_size, message_size)?;
Ok(result.clamp_non_negative().scaled(self.scale_factor))
}
}
fn query_custom_allreduce_table(
db: &PerfDatabase,
quant: CommQuantMode,
tp_size: u32,
size: f64,
) -> Result<PerformanceResult, AicError> {
if db.system_spec.node.num_gpus_per_node == 72
&& tp_size > 4
&& matches!(
db.database_mode,
DatabaseMode::Silicon | DatabaseMode::Hybrid
)
{
return query_nccl_table(db, quant, tp_size, "all_reduce", size);
}
let silicon = |db: &PerfDatabase| {
db.communication
.query_custom_allreduce_scaled(&db.system_spec, quant, tp_size, size)
.map(|v| PerformanceResult::with_energy(v.latency, v.energy, Source::Silicon))
};
match db.database_mode {
DatabaseMode::Sol | DatabaseMode::SolFull => Ok(PerformanceResult::new(
custom_allreduce_sol_ms(&db.system_spec, tp_size, size),
Source::Sol,
)
.with_sol(SolComponents::new(0.0, 0.0))),
DatabaseMode::Empirical => Ok(PerformanceResult::new(
custom_allreduce_empirical(db, quant, tp_size, size)?,
Source::Empirical,
)),
DatabaseMode::Hybrid => match silicon(db) {
Ok(result) => Ok(result),
Err(err) if err.is_missing_perf_data() => Ok(PerformanceResult::new(
custom_allreduce_empirical(db, quant, tp_size, size)?,
Source::Empirical,
)),
Err(err) => Err(err),
},
_ => silicon(db),
}
}
fn custom_allreduce_sol_ms(spec: &SystemSpec, tp_size: u32, size: f64) -> f64 {
if tp_size == 1 {
return 0.0;
}
let p2p_bw = p2p_bandwidth(spec, tp_size);
let tp = tp_size as f64;
2.0 * size * 2.0 / tp * (tp - 1.0) / p2p_bw * 1000.0
}
fn custom_allreduce_empirical(
db: &PerfDatabase,
quant: CommQuantMode,
tp_size: u32,
size: f64,
) -> Result<f64, AicError> {
let spec = &db.system_spec;
let sol_q = custom_allreduce_sol_ms(spec, tp_size, size);
if tp_size <= 1 || sol_q <= 0.0 {
return Ok(sol_q);
}
let eff = db
.communication
.measured_tp_slice(quant, tp_size, spec.node.num_gpus_per_node);
let sol = |c: &[f64]| custom_allreduce_sol_ms(spec, eff, c[0]);
let key = format!("custom_allreduce:{}:{eff}", quant.name());
let grid = db.util_grids.get_or_try_build(&key, || {
match db.communication.custom_allreduce_points(quant, eff) {
Ok(points) => Ok(Some(UtilGrid::new(util_empirical::build_samples(
points, sol,
)))),
Err(err) if err.is_missing_perf_data() => Ok(None),
Err(err) => Err(err),
}
})?;
let query = [size];
let (latency, _) = util_empirical::estimate(sol_q, &query, grid.as_deref(), 1.0)?;
db.note_provenance(if eff != tp_size {
util_empirical::ProvenanceTier::XShape
} else {
util_empirical::ProvenanceTier::Empirical
});
Ok(latency)
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct NcclOp {
pub name: String,
pub scale_factor: f64,
pub hidden_size: f64,
pub num_gpus: u32,
pub dtype: CommQuantMode,
pub operation: String,
#[serde(default = "crate::operators::gemm::default_seq_split")]
pub seq_split: u32,
}
impl NcclOp {
pub fn new(
name: impl Into<String>,
scale_factor: f64,
hidden_size: f64,
num_gpus: u32,
operation: impl Into<String>,
) -> Self {
Self {
name: name.into(),
scale_factor,
hidden_size,
num_gpus,
dtype: CommQuantMode::Half,
operation: operation.into(),
seq_split: 1,
}
}
pub fn query(&self, db: &PerfDatabase, num_tokens: u32) -> Result<PerformanceResult, AicError> {
if self.num_gpus <= 1 {
if matches!(db.database_mode, DatabaseMode::Sol | DatabaseMode::SolFull) {
return Ok(PerformanceResult::sol(SolComponents::new(0.0, 0.0)));
}
return Ok(PerformanceResult::new(0.0, Source::Empirical));
}
let per_rank_tokens = num_tokens.div_ceil(self.seq_split.max(1)); let message_size = (per_rank_tokens as f64) * self.hidden_size;
let result =
query_nccl_table(db, self.dtype, self.num_gpus, &self.operation, message_size)?;
Ok(result.clamp_non_negative().scaled(self.scale_factor))
}
}
fn query_nccl_table(
db: &PerfDatabase,
dtype: CommQuantMode,
num_gpus: u32,
operation: &str,
message_size: f64,
) -> Result<PerformanceResult, AicError> {
let silicon = |v: crate::perf_database::perf_interp::LeafValue| {
PerformanceResult::with_energy(v.latency, v.energy, Source::Silicon)
};
match db.database_mode {
DatabaseMode::Sol | DatabaseMode::SolFull => {
Ok(PerformanceResult::sol(SolComponents::new(
0.0,
nccl_sol_ms(&db.system_spec, dtype, num_gpus, operation, message_size),
)))
}
DatabaseMode::Empirical => Ok(PerformanceResult::new(
nccl_empirical(db, dtype, num_gpus, operation, message_size)?,
Source::Empirical,
)),
DatabaseMode::Hybrid => match db.communication.query_nccl_scaled(
&db.system_spec,
dtype,
operation,
num_gpus,
message_size,
) {
Ok(value) => Ok(silicon(value)),
Err(err) if err.is_missing_perf_data() => Ok(PerformanceResult::new(
nccl_empirical(db, dtype, num_gpus, operation, message_size)?,
Source::Empirical,
)),
Err(err) => Err(err),
},
_ => Ok(silicon(db.communication.query_nccl_scaled(
&db.system_spec,
dtype,
operation,
num_gpus,
message_size,
)?)),
}
}
fn nccl_sol_ms(
spec: &SystemSpec,
dtype: CommQuantMode,
num_gpus: u32,
operation: &str,
message_size: f64,
) -> f64 {
let p2p_bw = p2p_bandwidth(spec, num_gpus);
let n = num_gpus as f64;
let mem = dtype.mapping().memory;
match operation {
"all_gather" | "alltoall" | "reduce_scatter" => {
mem * message_size * (n - 1.0) / n / p2p_bw * 1000.0
}
"all_reduce" => 2.0 * mem * message_size * (n - 1.0) / n / p2p_bw * 1000.0,
_ => 0.0,
}
}
fn nccl_empirical(
db: &PerfDatabase,
dtype: CommQuantMode,
num_gpus: u32,
operation: &str,
message_size: f64,
) -> Result<f64, AicError> {
let spec = &db.system_spec;
let sol_q = nccl_sol_ms(spec, dtype, num_gpus, operation, message_size);
if num_gpus <= 1 || sol_q <= 0.0 {
return Ok(sol_q);
}
let max_collected = match db
.communication
.nccl_empirical_max_num_gpus(dtype, operation)
{
Ok(max) => max,
Err(err) if err.is_missing_perf_data() => {
return Err(AicError::EmpiricalNotImplemented(format!(
"No NCCL data for operation '{operation}' ({}, num_gpus={num_gpus}).",
dtype.name()
)));
}
Err(err) => return Err(err),
};
let eff = num_gpus.min(max_collected);
let sol = |c: &[f64]| nccl_sol_ms(spec, dtype, eff, operation, c[0]);
let key = format!("nccl:{}:{operation}:{eff}", dtype.name());
let grid = db.util_grids.get_or_try_build(&key, || {
match db
.communication
.nccl_empirical_points(dtype, operation, eff)
{
Ok(points) => Ok(Some(UtilGrid::new(util_empirical::build_samples(
points, sol,
)))),
Err(err) if err.is_missing_perf_data() => Ok(None),
Err(err) => Err(err),
}
})?;
let query = [message_size];
let (latency, _) = util_empirical::estimate(sol_q, &query, grid.as_deref(), 1.0)?;
db.note_provenance(if eff != num_gpus {
util_empirical::ProvenanceTier::XShape
} else {
util_empirical::ProvenanceTier::Empirical
});
Ok(latency)
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct P2POp {
pub name: String,
pub scale_factor: f64,
pub pp_size: u32,
pub hidden_size: u32,
#[serde(default = "crate::operators::gemm::default_seq_split")]
pub seq_split: u32,
}
impl P2POp {
pub fn new(name: impl Into<String>, pp_size: u32, hidden_size: u32) -> Self {
Self {
name: name.into(),
scale_factor: 1.0,
pp_size,
hidden_size,
seq_split: 1,
}
}
pub fn query(&self, db: &PerfDatabase, x: u32) -> Result<PerformanceResult, AicError> {
if self.pp_size <= 1 {
return Ok(PerformanceResult::zero());
}
let spec = &db.system_spec;
let per_rank_tokens = x.div_ceil(self.seq_split.max(1)); let bytes = (per_rank_tokens as f64) * (self.hidden_size as f64) * 2.0;
let inter_bw = spec.node.inter_node_bw.max(1.0);
let result = match db.database_mode {
DatabaseMode::Sol | DatabaseMode::SolFull => {
PerformanceResult::sol(SolComponents::new(0.0, bytes / inter_bw * 1000.0))
}
_ => PerformanceResult::new(
(bytes / inter_bw + spec.node.p2p_latency) * 1000.0,
Source::Empirical,
),
};
Ok(result.clamp_non_negative().scaled(self.scale_factor))
}
}
fn p2p_bandwidth(spec: &SystemSpec, num_gpus: u32) -> f64 {
spec.get_p2p_bandwidth(num_gpus)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::perf_database::CommunicationTable;
use std::path::PathBuf;
const REPO_ROOT_HINT: &str = env!("CARGO_MANIFEST_DIR");
fn b200_vllm_db() -> PerfDatabase {
let systems_root = PathBuf::from(REPO_ROOT_HINT)
.join("../..")
.join("src/aiconfigurator_core/systems");
PerfDatabase::load(&systems_root, "b200_sxm", "vllm", "0.19.0").expect("db must load")
}
#[test]
fn custom_allreduce_empirical_matches_python_oracles() {
let mut db = b200_vllm_db();
db.database_mode = DatabaseMode::Empirical;
use util_empirical::ProvenanceTier;
let cases = [
(
8u32,
300_000u64,
0.0210877421663319,
ProvenanceTier::Empirical,
),
(8, 1024, 0.007716159820556641, ProvenanceTier::Empirical),
(16, 524_288, 0.1607595384120941, ProvenanceTier::XShape),
(2, 777_777, 0.019098769751423886, ProvenanceTier::Empirical),
(4, 65_536, 0.008213120102882384, ProvenanceTier::Empirical),
];
for (tp, size, _expected, tier) in cases {
db.reset_provenance();
let __r = query_custom_allreduce_table(&db, CommQuantMode::Half, tp, size as f64)
.expect("empirical query");
let (latency, source) = (__r.latency_ms, __r.source);
assert!(
latency.is_finite() && latency > 0.0,
"expected positive latency, got {latency}"
);
assert_eq!(source, Source::Empirical);
assert_eq!(
db.worst_provenance(),
tier,
"(tp={tp}, size={size}): wrong tier"
);
}
}
#[test]
fn custom_allreduce_missing_tp_raises_empirical_not_implemented() {
for mode in [DatabaseMode::Empirical, DatabaseMode::Hybrid] {
let mut db = b200_vllm_db();
db.database_mode = mode;
let result = query_custom_allreduce_table(&db, CommQuantMode::Half, 5, 1024 as f64);
assert!(
matches!(result, Err(AicError::EmpiricalNotImplemented(_))),
"{mode:?}: got {result:?}"
);
}
}
#[test]
fn custom_allreduce_hybrid_prefers_silicon() {
let mut db = b200_vllm_db();
db.database_mode = DatabaseMode::Hybrid;
let cases = [
(8u32, 300_000u64, 0.024691462737973777),
(16, 524_288, 0.16075953841209412),
];
for (tp, size, _expected) in cases {
let __r = query_custom_allreduce_table(&db, CommQuantMode::Half, tp, size as f64)
.expect("hybrid query");
let (latency, source) = (__r.latency_ms, __r.source);
assert!(
latency.is_finite() && latency > 0.0,
"expected positive latency, got {latency}"
);
assert_eq!(source, Source::Silicon);
}
}
#[test]
fn nccl_empirical_matches_python_oracles() {
let mut db = b200_vllm_db();
db.database_mode = DatabaseMode::Empirical;
use util_empirical::ProvenanceTier;
let cases = [
(
8u32,
"all_reduce",
300_000u64,
0.027067167868039803,
ProvenanceTier::Empirical,
),
(
4,
"all_gather",
10_000_000,
0.05871496201240777,
ProvenanceTier::Empirical,
),
(
32,
"all_reduce",
1_048_576,
0.31676464285714284,
ProvenanceTier::XShape,
),
(
8,
"reduce_scatter",
999,
0.015899137756552793,
ProvenanceTier::Empirical,
),
(
2,
"alltoall",
4096,
0.009470000000000001,
ProvenanceTier::Empirical,
),
];
for (num_gpus, op, msg, _expected, tier) in cases {
db.reset_provenance();
let __r = query_nccl_table(&db, CommQuantMode::Half, num_gpus, op, msg as f64)
.expect("empirical query");
let (latency, source) = (__r.latency_ms, __r.source);
assert!(
latency.is_finite() && latency > 0.0,
"expected positive latency, got {latency}"
);
assert_eq!(source, Source::Empirical);
assert_eq!(
db.worst_provenance(),
tier,
"({num_gpus}, {op}, {msg}): wrong tier"
);
}
}
#[test]
fn nccl_missing_gpu_count_raises_empirical_not_implemented() {
for mode in [DatabaseMode::Empirical, DatabaseMode::Hybrid] {
let mut db = b200_vllm_db();
db.database_mode = mode;
let result = query_nccl_table(&db, CommQuantMode::Half, 3, "all_reduce", 1024 as f64);
assert!(
matches!(result, Err(AicError::EmpiricalNotImplemented(_))),
"{mode:?}: got {result:?}"
);
}
}
#[test]
fn nccl_empirical_zero_sol_returns_zero_not_a_gap() {
let mut db = b200_vllm_db();
db.database_mode = DatabaseMode::Empirical;
let __r = query_nccl_table(&db, CommQuantMode::Half, 8, "broadcast", 1024 as f64)
.expect("no-op query");
let (latency, source) = (__r.latency_ms, __r.source);
assert_eq!(latency, 0.0);
assert_eq!(source, Source::Empirical);
let __r = query_nccl_table(&db, CommQuantMode::Half, 1, "all_reduce", 4096 as f64)
.expect("single rank");
let latency = __r.latency_ms;
assert_eq!(latency, 0.0);
let __r = query_custom_allreduce_table(&db, CommQuantMode::Half, 1, 4096 as f64)
.expect("single rank allreduce");
let latency = __r.latency_ms;
assert_eq!(latency, 0.0);
}
#[test]
fn custom_allreduce_nvl72_reroute_is_mode_aware() {
let nvl72_db = |mode: DatabaseMode| {
let mut db = b200_vllm_db();
db.tables_mut().system_spec.node.num_gpus_per_node = 72;
db.database_mode = mode;
db
};
let db = nvl72_db(DatabaseMode::Hybrid);
for (tp, size, _expected) in [
(8u32, 300_000u64, 0.02807729736328125),
(16, 524_288, 0.031017857142857142),
] {
let __r = query_custom_allreduce_table(&db, CommQuantMode::Half, tp, size as f64)
.expect("hybrid reroute");
let (latency, source) = (__r.latency_ms, __r.source);
assert!(
latency.is_finite() && latency > 0.0,
"expected positive latency, got {latency}"
);
assert_eq!(source, Source::Silicon);
}
let db = nvl72_db(DatabaseMode::Silicon);
let __r = query_custom_allreduce_table(&db, CommQuantMode::Half, 8, 300_000.0)
.expect("silicon reroute");
let (latency, source) = (__r.latency_ms, __r.source);
let scaled = db
.communication
.query_custom_allreduce_scaled(&db.system_spec, CommQuantMode::Half, 8, 300_000.0)
.expect("db-level reroute")
.latency;
assert!(
(latency - scaled).abs() < 1e-12,
"operator ({latency}) and DB-level ({scaled}) reroutes must agree"
);
assert_eq!(source, Source::Silicon);
let db = nvl72_db(DatabaseMode::Empirical);
let __r = query_custom_allreduce_table(&db, CommQuantMode::Half, 8, 300_000.0)
.expect("empirical never reroutes");
let (latency, source) = (__r.latency_ms, __r.source);
assert!(
latency.is_finite() && latency > 0.0,
"expected positive latency, got {latency}"
);
assert_eq!(source, Source::Empirical);
let mut db = b200_vllm_db();
{
let tables = db.tables_mut();
tables.system_spec.node.num_gpus_per_node = 72;
tables.communication = CommunicationTable::new(tables.data_root.clone(), None, None);
}
db.database_mode = DatabaseMode::Hybrid;
let result = query_custom_allreduce_table(&db, CommQuantMode::Half, 8, 300_000.0);
assert!(
matches!(result, Err(AicError::EmpiricalNotImplemented(_))),
"expected the NCCL empirical miss to propagate, got {result:?}"
);
}
#[test]
fn nccl_hybrid_prefers_silicon() {
let mut db = b200_vllm_db();
db.database_mode = DatabaseMode::Hybrid;
let cases = [
(8u32, "all_reduce", 300_000u64, 0.02807729736328125),
(32, "all_reduce", 1_048_576, 0.3167646428571429),
];
for (num_gpus, op, msg, _expected) in cases {
let __r = query_nccl_table(&db, CommQuantMode::Half, num_gpus, op, msg as f64)
.expect("hybrid query");
let (latency, source) = (__r.latency_ms, __r.source);
assert!(
latency.is_finite() && latency > 0.0,
"expected positive latency, got {latency}"
);
assert_eq!(source, Source::Silicon);
}
}
#[test]
fn communication_sol_mode_returns_bounds_with_sol_source() {
let mut db = b200_vllm_db();
db.database_mode = DatabaseMode::Sol;
let spec = db.system_spec.clone();
let ar = CustomAllReduceOp::new("ar", 1.0, 8192, 8);
let result = ar.query(&db, 128).expect("ar sol");
let expected = custom_allreduce_sol_ms(&spec, 8, 128.0 * 8192.0);
assert_eq!(result.latency_ms, expected);
assert_eq!(result.source, Source::Sol);
assert_eq!(result.energy_wms, 0.0);
let nccl = NcclOp::new("ag", 1.0, 8192.0, 8, "all_gather");
let result = nccl.query(&db, 128).expect("nccl sol");
let expected = nccl_sol_ms(&spec, CommQuantMode::Half, 8, "all_gather", 128.0 * 8192.0);
assert_eq!(result.latency_ms, expected);
assert_eq!(result.source, Source::Sol);
let single = NcclOp::new("ag1", 1.0, 8192.0, 1, "all_gather");
let result = single.query(&db, 128).expect("nccl single sol");
assert_eq!(result.latency_ms, 0.0);
assert_eq!(result.source, Source::Sol);
let p2p = P2POp::new("p2p", 2, 8192);
let result = p2p.query(&db, 128).expect("p2p sol");
let bytes = 128.0 * 8192.0 * 2.0;
assert_eq!(result.latency_ms, bytes / spec.node.inter_node_bw * 1000.0);
assert_eq!(result.source, Source::Sol);
db.database_mode = DatabaseMode::Silicon;
let empirical = p2p.query(&db, 128).expect("p2p silicon");
assert_eq!(
empirical.latency_ms,
(bytes / spec.node.inter_node_bw + spec.node.p2p_latency) * 1000.0
);
assert_eq!(empirical.source, Source::Empirical);
}
}