MindSpore Lite 作为一款高性能推理框架,当前针对昇腾硬件有大量的优化特性,但是针对开源模型的泛化性存在一定的局限性,以及针对开源模型没有适配针对性的适配教程与优化教程,导致很多性能优化的高阶特性,用户使用难度大,调试成本高。最终,导致开发者无法直接将主流开源模型基于MindSpore Lite部署到昇腾硬件上。为了进一步提升MindSpore Lite针对开源模型的适配能力,以及开源算法的泛化支持,MindSpore Lite开发团队借助Agent能力,持续快速补齐开源模型基于MindSpore Lite 昇腾后端部署能力。
🚀 背景描述
MindSpore Lite 作为一款高性能推理框架,当前针对昇腾硬件有大量的优化特性,但是针对开源模型的泛化性存在一定的局限性,以及针对开源模型没有适配针对性的适配教程与优化教程,导致很多性能优化的高阶特性,用户使用难度大,调试成本高。最终,导致开发者无法直接将主流开源模型基于MindSpore Lite部署到昇腾硬件上。为了进一步提升MindSpore Lite针对开源模型的适配能力,以及开源算法的泛化支持,MindSpore Lite开发团队借助Agent能力,持续快速补齐开源模型基于MindSpore Lite 昇腾后端部署能力。
方案设计
MindSpore Lite昇腾后端推理主要针对中小(参数大小)模型场景,主要包含视频生成,图片生成,多模态理解,LLM(相对较小的LLM),语音合成(TTS),语音识别(ASR),自动驾驶,向量检索(搜索、推荐、广告等业务场景),以及传统CNN模型等算法类型进行泛化支持。MindSpore Lite开源开发团队会持续跟踪业界最新算法业务落地情况,按需适配开源模型推理能力,主要针对Atlas 800I A3、Atlas 800I A2、Atlas 300I Duo(部分小模型会适配香橙派)等硬件进行适配,并提供优化后的模型性能基线,为开源社区提供快速适配教程。

开源模型支持列表
具体的支持模型列表见:https://atomgit.com/mindspore/mindspore-lite/tree/master/mindspore-lite/examples/base_models
开源模型适配样例
开源模型迁移Skill
onnx模型导出脚本
MindSpore Lite支持多种格式的模型转化,但是当前最为常见的为ONNX模型,所以针对开源模型适配,我们选择ONNX格式作为开源模型转MindIR模型的输入文件,开发者可以通过将通过MindSpore Lite开源社区提供的onnx模型导出脚本将开源模型导出为onnx模型(默认动态shaoe),默认导出的onnx模型,为标准onnx模型(可以基于ONNXruntime在CPU进行推理的onnx格式);针对开源算法模型导出onnx模型,MindSpore Lite将整个过程整理成了对应的模型导出部署Skills
onnx模型推理
为了保证导出的onnx模型的推理效果和开源torch代码推理结果一致,MindSpore Lite开源社区会提供对应的onnx模型的推理集成代码,降低模型推理部署集成难度,减少前后处理逻辑适配,方便用户集成;
MindIR模型转换
MindSpore Lite开源社区会提供onnx模型转换为MindIR模型的转换命令,以及对应的配置文件,方便用户可以快速将onnx模型成功转换成MindIR模型,真正实现一键转换;
MindIR模型推理
为了保证MindIR模型可以集成部署,MindSpore Lite开源社区会提供对应的开源模型的集成部署教程,指导开发者怎么将一个MindIR模型部署到昇腾硬件;
开源模型优化
融合算子
MindSpore Lite当前支持
自定义算子格式 op_type="Custom" ,并在 attrs 里提供:
IO免拷贝;
整网如图;
自动调优;
....
价值
附录
自定义算子接入解析
2.3 Parse() 方法详细执行流程
OnnxCustomParser::Parse() 是核心方法,其完整流程如下:
Parse(onnx_graph, onnx_node)
│
├─ 1. 创建 ops::Custom 原生算子对象
│ auto prim = std::make_uniqueops::Custom();
│
├─ 2. 初始化必选/可选属性空向量
│ input_names = [], output_names = [], optional_input_names = [], type = ""
│
├─ 3. 遍历 onnx_node.attribute() 中的每个属性
│ │
│ ├─ 属性名 == "type"(必需,String 类型)
│ │ → 校验 AttributeType 必须为 STRING
│ │ → prim->set_type(type)
│ │ → prim->AddAttr("reg_op_name", type) // 设置注册算子名
│ │
│ ├─ 属性名 == "input_names"(必需,String[] 类型)
│ │ → 调用 CheckAndSetStrings() 校验类型 + 提取值
│ │ → prim->AddAttr("input_names", strings)
│ │
│ ├─ 属性名 == "output_names"(必需,String[] 类型)
│ │ → 同上,prim->AddAttr("output_names", strings)
│ │
│ ├─ 属性名 == "optional_input_names"(可选,String[] 类型)
│ │ → 同上,prim->AddAttr("optional_input_names", strings)
│ │
│ ├─ 属性名 == "output_num"(可选,Int 类型)
│ │ → 校验 AttributeType 必须为 INT
│ │ → prim->AddAttr("output_num", int_value)
│ │
│ ├─ 属性名 == "dtype"(特殊处理)
│ │ → GetDataTypeFromOnnx() 将 ONNX DataType → MindSpore TypeId
│ │ → prim->AddAttr("dst_type", TypeIdToType(...))
│ │
│ └─ 通用属性(按 ONNX AttributeType 分发):
│ ├─ FLOAT → prim->AddAttr(name, MakeValue(float_value))
│ ├─ INT → prim->AddAttr(name, MakeValue(int_value))
│ ├─ STRING → SetAttrString():识别 True/False bool 映射
│ ├─ INTS → SetAttrInts():提取 repeated int64
│ ├─ FLOATS → SetAttrFloats():提取 repeated float
│ └─ STRINGS → SetAttrStrings():提取 repeated string
│
├─ 4. 属性校验:CheckAttrs()
│ ├─ type 不能为空
│ ├─ input_names 不能为空
│ ├─ output_names 不能为空
│ ├─ optional_input_names 中的每个元素必须存在于 input_names 中
│ └─ 任一校验失败 → 返回 nullptr
│
└─ 5. 返回 prim->GetPrim()(PrimitiveCPtr)
2.4 String 类型属性的 Bool 值特殊处理
由于 ONNX 不支持 bool AttributeType,自定义算子中的 bool 属性需以 String 类型传递。SetAttrString() 函数实现自动识别:
void SetAttrString(const std::unique_ptrops::Custom &prim,
const std::string &attribute_name,
const std::string &attr_value) {
if (attr_value == "True" || attr_value == "true") {
prim->AddAttr(attribute_name, api::MakeValue(true)); // → C++ bool true
} else if (attr_value == "False" || attr_value == "false") {
prim->AddAttr(attribute_name, api::MakeValue(false)); // → C++ bool false
} else {
prim->AddAttr(attribute_name, api::MakeValue(attr_value)); // → 保持 string
}
}
2.5 属性类型映射总表
ONNX AttributeProto_AttributeType)
MindSpore 处理方式
示例属性
FLOAT
api::MakeValue(float)
epsilon=1e-5
INT
api::MakeValue(int64_t)
output_num=2
STRING
先判断 True/False → bool,否则保留 string
activation="gelu" / use_bias="True"
INTS
api::MakeValue(std::vector<int64_t>)
kernel_shape=[3,3]
FLOATS
api::MakeValue(std::vector
scale=[1.0,2.0]
STRINGS
api::MakeValue(std::vectorstd::string)
input_names=["x","y"]
其他
报错 MS_LOG(ERROR) 并返回 nullptr
—
三、完整接入示例
场景:将一个含自定义 MatMul 算子的 ONNX 模型转换为 .mindir
Step 1:确保 ONNX 模型中的 Custom 节点格式正确
NodeProto {
name: "CustomMatMul_0"
op_type: "Custom"
attribute {
name: "type" type: STRING s: "CustomMatMul"
}
attribute {
name: "input_names" type: STRINGS strings: ["A", "B"]
}
attribute {
name: "output_names" type: STRINGS strings: ["C"]
}
attribute {
name: "transpose_a" type: STRING s: "False"
}
attribute {
name: "transpose_b" type: STRING s: "True"
}
input: "input_0"
input: "input_1"
output: "output_0"
}
Step 2:转换工具自动解析
./converter_lite --fmk=ONNX
--modelFile=model_with_custom.onnx
--outputFile=model_converted
此时 onnx_custom_parser.cc 的 OnnxCustomParser 被自动触发:
读取 type="CustomMatMul" → 设置 reg_op_name
读取 input_names=["A","B"] / output_names=["C"]
transpose_a="False" → 转为 bool(false) 存入 Attr
transpose_b="True" → 转为 bool(true) 存入 Attr
Step 3:推理端加载模型
转换后的 .mindir 模型中保留了完整的自定义算子信息,推理时通过 REGISTER_CUSTOM_KERNEL_INTERFACE 注册对应的 Kernel 实现即可。
四、常见问题与注意事项
问题
原因
解决方案
解析返回 nullptr
type/input_names/output_names 未设置或为空
检查 ONNX 导出逻辑,确保必需属性完整
属性类型不匹配
如 type 应为 STRING 实际为 INT
检查 ONNX 模型导出方式
optional_input_names 不在 input_names 中
可选输入不在必需输入列表中
确保 optional_input_names 是 input_names 的子集
bool 值未正确转换
使用了非 True/False 的其他表示
使用 "True"/"true"/"False"/"false"
不支持的数据类型
AttributeType 为 UNDEFINED/TENSOR 等
仅支持 FLOAT/INT/STRING/INTS/FLOATS/STRINGS
五、相关参考
MindSpore Lite 离线构建自定义算子文档
MindSpore Lite 自定义算子云侧适配
示例代码:mindspore-lite/examples/converter_extend/node_parser/
注册 Kernel:REGISTER_CUSTOM_KERNEL_INTERFACE(provider, op_type, creator)
🎉🎉🎉