use fuel_ir::dispatch::OpKind;
use fuel_ir::{BackendId, DType};
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct ImplId {
pub backend: BackendId,
pub op: OpKind,
pub dtypes: Vec<DType>,
pub kernel_source: String,
pub kernel_revision_hash: u64,
}
const VENDOR_SOURCES: &[&str] = &[
"cublas", "cudnn", "cutlass", "rocblas", "mkl", "aocl", "onednn",
];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImplClass<'a> {
Baracuda { symbol: &'a str },
Vendor { which: &'a str },
FuelNative { which: &'a str },
}
impl ImplId {
pub fn classify(&self) -> ImplClass<'_> {
let src = self.kernel_source.as_str();
if src == "baracuda" {
ImplClass::Baracuda { symbol: src }
} else if VENDOR_SOURCES.contains(&src) {
ImplClass::Vendor { which: src }
} else {
ImplClass::FuelNative { which: src }
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use fuel_ir::dispatch::OpKind;
fn id(kernel_source: &str, backend: BackendId) -> ImplId {
ImplId {
backend,
op: OpKind::MatMul,
dtypes: vec![DType::F16, DType::F16, DType::F16],
kernel_source: kernel_source.into(),
kernel_revision_hash: 0xabc,
}
}
#[test]
fn baracuda_cuda_kernel_classifies_as_baracuda() {
assert_eq!(
id("baracuda", BackendId::Cuda).classify(),
ImplClass::Baracuda { symbol: "baracuda" },
);
}
#[test]
fn vendor_sources_classify_as_vendor() {
for v in ["cublas", "cudnn", "mkl", "aocl"] {
assert_eq!(
id(v, BackendId::Cuda).classify(),
ImplClass::Vendor { which: v },
"{v} must classify as Vendor",
);
}
}
#[test]
fn portable_and_unknown_classify_as_fuel_native() {
assert_eq!(
id("portable-cpu", BackendId::Cpu).classify(),
ImplClass::FuelNative {
which: "portable-cpu"
},
);
assert_eq!(
id("slang", BackendId::Vulkan).classify(),
ImplClass::FuelNative { which: "slang" },
);
}
#[test]
fn impl_id_serializes_five_separable_fields() {
let json = serde_json::to_string(&id("baracuda", BackendId::Cuda)).expect("serialize");
for field in [
"backend",
"op",
"dtypes",
"kernel_source",
"kernel_revision_hash",
] {
assert!(
json.contains(field),
"ImplId wire form must carry `{field}` as its own field"
);
}
let back: ImplId = serde_json::from_str(&json).expect("deserialize");
assert_eq!(back, id("baracuda", BackendId::Cuda));
}
}