use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::sync::OnceLock;
use super::perf_interp::{LeafValue, Node, OpInterpConfig, PreparedGrid};
use super::{SourceResolver, kernel_source_ok};
use crate::common::error::AicError;
use crate::config::{PerfDbSources, PerfSource};
use crate::perf_database::parquet_loader::PerfReader;
pub struct StateSpaceTable {
data_root: PathBuf,
mamba2_sources: Vec<PerfSource>,
gdn_sources: Vec<PerfSource>,
kda_sources: Vec<PerfSource>,
vllm_024_gdn_aliases: bool,
sglang_sm100_gdn_flashinfer_lane: bool,
mamba2: OnceLock<Result<Mamba2Grids, AicError>>,
gdn: OnceLock<Result<GdnGrids, AicError>>,
kda: OnceLock<Result<KdaGrids, AicError>>,
}
struct Mamba2Grids {
by_keys: BTreeMap<Mamba2Key, PreparedGrid>,
}
struct GdnGrids {
by_keys: BTreeMap<GdnKey, PreparedGrid>,
}
struct KdaGrids {
by_keys: BTreeMap<KdaKey, PreparedGrid>,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct Mamba2Key {
kernel_source: String,
phase: String,
d_model: u32,
d_state: u32,
d_conv: u32,
nheads: u32,
head_dim: u32,
n_groups: u32,
chunk_size: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct GdnKey {
kernel_source: String,
phase: String,
d_model: u32,
d_conv: u32,
num_k_heads: u32,
head_k_dim: u32,
num_v_heads: u32,
head_v_dim: u32,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
struct KdaKey {
kernel_source: String,
phase: String,
d_model: u32,
d_conv: u32,
num_k_heads: u32,
head_k_dim: u32,
num_v_heads: u32,
head_v_dim: u32,
}
impl StateSpaceTable {
pub fn new(data_root: PathBuf, backend: &str, version: &str) -> Self {
Self::with_sources(
data_root,
backend,
version,
None,
&SourceResolver::fixed(PerfDbSources::default()),
)
.expect("fixed-map resolution is infallible")
}
pub fn with_sources(
data_root: PathBuf,
backend: &str,
version: &str,
sm_version: Option<u32>,
resolver: &SourceResolver,
) -> Result<Self, AicError> {
let mamba2_sources = resolver.sources_for("mamba2_perf.parquet", &data_root)?;
let gdn_sources = resolver.sources_for("gdn_perf.parquet", &data_root)?;
let kda_sources = resolver.sources_for("kda_perf.parquet", &data_root)?;
Ok(Self {
data_root,
mamba2_sources,
gdn_sources,
kda_sources,
vllm_024_gdn_aliases: backend == "vllm" && version == "0.24.0",
sglang_sm100_gdn_flashinfer_lane: backend == "sglang"
&& matches!(sm_version, Some(v) if (100..110).contains(&v)),
mamba2: OnceLock::new(),
gdn: OnceLock::new(),
kda: OnceLock::new(),
})
}
#[allow(clippy::too_many_arguments)]
pub fn query_mamba2(
&self,
kernel_source: &str,
phase: &str,
batch_size: u32,
seq_len: u32,
d_model: u32,
d_state: u32,
d_conv: u32,
nheads: u32,
head_dim: u32,
n_groups: u32,
chunk_size: u32,
sol: &dyn Fn(f64, f64) -> f64,
) -> Result<LeafValue, AicError> {
if phase == "generation" {
return Err(AicError::PerfDatabase(format!(
"Mamba2 generation data intentionally not used (matches Python v2 \
`load_mamba2_data` defaultdict bug in operations/mamba.py — generation \
leaves load empty, so every generation query degrades to SOL); \
operator must fall to SOL. ks={kernel_source}, d_model={d_model}"
)));
}
let grids = self.load_mamba2()?;
let key = Mamba2Key {
kernel_source: kernel_source.to_string(),
phase: phase.to_string(),
d_model,
d_state,
d_conv,
nheads,
head_dim,
n_groups,
chunk_size,
};
let node = match grids.by_keys.get(&key) {
Some(node) => node,
None => grids
.by_keys
.iter()
.find(|(k, _)| {
k.kernel_source == key.kernel_source
&& k.phase == key.phase
&& k.d_model == key.d_model
})
.map(|(_, node)| node)
.ok_or_else(|| missing("Mamba2", &self.data_root, format!("{key:?}")))?,
};
engine_query(node, phase, batch_size, seq_len, sol)
}
#[allow(clippy::too_many_arguments)]
pub fn query_gdn(
&self,
kernel_source: &str,
phase: &str,
batch_size: u32,
seq_len: u32,
d_model: u32,
d_conv: u32,
num_k_heads: u32,
head_k_dim: u32,
num_v_heads: u32,
head_v_dim: u32,
mamba_ssm_dtype: &str,
sol: &dyn Fn(f64, f64) -> f64,
) -> Result<LeafValue, AicError> {
let causal_conv = matches!(kernel_source, "causal_conv1d_fn" | "causal_conv1d_update");
let flashinfer_physical = kernel_source == "flashinfer_gated_delta_rule_decode";
let flashinfer_bf16_query = self.sglang_sm100_gdn_flashinfer_lane
&& mamba_ssm_dtype == "bfloat16"
&& phase == "generation";
let requires_flashinfer_alias =
flashinfer_bf16_query && kernel_source == "fused_sigmoid_gating_delta_rule_update";
let exact_flashinfer_query = flashinfer_bf16_query && flashinfer_physical;
if (flashinfer_physical && !exact_flashinfer_query)
|| (mamba_ssm_dtype != "float32"
&& !causal_conv
&& !requires_flashinfer_alias
&& !exact_flashinfer_query)
{
return Err(AicError::PerfDatabase(format!(
"GDN state-sensitive silicon row is not keyed by mamba_ssm_dtype; \
refusing kernel_source={kernel_source}, phase={phase}, \
mamba_ssm_dtype={mamba_ssm_dtype}"
)));
}
let grids = self.load_gdn()?;
let key = GdnKey {
kernel_source: kernel_source.to_string(),
phase: phase.to_string(),
d_model,
d_conv,
num_k_heads,
head_k_dim,
num_v_heads,
head_v_dim,
};
let aliases: &[&str] = if self.vllm_024_gdn_aliases {
match (key.kernel_source.as_str(), key.phase.as_str()) {
("chunk_gated_delta_rule", "context") => &[
"chunk_gated_delta_rule_flashinfer",
"chunk_gated_delta_rule_triton",
"chunk_gated_delta_rule_cutedsl",
],
("fused_sigmoid_gating_delta_rule_update", "generation") => {
&["fused_recurrent_gated_delta_rule_packed_decode"]
}
_ => &[],
}
} else if requires_flashinfer_alias {
&["flashinfer_gated_delta_rule_decode"]
} else {
&[]
};
let alias_matches: Vec<_> = aliases
.iter()
.filter_map(|alias| {
let mut alias_key = key.clone();
alias_key.kernel_source = (*alias).to_string();
grids.by_keys.get_key_value(&alias_key)
})
.collect();
if alias_matches.len() > 1 {
let sources: Vec<_> = alias_matches
.iter()
.map(|(alias_key, _)| alias_key.kernel_source.as_str())
.collect();
return Err(AicError::PerfDatabase(format!(
"ambiguous vLLM 0.24.0 GDN physical kernels for {key:?}: {}",
sources.join(", ")
)));
}
if let Some((_, node)) = alias_matches.first() {
return engine_query(node, phase, batch_size, seq_len, sol);
}
if requires_flashinfer_alias {
return Err(missing(
"GDN FlashInfer BF16 alias",
&self.data_root,
format!("{key:?}"),
));
}
let node = match grids.by_keys.get(&key) {
Some(node) => node,
None => return Err(missing("GDN", &self.data_root, format!("{key:?}"))),
};
engine_query(node, phase, batch_size, seq_len, sol)
}
#[allow(clippy::too_many_arguments)]
pub fn query_kda(
&self,
kernel_source: &str,
phase: &str,
batch_size: u32,
seq_len: u32,
d_model: u32,
d_conv: u32,
num_k_heads: u32,
head_k_dim: u32,
num_v_heads: u32,
head_v_dim: u32,
sol: &dyn Fn(f64, f64) -> f64,
) -> Result<LeafValue, AicError> {
let grids = self.load_kda()?;
let key = KdaKey {
kernel_source: kernel_source.to_string(),
phase: phase.to_string(),
d_model,
d_conv,
num_k_heads,
head_k_dim,
num_v_heads,
head_v_dim,
};
let node = match grids.by_keys.get(&key) {
Some(node) => node,
None => {
let nearest = grids
.by_keys
.iter()
.filter(|(k, _)| {
k.kernel_source == key.kernel_source
&& k.phase == key.phase
&& k.d_model == key.d_model
})
.min_by_key(|(k, _)| (k.num_v_heads as i64 - key.num_v_heads as i64).abs());
match nearest {
Some((_, node)) => node,
None => return Err(missing("KDA", &self.data_root, format!("{key:?}"))),
}
}
};
engine_query(node, phase, batch_size, seq_len, sol)
}
fn load_mamba2(&self) -> Result<&Mamba2Grids, AicError> {
let cell = self
.mamba2
.get_or_init(|| load_mamba2_parquet(&self.mamba2_sources));
cell.as_ref().map_err(clone_err)
}
fn load_gdn(&self) -> Result<&GdnGrids, AicError> {
let cell = self.gdn.get_or_init(|| load_gdn_parquet(&self.gdn_sources));
cell.as_ref().map_err(clone_err)
}
fn load_kda(&self) -> Result<&KdaGrids, AicError> {
let cell = self.kda.get_or_init(|| load_kda_parquet(&self.kda_sources));
cell.as_ref().map_err(clone_err)
}
pub fn kda_has_verify_rows(&self, kernel_source: &str) -> bool {
match self.load_kda() {
Ok(grids) => grids
.by_keys
.keys()
.any(|k| k.kernel_source == kernel_source && k.phase == "verify"),
Err(_) => false,
}
}
#[allow(clippy::too_many_arguments)]
pub fn kda_has_key(
&self,
kernel_source: &str,
phase: &str,
d_model: u32,
d_conv: u32,
num_k_heads: u32,
head_k_dim: u32,
num_v_heads: u32,
head_v_dim: u32,
) -> bool {
match self.load_kda() {
Ok(grids) => grids.by_keys.contains_key(&KdaKey {
kernel_source: kernel_source.to_string(),
phase: phase.to_string(),
d_model,
d_conv,
num_k_heads,
head_k_dim,
num_v_heads,
head_v_dim,
}),
Err(_) => false,
}
}
}
fn engine_query(
node: &PreparedGrid,
phase: &str,
batch_size: u32,
seq_len: u32,
sol: &dyn Fn(f64, f64) -> f64,
) -> Result<LeafValue, AicError> {
if phase == "generation" {
let s = seq_len as f64;
let sol1 = move |c: &[f64]| sol(c[0], s);
let cfg = OpInterpConfig::grid(&["batch"], &sol1);
node.query_value(&cfg, &[batch_size as f64])
} else {
if seq_len == 0 {
return Err(AicError::PerfDatabase(
"state-space context/verify query needs seq_len > 0".to_string(),
));
}
let sol2 = move |c: &[f64]| sol(c[0], c[1]);
let cfg = OpInterpConfig::grid(&["batch", "seq_len"], &sol2);
node.query_value(&cfg, &[batch_size as f64, seq_len as f64])
}
}
fn insert_first_wins(root: &mut Node, path: &[u32], value: LeafValue) {
let Node::Branch(map) = root else {
return; };
if path.len() == 1 {
map.entry(path[0]).or_insert(Node::Leaf(value));
} else {
let child = map.entry(path[0]).or_insert_with(Node::branch);
insert_first_wins(child, &path[1..], value);
}
}
fn prepare_nodes<K: Ord>(by_keys: BTreeMap<K, Node>) -> BTreeMap<K, PreparedGrid> {
by_keys
.into_iter()
.map(|(key, node)| (key, PreparedGrid::new(node)))
.collect()
}
fn load_mamba2_parquet(sources: &[PerfSource]) -> Result<Mamba2Grids, AicError> {
let mut by_keys: BTreeMap<Mamba2Key, Node> = BTreeMap::new();
let mut any_source = false;
for source in sources {
let path = source.path();
if !path.exists() {
continue;
}
any_source = true;
let reader = PerfReader::open(path)?;
let kernel_source_col = reader.col("kernel_source")?;
let phase_col = reader.col("phase")?;
let batch_size_col = reader.col("batch_size")?;
let seq_len_col = reader.col("seq_len")?;
let d_model_col = reader.col("d_model")?;
let d_state_col = reader.col("d_state")?;
let d_conv_col = reader.col("d_conv")?;
let nheads_col = reader.col("nheads")?;
let head_dim_col = reader.col("head_dim")?;
let n_groups_col = reader.col("n_groups")?;
let chunk_size_col = reader.col("chunk_size")?;
let latency_col = reader.col("latency")?;
let power_col = reader.col_optional("power");
let ks_col = reader.col_optional("kernel_source");
for row in reader.rows()? {
let row = row?;
if !kernel_source_ok(source.kernel_sources(), ks_col, &row)? {
continue;
}
let phase = row.str_owned(phase_col)?;
let key = Mamba2Key {
kernel_source: row.str_owned(kernel_source_col)?,
phase: phase.clone(),
d_model: row.u32(d_model_col)?,
d_state: row.u32(d_state_col)?,
d_conv: row.u32(d_conv_col)?,
nheads: row.u32(nheads_col)?,
head_dim: row.u32(head_dim_col)?,
n_groups: row.u32(n_groups_col)?,
chunk_size: row.u32(chunk_size_col)?,
};
let node = by_keys.entry(key).or_insert_with(Node::branch);
let batch = row.u32(batch_size_col)?;
let latency = row.f64(latency_col)?;
let power = row.f64_optional(power_col)?.unwrap_or(0.0);
let leaf = LeafValue::with_power(latency, power);
if phase == "generation" {
insert_first_wins(node, &[batch], leaf);
} else {
insert_first_wins(node, &[batch, row.u32(seq_len_col)?], leaf);
}
}
}
if !any_source || by_keys.is_empty() {
return Err(AicError::PerfDatabase(format!(
"no Mamba2 rows loaded from {} source(s) (first: {})",
sources.len(),
sources
.first()
.map(|s| s.path().display().to_string())
.unwrap_or_default()
)));
}
Ok(Mamba2Grids {
by_keys: prepare_nodes(by_keys),
})
}
pub(crate) fn normalize_gdn_kernel_source(kernel_source: String) -> String {
match kernel_source.as_str() {
"fused_recurrent_gated_delta_rule" | "fused_recurrent_gated_delta_rule_packed_decode" => {
"fused_sigmoid_gating_delta_rule_update".to_string()
}
_ => kernel_source,
}
}
fn load_gdn_parquet(sources: &[PerfSource]) -> Result<GdnGrids, AicError> {
let mut by_keys: BTreeMap<GdnKey, Node> = BTreeMap::new();
let mut any_source = false;
for source in sources {
let path = source.path();
if !path.exists() {
continue;
}
any_source = true;
let reader = PerfReader::open(path)?;
let kernel_source_col = reader.col("kernel_source")?;
let phase_col = reader.col("phase")?;
let batch_size_col = reader.col("batch_size")?;
let seq_len_col = reader.col("seq_len")?;
let d_model_col = reader.col("d_model")?;
let d_conv_col = reader.col("d_conv")?;
let num_k_heads_col = reader.col("num_k_heads")?;
let head_k_dim_col = reader.col("head_k_dim")?;
let num_v_heads_col = reader.col("num_v_heads")?;
let head_v_dim_col = reader.col("head_v_dim")?;
let latency_col = reader.col("latency")?;
let power_col = reader.col_optional("power");
let ks_col = reader.col_optional("kernel_source");
for row in reader.rows()? {
let row = row?;
if !kernel_source_ok(source.kernel_sources(), ks_col, &row)? {
continue;
}
let phase = row.str_owned(phase_col)?;
let key = GdnKey {
kernel_source: normalize_gdn_kernel_source(row.str_owned(kernel_source_col)?),
phase: phase.clone(),
d_model: row.u32(d_model_col)?,
d_conv: row.u32(d_conv_col)?,
num_k_heads: row.u32(num_k_heads_col)?,
head_k_dim: row.u32(head_k_dim_col)?,
num_v_heads: row.u32(num_v_heads_col)?,
head_v_dim: row.u32(head_v_dim_col)?,
};
let node = by_keys.entry(key).or_insert_with(Node::branch);
let batch = row.u32(batch_size_col)?;
let latency = row.f64(latency_col)?;
let power = row.f64_optional(power_col)?.unwrap_or(0.0);
let leaf = LeafValue::with_power(latency, power);
if phase == "generation" {
insert_first_wins(node, &[batch], leaf);
} else {
insert_first_wins(node, &[batch, row.u32(seq_len_col)?], leaf);
}
}
}
if !any_source || by_keys.is_empty() {
return Err(AicError::PerfDatabase(format!(
"no GDN rows loaded from {} source(s) (first: {})",
sources.len(),
sources
.first()
.map(|s| s.path().display().to_string())
.unwrap_or_default()
)));
}
Ok(GdnGrids {
by_keys: prepare_nodes(by_keys),
})
}
fn load_kda_parquet(sources: &[PerfSource]) -> Result<KdaGrids, AicError> {
let mut by_keys: BTreeMap<KdaKey, Node> = BTreeMap::new();
let mut any_source = false;
for source in sources {
let path = source.path();
if !path.exists() {
continue;
}
any_source = true;
let reader = PerfReader::open(path)?;
let kernel_source_col = reader.col("kernel_source")?;
let phase_col = reader.col("phase")?;
let batch_size_col = reader.col("batch_size")?;
let seq_len_col = reader.col("seq_len")?;
let d_model_col = reader.col("d_model")?;
let d_conv_col = reader.col("d_conv")?;
let num_k_heads_col = reader.col("num_k_heads")?;
let head_k_dim_col = reader.col("head_k_dim")?;
let num_v_heads_col = reader.col("num_v_heads")?;
let head_v_dim_col = reader.col("head_v_dim")?;
let latency_col = reader.col("latency")?;
let power_col = reader.col_optional("power");
let ks_col = reader.col_optional("kernel_source");
for row in reader.rows()? {
let row = row?;
if !kernel_source_ok(source.kernel_sources(), ks_col, &row)? {
continue;
}
let phase = row.str_owned(phase_col)?;
let key = KdaKey {
kernel_source: row.str_owned(kernel_source_col)?,
phase: phase.clone(),
d_model: row.u32(d_model_col)?,
d_conv: row.u32(d_conv_col)?,
num_k_heads: row.u32(num_k_heads_col)?,
head_k_dim: row.u32(head_k_dim_col)?,
num_v_heads: row.u32(num_v_heads_col)?,
head_v_dim: row.u32(head_v_dim_col)?,
};
let node = by_keys.entry(key).or_insert_with(Node::branch);
let batch = row.u32(batch_size_col)?;
let latency = row.f64(latency_col)?;
let power = row.f64_optional(power_col)?.unwrap_or(0.0);
let leaf = LeafValue::with_power(latency, power);
if phase == "context" || phase == "verify" {
insert_first_wins(node, &[batch, row.u32(seq_len_col)?], leaf);
} else {
insert_first_wins(node, &[batch], leaf);
}
}
}
if !any_source || by_keys.is_empty() {
return Err(AicError::PerfDatabase(format!(
"no KDA rows loaded from {} source(s) (first: {})",
sources.len(),
sources
.first()
.map(|s| s.path().display().to_string())
.unwrap_or_default()
)));
}
Ok(KdaGrids {
by_keys: prepare_nodes(by_keys),
})
}
fn missing(table: &str, data_root: &Path, descriptor: String) -> AicError {
AicError::PerfDatabase(format!(
"{table} data missing for {descriptor} at {}",
data_root.display()
))
}
fn clone_err(err: &AicError) -> AicError {
AicError::PerfDatabase(err.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::common::system_spec::SystemSpec;
fn data_root(rel: &str) -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../python/aisimulate/src/aiconfigurator_core/systems/data")
.join(rel)
}
fn h100_sxm_mem_bw() -> f64 {
let yaml = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("../../python/aisimulate/src/aiconfigurator_core/systems/h100_sxm.yaml");
SystemSpec::load(&yaml)
.expect("h100_sxm.yaml must parse")
.gpu
.mem_bw
}
fn dummy_sol(_b: f64, _s: f64) -> f64 {
1.0
}
#[test]
fn first_wins_keeps_existing_leaf_at_mixed_depth() {
let first = LeafValue::latency_only(1.0);
let mut node = Node::branch();
insert_first_wins(&mut node, &[4], first);
insert_first_wins(&mut node, &[4, 8], LeafValue::latency_only(2.0));
let Node::Branch(root) = node else {
panic!("expected root branch");
};
match root.get(&4) {
Some(Node::Leaf(actual)) => assert_eq!(*actual, first),
other => panic!("expected first leaf, got {other:?}"),
}
}
fn in_memory_gdn_table(
backend: &str,
version: &str,
rows: &[(&str, &str, u32, f64)],
) -> StateSpaceTable {
let mut by_keys: BTreeMap<GdnKey, Node> = BTreeMap::new();
for &(kernel_source, phase, num_v_heads, latency) in rows {
let key = GdnKey {
kernel_source: kernel_source.to_string(),
phase: phase.to_string(),
d_model: 5120,
d_conv: 4,
num_k_heads: 16,
head_k_dim: 128,
num_v_heads,
head_v_dim: 128,
};
let node = by_keys.entry(key).or_insert_with(Node::branch);
let leaf = LeafValue::latency_only(latency);
if phase == "generation" {
insert_first_wins(node, &[1], leaf);
} else {
insert_first_wins(node, &[1, 1024], leaf);
}
}
let table = StateSpaceTable::new(PathBuf::from("test-data"), backend, version);
assert!(
table
.gdn
.set(Ok(GdnGrids {
by_keys: prepare_nodes(by_keys),
}))
.is_ok()
);
table
}
fn query_gdn_test_shape(
table: &StateSpaceTable,
kernel_source: &str,
phase: &str,
num_v_heads: u32,
) -> Result<f64, AicError> {
query_gdn_test_shape_with_dtype(table, kernel_source, phase, num_v_heads, "float32")
}
fn query_gdn_test_shape_with_dtype(
table: &StateSpaceTable,
kernel_source: &str,
phase: &str,
num_v_heads: u32,
mamba_ssm_dtype: &str,
) -> Result<f64, AicError> {
table
.query_gdn(
kernel_source,
phase,
1,
1024,
5120,
4,
16,
128,
num_v_heads,
128,
mamba_ssm_dtype,
&dummy_sol,
)
.map(|v| v.latency)
}
#[test]
fn vllm_024_gdn_resolves_context_and_generation_physical_aliases() {
for source in [
"chunk_gated_delta_rule_flashinfer",
"chunk_gated_delta_rule_triton",
"chunk_gated_delta_rule_cutedsl",
] {
let table = in_memory_gdn_table("vllm", "0.24.0", &[(source, "context", 48, 2.0)]);
assert_eq!(
query_gdn_test_shape(&table, "chunk_gated_delta_rule", "context", 48).unwrap(),
2.0
);
}
let table = in_memory_gdn_table(
"vllm",
"0.24.0",
&[(
"fused_recurrent_gated_delta_rule_packed_decode",
"generation",
48,
3.0,
)],
);
assert_eq!(
query_gdn_test_shape(
&table,
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
)
.unwrap(),
3.0
);
}
#[test]
fn gdn_causal_conv_rows_are_state_dtype_independent() {
let table = in_memory_gdn_table(
"sglang",
"0.5.14",
&[
("causal_conv1d_fn", "context", 48, 2.0),
("causal_conv1d_update", "generation", 48, 3.0),
],
);
for dtype in ["bfloat16", "float16"] {
assert_eq!(
query_gdn_test_shape_with_dtype(&table, "causal_conv1d_fn", "context", 48, dtype,)
.unwrap(),
2.0
);
assert_eq!(
query_gdn_test_shape_with_dtype(
&table,
"causal_conv1d_update",
"generation",
48,
dtype,
)
.unwrap(),
3.0
);
}
}
#[test]
fn gdn_context_scan_rows_require_fp32_state() {
let table = in_memory_gdn_table(
"sglang",
"0.5.14",
&[("chunk_gated_delta_rule", "context", 48, 2.0)],
);
assert_eq!(
query_gdn_test_shape_with_dtype(
&table,
"chunk_gated_delta_rule",
"context",
48,
"float32"
)
.unwrap(),
2.0
);
for dtype in ["bfloat16", "float16"] {
assert!(
query_gdn_test_shape_with_dtype(
&table,
"chunk_gated_delta_rule",
"context",
48,
dtype
)
.is_err()
);
}
}
#[test]
fn vllm_024_gdn_own_physical_lane_wins_over_logical_lane() {
let table = in_memory_gdn_table(
"vllm",
"0.24.0",
&[
("chunk_gated_delta_rule", "context", 48, 1.0),
("chunk_gated_delta_rule_flashinfer", "context", 48, 2.0),
],
);
assert_eq!(
query_gdn_test_shape(&table, "chunk_gated_delta_rule", "context", 48).unwrap(),
2.0
);
}
#[test]
fn gdn_physical_aliases_are_vllm_024_only() {
for (backend, version) in [("vllm", "0.23.0"), ("sglang", "0.24.0")] {
let table = in_memory_gdn_table(
backend,
version,
&[("chunk_gated_delta_rule_flashinfer", "context", 48, 2.0)],
);
assert!(query_gdn_test_shape(&table, "chunk_gated_delta_rule", "context", 48).is_err());
}
}
#[test]
fn vllm_024_gdn_ambiguous_exact_aliases_error() {
let table = in_memory_gdn_table(
"vllm",
"0.24.0",
&[
("chunk_gated_delta_rule", "context", 48, 1.0),
("chunk_gated_delta_rule_flashinfer", "context", 48, 2.0),
("chunk_gated_delta_rule_triton", "context", 48, 3.0),
],
);
match query_gdn_test_shape(&table, "chunk_gated_delta_rule", "context", 48) {
Err(AicError::PerfDatabase(message)) => {
assert!(message.contains("ambiguous vLLM 0.24.0 GDN physical kernels"));
assert!(message.contains("chunk_gated_delta_rule_flashinfer"));
assert!(message.contains("chunk_gated_delta_rule_triton"));
}
other => panic!("expected an explicit ambiguity error, got {other:?}"),
}
}
#[test]
fn vllm_024_gdn_alias_has_no_nearest_shape_fallback() {
let table = in_memory_gdn_table(
"vllm",
"0.24.0",
&[("chunk_gated_delta_rule_flashinfer", "context", 32, 2.0)],
);
assert!(query_gdn_test_shape(&table, "chunk_gated_delta_rule", "context", 48).is_err());
}
#[test]
fn vllm_024_gdn_does_not_borrow_nearest_shape_within_logical_source() {
let table = in_memory_gdn_table(
"vllm",
"0.24.0",
&[
("chunk_gated_delta_rule_flashinfer", "context", 32, 2.0),
("chunk_gated_delta_rule", "context", 16, 4.0),
("chunk_gated_delta_rule", "context", 64, 5.0),
],
);
assert!(query_gdn_test_shape(&table, "chunk_gated_delta_rule", "context", 48).is_err());
}
fn in_memory_gdn_table_with_sm(
backend: &str,
version: &str,
sm_version: Option<u32>,
rows: &[(&str, &str, u32, f64)],
) -> StateSpaceTable {
let mut by_keys: BTreeMap<GdnKey, Node> = BTreeMap::new();
for &(kernel_source, phase, num_v_heads, latency) in rows {
let key = GdnKey {
kernel_source: kernel_source.to_string(),
phase: phase.to_string(),
d_model: 5120,
d_conv: 4,
num_k_heads: 16,
head_k_dim: 128,
num_v_heads,
head_v_dim: 128,
};
let node = by_keys.entry(key).or_insert_with(Node::branch);
let leaf = LeafValue::latency_only(latency);
if phase == "generation" {
insert_first_wins(node, &[1], leaf);
} else {
insert_first_wins(node, &[1, 1024], leaf);
}
}
let table = StateSpaceTable::with_sources(
PathBuf::from("test-data"),
backend,
version,
sm_version,
&SourceResolver::fixed(PerfDbSources::default()),
)
.expect("fixed-map resolution is infallible");
assert!(
table
.gdn
.set(Ok(GdnGrids {
by_keys: prepare_nodes(by_keys),
}))
.is_ok()
);
table
}
#[test]
fn sglang_sm100_gdn_prefers_flashinfer_decode_lane_for_bf16_state() {
let table = in_memory_gdn_table_with_sm(
"sglang",
"0.5.14",
Some(103),
&[
(
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
4.0,
),
("flashinfer_gated_delta_rule_decode", "generation", 48, 2.1),
],
);
assert_eq!(
query_gdn_test_shape_with_dtype(
&table,
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
"bfloat16"
)
.unwrap(),
2.1
);
}
#[test]
fn sglang_sm100_gdn_keeps_fla_lane_for_fp32_state_even_if_flashinfer_present() {
let table = in_memory_gdn_table_with_sm(
"sglang",
"0.5.14",
Some(103),
&[
(
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
4.0,
),
("flashinfer_gated_delta_rule_decode", "generation", 48, 2.1),
],
);
assert_eq!(
query_gdn_test_shape(
&table,
"fused_sigmoid_gating_delta_rule_update",
"generation",
48
)
.unwrap(),
4.0
);
}
#[test]
fn sglang_sm120_gdn_uses_fla_rows_only_for_fp32_state() {
let table = in_memory_gdn_table_with_sm(
"sglang",
"0.5.14",
Some(120),
&[
(
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
4.0,
),
("flashinfer_gated_delta_rule_decode", "generation", 48, 2.1),
],
);
assert_eq!(
query_gdn_test_shape_with_dtype(
&table,
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
"float32"
)
.unwrap(),
4.0
);
for dtype in ["bfloat16", "float16"] {
assert!(
query_gdn_test_shape_with_dtype(
&table,
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
dtype
)
.is_err()
);
}
}
#[test]
fn sglang_sm100_gdn_misses_when_required_flashinfer_alias_is_absent() {
let table = in_memory_gdn_table_with_sm(
"sglang",
"0.5.14",
Some(103),
&[(
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
4.0,
)],
);
assert!(
query_gdn_test_shape_with_dtype(
&table,
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
"bfloat16"
)
.is_err()
);
}
#[test]
fn sglang_sm90_gdn_uses_fla_rows_only_for_fp32_state() {
let table = in_memory_gdn_table_with_sm(
"sglang",
"0.5.10",
Some(90),
&[
(
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
4.0,
),
("flashinfer_gated_delta_rule_decode", "generation", 48, 2.1),
],
);
assert_eq!(
query_gdn_test_shape_with_dtype(
&table,
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
"float32"
)
.unwrap(),
4.0
);
for dtype in ["bfloat16", "float16"] {
assert!(
query_gdn_test_shape_with_dtype(
&table,
"fused_sigmoid_gating_delta_rule_update",
"generation",
48,
dtype
)
.is_err()
);
}
}
fn in_memory_kda_table(rows: &[(&str, &str, u32, f64)]) -> StateSpaceTable {
let mut by_keys: BTreeMap<KdaKey, Node> = BTreeMap::new();
for &(kernel_source, phase, num_v_heads, latency) in rows {
let key = KdaKey {
kernel_source: kernel_source.to_string(),
phase: phase.to_string(),
d_model: 4096,
d_conv: 4,
num_k_heads: 16,
head_k_dim: 128,
num_v_heads,
head_v_dim: 128,
};
let node = by_keys.entry(key).or_insert_with(Node::branch);
let leaf = LeafValue::latency_only(latency);
if phase == "generation" {
insert_first_wins(node, &[1], leaf);
} else {
insert_first_wins(node, &[1, 4], leaf);
}
}
let table = StateSpaceTable::new(PathBuf::from("test-data"), "sglang", "0.5.14");
assert!(
table
.kda
.set(Ok(KdaGrids {
by_keys: prepare_nodes(by_keys),
}))
.is_ok()
);
table
}
fn query_kda_test_shape(
table: &StateSpaceTable,
kernel_source: &str,
phase: &str,
num_v_heads: u32,
) -> Result<f64, AicError> {
table
.query_kda(
kernel_source,
phase,
1,
4,
4096,
4,
16,
128,
num_v_heads,
128,
&dummy_sol,
)
.map(|v| v.latency)
}
#[test]
fn kda_verify_is_a_two_axis_grid_and_generation_one_axis() {
let table = in_memory_kda_table(&[
("fused_sigmoid_gating_delta_rule_update", "verify", 16, 2.5),
("fused_recurrent_kda_packed_decode", "generation", 16, 1.5),
]);
assert_eq!(
query_kda_test_shape(
&table,
"fused_sigmoid_gating_delta_rule_update",
"verify",
16
)
.unwrap(),
2.5
);
assert_eq!(
query_kda_test_shape(
&table,
"fused_recurrent_kda_packed_decode",
"generation",
16
)
.unwrap(),
1.5
);
}
#[test]
fn kda_nearest_shard_fallback_has_no_alias_sources() {
let table = in_memory_kda_table(&[
("chunk_kda", "context", 8, 4.0),
("chunk_kda", "context", 32, 5.0),
]);
assert_eq!(
query_kda_test_shape(&table, "chunk_kda", "context", 24).unwrap(),
5.0
);
let table = in_memory_kda_table(&[("chunk_kda_with_fused_gate", "context", 16, 2.0)]);
assert!(query_kda_test_shape(&table, "chunk_kda", "context", 16).is_err());
}
#[test]
fn state_space_loaders_smoke() {
let root = data_root("b200_sxm/vllm/0.24.0");
let table = StateSpaceTable::new(root, "vllm", "0.24.0");
let _ = table
.query_gdn(
"causal_conv1d_fn",
"prefill",
1,
1024,
4096,
4,
16,
128,
32,
128,
"float32",
&dummy_sol,
)
.err();
}
#[test]
fn gdn_table_finds_qwen35_27b_conv1d_update() {
let root = data_root("b200_sxm/vllm/0.24.0");
let table = StateSpaceTable::new(root, "vllm", "0.24.0");
let r = table.query_gdn(
"causal_conv1d_update",
"generation",
1,
1,
5120,
4,
16,
128,
48,
128,
"float32",
&dummy_sol,
);
eprintln!("query: {r:?}");
assert!(r.is_ok(), "expected silicon lookup to succeed: {r:?}");
let latency = r.unwrap().latency;
assert!(latency > 0.0, "non-zero latency: {latency}");
eprintln!("latency: {latency}");
}
#[test]
fn gdn_energy_matches_python_oracle() {
use crate::perf_database::energy_test_fixtures::{Col, write_parquet};
let tmp = tempfile::tempdir().expect("tmpdir");
write_parquet(
&tmp.path().join("gdn_perf.parquet"),
&[
Col::Str("kernel_source", vec!["causal_conv1d_fn"; 2]),
Col::Str("phase", vec!["context", "context"]),
Col::I64("batch_size", vec![1, 1]),
Col::I64("seq_len", vec![1024, 2048]),
Col::I64("d_model", vec![2048, 2048]),
Col::I64("d_conv", vec![4, 4]),
Col::I64("num_k_heads", vec![16, 16]),
Col::I64("head_k_dim", vec![128, 128]),
Col::I64("num_v_heads", vec![32, 32]),
Col::I64("head_v_dim", vec![128, 128]),
Col::F64("latency", vec![1.0, 3.0]),
Col::F64("power", vec![100.0, 200.0]),
],
);
let table = StateSpaceTable::new(tmp.path().to_path_buf(), "vllm", "1.0");
let v = table
.query_gdn(
"causal_conv1d_fn",
"context",
1,
1536,
2048,
4,
16,
128,
32,
128,
"float32",
&dummy_sol,
)
.unwrap();
assert!((v.latency - 2.0).abs() < 1e-9, "latency {}", v.latency);
assert!(
(v.energy - 300.0).abs() < 1e-9 * 300.0,
"energy {}",
v.energy
);
}
}