已合并
【fix】: support empty onnx domain #4093
tang-haojie创建于 7月21日
【fix】: support empty onnx domain #4093
已合并
共 2 个文件变更+15-32
| @@ -417,34 +417,14 @@ Status OnnxModelParser::ConstructOriType(const ge::onnx::NodeProto *node_proto, | |||
| 417 | return SUCCESS; | 417 | return SUCCESS; |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | - std::string domain = node_proto->domain(); | 420 | + std::string domain = node_proto->domain().empty() ? "ai.onnx" : node_proto->domain(); |
| 421 | - int64_t version = 0; | 421 | + std::map<std::string, int64_t>::const_iterator it = domain_verseion_.find(domain); |
| 422 | - if (!domain.empty()) { | 422 | + if (it == domain_verseion_.end()) { |
| 423 | - std::map<std::string, int64_t>::const_iterator it = domain_verseion_.find(domain); | 423 | + REPORT_INNER_ERR_MSG("E19999", "The opset of domain[%s] has no responding version.", domain.c_str()); |
| 424 | - if (it != domain_verseion_.end()) { | 424 | + GELOGE(PARAM_INVALID, "[Check][Param]The opset of domain[%s] has no responding version.", domain.c_str()); |
| 425 | - version = it->second; | 425 | + return PARAM_INVALID; |
| 426 | - } else { | ||
| 427 | - REPORT_INNER_ERR_MSG("E19999", "The opset of domain[%s] has no responding version.", domain.c_str()); | ||
| 428 | - GELOGE(PARAM_INVALID, "[Check][Param]The opset of domain[%s] has no responding version.", domain.c_str()); | ||
| 429 | - return PARAM_INVALID; | ||
| 430 | - } | ||
| 431 | - } else { | ||
| 432 | - size_t domain_version_size = domain_verseion_.size(); | ||
| 433 | - if (domain_version_size == 1) { | ||
| 434 | - domain = domain_verseion_.begin()->first; | ||
| 435 | - version = domain_verseion_.begin()->second; | ||
| 436 | - } else { | ||
| 437 | - GELOGE(PARAM_INVALID, "[Check][Param]The size of domain_version[%zu] should be equal to one.", | ||
| 438 | - domain_version_size); | ||
| 439 | - REPORT_PREDEFINED_ERR_MSG("E16005", std::vector<const char *>({"domain_version_size"}), | ||
| 440 | - std::vector<const char *>({to_string(domain_version_size).c_str()})); | ||
| 441 | - return PARAM_INVALID; | ||
| 442 | - } | ||
| 443 | - } | ||
| 444 | - | ||
| 445 | - if (domain.empty()) { | ||
| 446 | - domain = "ai.onnx"; | ||
| 447 | } | 426 | } |
| 427 | + int64_t version = it->second; | ||
| 448 | 428 | ||
| 449 | ori_type = domain + "::" + to_string(version) + "::" + ori_type; | 429 | ori_type = domain + "::" + to_string(version) + "::" + ori_type; |
| 450 | return SUCCESS; | 430 | return SUCCESS; |
| @@ -927,8 +907,9 @@ Status OnnxModelParser::ModelParseToGraph(const ge::onnx::ModelProto &onnx_model | |||
| 927 | 907 | ||
| 928 | auto opset_import = onnx_model.opset_import(); | 908 | auto opset_import = onnx_model.opset_import(); |
| 929 | for (auto it : opset_import) { | 909 | for (auto it : opset_import) { |
| 930 | - domain_verseion_[it.domain()] = it.version(); | 910 | + std::string domain = it.domain().empty() ? "ai.onnx" : it.domain(); |
| 931 | - GELOGI("Domain:[%s], Version:[%ld].", it.domain().c_str(), it.version()); | 911 | + domain_verseion_[domain] = it.version(); |
| 912 | + GELOGI("Domain:[%s], Version:[%ld].", domain.c_str(), it.version()); | ||
| 932 | } | 913 | } |
| 933 | std::string root_graph_name = | 914 | std::string root_graph_name = |
| 934 | ParserUtils::GetGraphName(root_graph).empty() ? "default_graph" : ParserUtils::GetGraphName(root_graph); | 915 | ParserUtils::GetGraphName(root_graph).empty() ? "default_graph" : ParserUtils::GetGraphName(root_graph); |
| @@ -774,7 +774,8 @@ TEST_F(UtestOnnxParser, ConstructOriType_empty_domain_multiple_versions) { | |||
| 774 | 774 | ||
| 775 | std::string ori_type; | 775 | std::string ori_type; |
| 776 | auto ret = parser.ConstructOriType(&node, ori_type); | 776 | auto ret = parser.ConstructOriType(&node, ori_type); |
| 777 | - EXPECT_EQ(ret, PARAM_INVALID); | 777 | + EXPECT_EQ(ret, SUCCESS); |
| 778 | + EXPECT_EQ(ori_type, "ai.onnx::11::CustomOp"); | ||
| 778 | } | 779 | } |
| 779 | 780 | ||
| 780 | TEST_F(UtestOnnxParser, ConstructOriType_empty_domain_single_version) { | 781 | TEST_F(UtestOnnxParser, ConstructOriType_empty_domain_single_version) { |
| @@ -1100,7 +1101,7 @@ TEST_F(UtestOnnxParser, ConstructInputOutputContext_basic) { | |||
| 1100 | 1101 | ||
| 1101 | // ======================== Prechecker tests ======================== | 1102 | // ======================== Prechecker tests ======================== |
| 1102 | 1103 | ||
| 1103 | -TEST_F(UtestOnnxParser, Prechecker_construct_ori_type_failure) { | 1104 | +TEST_F(UtestOnnxParser, Prechecker_unregistered_op_type_failure) { |
| 1104 | OnnxModelParser parser; | 1105 | OnnxModelParser parser; |
| 1105 | parser.domain_verseion_["ai.onnx"] = 11; | 1106 | parser.domain_verseion_["ai.onnx"] = 11; |
| 1106 | parser.domain_verseion_["other.domain"] = 1; | 1107 | parser.domain_verseion_["other.domain"] = 1; |
| @@ -1112,7 +1113,8 @@ TEST_F(UtestOnnxParser, Prechecker_construct_ori_type_failure) { | |||
| 1112 | node->set_domain(""); | 1113 | node->set_domain(""); |
| 1113 | 1114 | ||
| 1114 | auto ret = parser.Prechecker(graph); | 1115 | auto ret = parser.Prechecker(graph); |
| 1115 | - EXPECT_NE(ret, SUCCESS); | 1116 | + EXPECT_EQ(ret, SUCCESS); |
| 1117 | + EXPECT_TRUE(parser.HasError()); | ||
| 1116 | } | 1118 | } |
| 1117 | 1119 | ||
| 1118 | // ======================== AdapterOpType tests ======================== | 1120 | // ======================== AdapterOpType tests ======================== |
🟡 Medium Priority
变更行:
onnx_parser.cc第 420–427 行(ConstructOriType函数的新逻辑)。旧行为:当节点
domain为空且domain_verseion_中恰好只有 1 个条目时,旧代码会将该条目的 domain 和 version 回退用于该节点(无论该条目是"ai.onnx"还是自定义 domain 如"com.microsoft")。这意味着仅导入单个自定义 opset、不含标准"ai.onnx"opset 的模型,其空 domain 节点仍能成功解析。新行为:空 domain 始终默认映射为
"ai.onnx",直接在domain_verseion_中查找。若"ai.onnx"不在 map 中,返回PARAM_INVALID。触发条件:模型仅导入一个自定义 domain 的 opset(如
opset_import { domain: "custom.domain", version: 1 }),不含domain=""或domain="ai.onnx"的 opset 条目,且包含domain=""的节点。失败模式:此类模型在旧代码下可成功解析,新代码下
ConstructOriType返回PARAM_INVALID,导致整个模型解析失败。"ai.onnx"查找失败后增加回退:若domain_verseion_.size() == 1,使用该唯一条目。建议:若需保持向后兼容,在
domain_verseion_.find("ai.onnx")返回end()且domain_verseion_.size() == 1时,回退使用该唯一条目的 domain 和 version;否则按当前逻辑返回错误。若确认移除回退为有意行为,需在变更说明中记录此破坏性变更。