use std::sync::Arc;
use onnx_runtime_ep_api::{OpKey, OpRegistry};
use crate::runtime::CudaRuntime;
pub mod attention;
pub mod cast;
pub mod elementwise;
pub mod gemm;
pub mod matmul;
pub mod normalization;
pub mod pointwise;
pub mod reduce;
pub mod softmax;
use elementwise::{BinaryFactory, BinaryOp, UnaryFactory, UnaryOp};
use pointwise::{
CmpFactory, CmpOp, LogicalFactory, LogicalOp, NotFactory, UnaryMathFactory, UnaryMathOp,
};
pub const CUDA_COVERED_OPS: &[&str] = &[
"MatMul", "Gemm", "Relu", "Sqrt", "Erf", "Tanh", "Sigmoid", "Gelu", "Add", "Sub", "Mul", "Div",
"Pow", "Min", "Max", "Attention", "Softmax", "LayerNormalization", "SkipLayerNormalization",
"SimplifiedLayerNormalization", "RMSNormalization", "Cast", "CastLike", "ReduceSum",
"ReduceMean", "ReduceMax", "ReduceMin", "Abs", "Neg", "Reciprocal", "Exp", "Log", "Sign",
"Floor", "Ceil", "Round", "Sin", "Cos", "Softplus", "Not", "And", "Or", "Xor", "Equal",
"Greater", "Less", "GreaterOrEqual", "LessOrEqual",
];
pub fn build_cuda_registry(runtime: Arc<CudaRuntime>) -> OpRegistry {
let mut reg = OpRegistry::new();
reg.register(
OpKey::new("MatMul", "", 1),
Box::new(matmul::MatMulFactory {
runtime: runtime.clone(),
}),
);
reg.register(
OpKey::new("Gemm", "", 1),
Box::new(gemm::GemmFactory {
runtime: runtime.clone(),
}),
);
for (op_type, domain, op) in [
("Relu", "", UnaryOp::Relu),
("Sqrt", "", UnaryOp::Sqrt),
("Erf", "", UnaryOp::Erf),
("Tanh", "", UnaryOp::Tanh),
("Sigmoid", "", UnaryOp::Sigmoid),
("Gelu", "com.microsoft", UnaryOp::Gelu),
] {
reg.register(
OpKey::new(op_type, domain, 1),
Box::new(UnaryFactory {
op,
runtime: runtime.clone(),
}),
);
}
for (op_type, op) in [
("Add", BinaryOp::Add),
("Sub", BinaryOp::Sub),
("Mul", BinaryOp::Mul),
("Div", BinaryOp::Div),
("Pow", BinaryOp::Pow),
("Min", BinaryOp::Min),
("Max", BinaryOp::Max),
] {
reg.register(
OpKey::new(op_type, "", 1),
Box::new(BinaryFactory {
op,
runtime: runtime.clone(),
}),
);
}
reg.register(
OpKey::new("Attention", "com.microsoft", 1),
Box::new(attention::AttentionFactory {
runtime: runtime.clone(),
}),
);
reg.register(
OpKey::new("Softmax", "", 1),
Box::new(softmax::SoftmaxLegacyFactory {
runtime: runtime.clone(),
}),
);
reg.register(
OpKey::new("Softmax", "", 13),
Box::new(softmax::SoftmaxFactory {
runtime: runtime.clone(),
}),
);
for domain in ["", "com.microsoft"] {
reg.register(
OpKey::new("LayerNormalization", domain, 1),
Box::new(normalization::LayerNormFactory {
runtime: runtime.clone(),
}),
);
}
reg.register(
OpKey::new("SimplifiedLayerNormalization", "com.microsoft", 1),
Box::new(normalization::RmsNormFactory {
runtime: runtime.clone(),
}),
);
reg.register(
OpKey::new("RMSNormalization", "", 1),
Box::new(normalization::RmsNormFactory {
runtime: runtime.clone(),
}),
);
reg.register(
OpKey::new("SkipLayerNormalization", "com.microsoft", 1),
Box::new(normalization::SkipLayerNormFactory {
runtime: runtime.clone(),
}),
);
for op_type in ["Cast", "CastLike"] {
reg.register(
OpKey::new(op_type, "", 1),
Box::new(cast::CastFactory {
runtime: runtime.clone(),
}),
);
}
reg.register(
OpKey::new("ReduceSum", "", 1),
Box::new(reduce::ReduceSumFactory {
runtime: runtime.clone(),
}),
);
reg.register(
OpKey::new("ReduceMean", "", 1),
Box::new(reduce::ReduceMeanFactory {
runtime: runtime.clone(),
}),
);
reg.register(
OpKey::new("ReduceMax", "", 1),
Box::new(reduce::ReduceMaxFactory {
runtime: runtime.clone(),
}),
);
reg.register(
OpKey::new("ReduceMin", "", 1),
Box::new(reduce::ReduceMinFactory {
runtime: runtime.clone(),
}),
);
for (op_type, op) in [
("Abs", UnaryMathOp::Abs),
("Neg", UnaryMathOp::Neg),
("Reciprocal", UnaryMathOp::Reciprocal),
("Exp", UnaryMathOp::Exp),
("Log", UnaryMathOp::Log),
("Sign", UnaryMathOp::Sign),
("Floor", UnaryMathOp::Floor),
("Ceil", UnaryMathOp::Ceil),
("Round", UnaryMathOp::Round),
("Sin", UnaryMathOp::Sin),
("Cos", UnaryMathOp::Cos),
("Softplus", UnaryMathOp::Softplus),
] {
reg.register(
OpKey::new(op_type, "", 1),
Box::new(UnaryMathFactory {
op,
runtime: runtime.clone(),
}),
);
}
reg.register(
OpKey::new("Not", "", 1),
Box::new(NotFactory {
runtime: runtime.clone(),
}),
);
for (op_type, op) in [
("And", LogicalOp::And),
("Or", LogicalOp::Or),
("Xor", LogicalOp::Xor),
] {
reg.register(
OpKey::new(op_type, "", 1),
Box::new(LogicalFactory {
op,
runtime: runtime.clone(),
}),
);
}
for (op_type, op) in [
("Equal", CmpOp::Equal),
("Greater", CmpOp::Greater),
("Less", CmpOp::Less),
("GreaterOrEqual", CmpOp::GreaterOrEqual),
("LessOrEqual", CmpOp::LessOrEqual),
] {
reg.register(
OpKey::new(op_type, "", 1),
Box::new(CmpFactory {
op,
runtime: runtime.clone(),
}),
);
}
reg
}
#[cfg(test)]
mod tests {
use super::CUDA_COVERED_OPS;
#[test]
fn wave2_ops_are_listed_in_coverage() {
for op in [
"Softmax",
"LayerNormalization",
"SkipLayerNormalization",
"SimplifiedLayerNormalization",
"RMSNormalization",
"Cast",
"CastLike",
"ReduceSum",
"ReduceMean",
"ReduceMax",
"ReduceMin",
] {
assert!(
CUDA_COVERED_OPS.contains(&op),
"{op} missing from CUDA_COVERED_OPS"
);
}
}
#[test]
fn covered_ops_have_no_duplicates() {
let mut seen = std::collections::HashSet::new();
for op in CUDA_COVERED_OPS {
assert!(seen.insert(*op), "duplicate op {op} in CUDA_COVERED_OPS");
}
}
#[test]
fn wave3_pointwise_ops_are_listed_in_coverage() {
for op in [
"Abs", "Neg", "Reciprocal", "Exp", "Log", "Sign", "Floor", "Ceil", "Round", "Sin",
"Cos", "Softplus", "Not", "And", "Or", "Xor", "Equal", "Greater", "Less",
"GreaterOrEqual", "LessOrEqual",
] {
assert!(
CUDA_COVERED_OPS.contains(&op),
"{op} missing from CUDA_COVERED_OPS"
);
}
}
}