Merged
[fix] 通信域重复创建时 RPT_INPUT_ERR 补充规范报错 #4965
guanzhongkangAdd on Aug 31
[fix] 通信域重复创建时 RPT_INPUT_ERR 补充规范报错 #4965
Merged
guanzhongkangAdd on Aug 31
Total: 5 files changed+146-8
@@ -5,13 +5,13 @@
5The following is error format. The meanings of the placeholders %s in sequence are: operator name, parameter value, parameter name, expected value.5The following is error format. The meanings of the placeholders %s in sequence are: operator name, parameter value, parameter name, expected value.
6 6 
7```text7```text
8-Failed to verify parameters of operator %s (operator name). Value %s for parameter %s is invalid. The expected value is %s.8+Failed to verify parameters of operator %s. Value %s for parameter %s is invalid. The expected value is %s.
9```9```
10 10 
11Error example:11Error example:
12 12 
13```text13```text
14-Failed to verify parameters of operator CheckRankID (operator name). Value 1sfa for parameter rank_id is invalid. The expected value is a non-negative decimal number.14+Failed to verify parameters of operator CheckRankID. Value 1sfa for parameter rank_id is invalid. The expected value is a non-negative decimal number.
15```15```
16 16 
17## Solution17## Solution
@@ -5,13 +5,13 @@
5报错格式如下,占位符%s的含义依次为算子名、参数值、参数名、期望值:5报错格式如下,占位符%s的含义依次为算子名、参数值、参数名、期望值:
6 6 
7```text7```text
8-Failed to verify parameters of operator %s (operator name). Value %s for parameter %s is invalid. The expected value is %s.8+Failed to verify parameters of operator %s. Value %s for parameter %s is invalid. The expected value is %s.
严正行
严正行严正行Aug 31

[LOW] PR 描述“文档更新:无”与实际改动 2 个错误码文档不符

问题描述: 本 PR 实际修改了 docs/zh/error_codes/EI0003-*.md 与 docs/en/error_codes/EI0003-*.md 两个文档(错误格式与示例中删除了 %s 后的 (operator name) 括号注释),以及 src/legacy/ascend910/common/error_code/error_code.cc 中 EI0003 的 ErrMessage 模板(同步删除 (operator name))。

但 PR 描述的“文档更新”栏填的是“无”,“描述”栏也未提及模板文案变更。这属于错误码模板的行为变更:凡是 EI0003 渲染出的报错文案都会少一段 (operator name) 注释,影响用户可见的报错格式与资料一致性。

建议修复: 在 PR 描述中补充说明:

  1. “文档更新”栏改为实际更新的两个 EI0003 文档路径;
  2. “描述”栏补充一条:EI0003 模板删除 (operator name) 括号注释(error_code.cc 与中英文档同步),并说明该变更与本次 RPT_INPUT_ERR 上报的关系(如:新上报的 ccl_op 槽直接渲染算子名,模板中的重复注释不再需要)。

若该模板变更是顺手修复而非本 PR 目标,建议在描述中单独声明,便于 committer 评审时确认影响面。

likedislike
guanzhongkang
guanzhongkang
Sep 1 Comments:
9```9```
10 10 
11报错示例如下:11报错示例如下:
12 12 
13```text13```text
14-Failed to verify parameters of operator CheckRankID (operator name). Value 1sfa for parameter rank_id is invalid. The expected value is a non-negative decimal number.14+Failed to verify parameters of operator CheckRankID. Value 1sfa for parameter rank_id is invalid. The expected value is a non-negative decimal number.
15```15```
16 16 
17## 解决方法17## 解决方法
@@ -42,7 +42,7 @@ const std::string hcomm_g_msg = R"(
42 "errClass": "HCCL Errors",42 "errClass": "HCCL Errors",
43 "errTitle": "Invalid_Argument_Collective_Communication_Operator",43 "errTitle": "Invalid_Argument_Collective_Communication_Operator",
44 "ErrCode": "EI0003",44 "ErrCode": "EI0003",
45- "ErrMessage": "Failed to verify parameters of operator %s (operator name). Value %s for parameter %s is invalid. The expected value is %s.",45+ "ErrMessage": "Failed to verify parameters of operator %s. Value %s for parameter %s is invalid. The expected value is %s.",
46 "Arglist": "ccl_op,value,parameter,expect",46 "Arglist": "ccl_op,value,parameter,expect",
47 "suggestion": {47 "suggestion": {
48 "Possible Cause": "N/A",48 "Possible Cause": "N/A",
@@ -225,8 +225,12 @@ HcclResult CreateCommConfigRootInfo(
225{225{
226 // check226 // check
227 HcclCommInfoV2& opbasedCommInfoV2 = GetCommInfoV2();227 HcclCommInfoV2& opbasedCommInfoV2 = GetCommInfoV2();
228+ bool commExists = opbasedCommInfoV2.hcclGroupMap.find(identifier) != opbasedCommInfoV2.hcclGroupMap.end();
229+ RPT_INPUT_ERR(
230+ commExists, "EI0003", vector<string>({"ccl_op", "value", "parameter", "expect"}),
231+ vector<string>({"HcclCommInitRootInfo", identifier, "identifier", "an identifier that is not in use"}));
228 CHK_PRT_RET(232 CHK_PRT_RET(
229- opbasedCommInfoV2.hcclGroupMap.find(identifier) != opbasedCommInfoV2.hcclGroupMap.end(),233+ commExists,
230 HCCL_ERROR(234 HCCL_ERROR(
231 "[HcclCommInitRootInfoConfigV2]errNo[0x%016llx] The comm name[%s] already exists in Group2Comm map.",235 "[HcclCommInitRootInfoConfigV2]errNo[0x%016llx] The comm name[%s] already exists in Group2Comm map.",
232 HCCL_ERROR_CODE(HCCL_E_PARA), identifier.c_str()),236 HCCL_ERROR_CODE(HCCL_E_PARA), identifier.c_str()),
@@ -1783,8 +1787,12 @@ CommInitRootInfo(u32 nRanks, u32 rank, const HcclRootHandleV2& rootHandle, const
1783 CHK_RET(CallSingletons());1787 CHK_RET(CallSingletons());
1784 // check1788 // check
1785 HcclCommInfoV2& opbasedCommInfoV2 = GetCommInfoV2();1789 HcclCommInfoV2& opbasedCommInfoV2 = GetCommInfoV2();
1790+ bool commExists = opbasedCommInfoV2.hcclGroupMap.find(identifier) != opbasedCommInfoV2.hcclGroupMap.end();
1791+ RPT_INPUT_ERR(
1792+ commExists, "EI0003", vector<string>({"ccl_op", "value", "parameter", "expect"}),
严正行

[MEDIUM] 重复创建分支无 UT 覆盖,PR 描述"补充的UT用例"一节为空

问题分析:

  • 本 PR 对三处查重分支新增 RPT_INPUT_ERR 上报(第 229/1791/1955 行)并将命中条件重构为 commExists,属 src/ 生产代码行为变更,但 test/ 目录无任何变更。
  • 现有 RootInfo 系列 UT(test/ut/framework/communicator/ut_HcclCommInitRootInfo_API_test.cc、ut_HcclCommInitRootInfoConfig_API_test.cc)的用例仅覆盖 nRanksIsZero/GetDeviceError/RootInfoIsNull/RankGreaterThan/PCommIsNull/InitCommParams 等场景,无"identifier 已存在(重复创建)"用例——本次修改的核心分支(查重命中 → 上报 → 返回 HCCL_E_PARA)无自动化断言。
  • 仓内已有可参照的 Duplicate 用例模式:test/ut/framework/communicator/ut_HcclCommEngineCtx_API_test.cc:92 的 Ut_HcclEngineCtxCreate_When_Duplicate_Creation_Expect_Return_EPARA。
  • RPT_INPUT_ERR 宏在 RptInputErr == nullptr 时静默跳过(adapter_error_manager_pub.h 弱符号判空),UT 环境不会因上报而崩溃,可测性无障碍。

建议修复: 在 ut_HcclCommInitRootInfo_API_test.cc(或 Config 版)补充用例:先成功创建一次通信域,再用相同 identifier 重复调用,断言返回值为 HCCL_E_PARA;同时在 PR 描述"补充的UT用例"一节补齐用例名与执行结果。

likedislike
guanzhongkang
guanzhongkang
Sep 2 Comments:
1793+ vector<string>({"HcclCommInitRootInfo", identifier, "identifier", "an identifier that is not in use"}));
1786 CHK_PRT_RET(1794 CHK_PRT_RET(
1787- opbasedCommInfoV2.hcclGroupMap.find(identifier) != opbasedCommInfoV2.hcclGroupMap.end(),1795+ commExists,
1788 HCCL_ERROR(1796 HCCL_ERROR(
1789 "[CreateCommConfig] errNo[0x%016llx] The rootHandle[%s] already exists in Group2Comm map.",1797 "[CreateCommConfig] errNo[0x%016llx] The rootHandle[%s] already exists in Group2Comm map.",
1790 HCCL_ERROR_CODE(HCCL_E_PARA), identifier.c_str()),1798 HCCL_ERROR_CODE(HCCL_E_PARA), identifier.c_str()),
@@ -1943,8 +1951,12 @@ HcclResult HcclCommInitRootInfoConfigV2(
1943 // 临时规避,在初始化通信域前声明单例保证时序1951 // 临时规避,在初始化通信域前声明单例保证时序
1944 CHK_RET(CallSingletons());1952 CHK_RET(CallSingletons());
1945 HcclCommInfoV2& opbasedCommInfoV2 = GetCommInfoV2();1953 HcclCommInfoV2& opbasedCommInfoV2 = GetCommInfoV2();
1954+ bool commExists = opbasedCommInfoV2.hcclGroupMap.find(identifier) != opbasedCommInfoV2.hcclGroupMap.end();
1955+ RPT_INPUT_ERR(
1956+ commExists, "EI0003", vector<string>({"ccl_op", "value", "parameter", "expect"}),
严正行

[MEDIUM] 910 legacy 侧同型"通信域重复创建"查重未补充 EI0003 上报,修复范围存在缺口

问题分析:

  • 本 PR 为 950 侧 RootInfo 路径三处查重(第 229/1791/1955 行)补充了 RPT_INPUT_ERR 规范上报,PR 描述声明"上报范围收敛为 RootInfo 路径",且仅明确排除了 ClusterInfo 路径。
  • 但 910 legacy 侧存在同型查重:src/legacy/ascend910/framework/op_base/src/op_base.cc 第 1605-1611 行 InitCommRootInfo 中 opGroup2CommMap.find(commIdentifier) 命中时同样仅打印 HCCL_ERROR、返回 HCCL_E_PARA,未上报 EI0003。
  • 910 入口 HcclCommInitRootInfo(op_base.cc:1915)经 HCCLV2_FUNC_RUN 分流:isSupportV2=true 时走 950 实现可拿到上报;910 硬件(A2/A3,isSupportV2=false)走 910 InitCommRootInfo,该路径重复创建通信域仍拿不到带错误码的规范报错,与本 PR 修复目标("用户侧拿不到带错误码的规范报错")相悖。
  • 910 侧已有大量 RPT_INPUT_ERR 使用先例(op_base.cc:957/1044/1283/1944 等),且 EI0003 错误码表由 ascend910/common/error_code/error_code.cc 全局注册、910/950 共用,补充上报技术可行。

建议修复: 二选一: (1) 在 op_base.cc InitCommRootInfo 查重处同步补充:RPT_INPUT_ERR(iter != opBaseHcom.opGroup2CommMap.end(), "EI0003", std::vector<std::string>({"ccl_op", "value", "parameter", "expect"}), std::vector<std::string>({"HcclCommInitRootInfo", commIdentifier, "identifier", "an identifier that is not in use"})); (2) 若 910 路径确定不覆盖,请在 PR 描述"上报范围收敛"条目中明确写出 910 侧不补及原因,便于 committer 评审确认影响面。

likedislike
guanzhongkang
guanzhongkang
Sep 2 Comments:
1957+ vector<string>({"HcclCommInitRootInfo", identifier, "identifier", "an identifier that is not in use"}));
1946 CHK_PRT_RET(1958 CHK_PRT_RET(
1947- opbasedCommInfoV2.hcclGroupMap.find(identifier) != opbasedCommInfoV2.hcclGroupMap.end(),1959+ commExists,
1948 HCCL_ERROR(1960 HCCL_ERROR(
1949 "[HcclCommInitRootInfoConfigV2]errNo[0x%016llx] The comm name[%s] already exists in Group2Comm map.",1961 "[HcclCommInitRootInfoConfigV2]errNo[0x%016llx] The comm name[%s] already exists in Group2Comm map.",
1950 HCCL_ERROR_CODE(HCCL_E_PARA), identifier.c_str()),1962 HCCL_ERROR_CODE(HCCL_E_PARA), identifier.c_str()),
@@ -2490,6 +2490,132 @@ TEST_F(OpbaseTestV2, Ut_HcclCommInitRootInfoConfigV2_When_ProviderFails_Expect_R
2490 EXPECT_EQ(HcclCommInitRootInfoConfigV2(nRanks, &rootInfo, rank, &config, &comm), HCCL_E_INTERNAL);2490 EXPECT_EQ(HcclCommInitRootInfoConfigV2(nRanks, &rootInfo, rank, &config, &comm), HCCL_E_INTERNAL);
2491}2491}
2492 2492 
2493+namespace {
2494+// 捕获 RptInputErr 上报内容, 用于断言通信域重复创建时触发 EI0003 规范报错
2495+std::string g_dupRptErrorCode;
2496+std::vector<std::string> g_dupRptKeys;
2497+std::vector<std::string> g_dupRptValues;
2498+ 
2499+void stub_RptInputErr_capture(std::string error_code, std::vector<std::string> key, std::vector<std::string> value)
2500+{
2501+ g_dupRptErrorCode = error_code;
2502+ g_dupRptKeys = key;
2503+ g_dupRptValues = value;
2504+}
2505+} // namespace
2506+ 
2507+// op_base_v2.cc 内部接口(未在头文件中声明): 其查重分支被 HcclCommInitRootInfoConfigV2 入口查重遮蔽,
2508+// 公共接口无法触达, 此处声明用于直接测试
2509+HcclResult CreateCommConfigRootInfo(
2510+ uint32_t rank, const HcclCommConfig* config, const std::string& identifier, const RankTableInfo& ranktable,
2511+ HcclComm* comm);
2512+ 
2513+// 相同 identifier 重复创建通信域: CommInitRootInfo 查重命中, 上报 EI0003 并返回 HCCL_E_PARA
2514+TEST_F(OpbaseTestV2, Ut_HcclCommInitRootInfoV2_When_DuplicateCreation_Expect_Return_HCCL_E_PARA)
2515+{
2516+ // when
2517+ MOCKER(HrtGetDeviceType).stubs().with(mockcpp::any()).will(returnValue((DevType)DevType::DEV_TYPE_950));
2518+ MOCKER(HrtGetDeviceCount).stubs().will(returnValue(1));
2519+ MOCKER_CPP(&HcclCommunicator::Init, HcclResult(HcclCommunicator::*)(const RankTableInfo&))
2520+ .stubs()
2521+ .with(mockcpp::any())
2522+ .will(returnValue(HCCL_SUCCESS));
2523+ MOCKER_CPP(&CommunicatorImpl::SetCommExecuteConfig).stubs().will(ignoreReturnValue());
2524+ MOCKER(RptInputErr).stubs().will(invoke(stub_RptInputErr_capture));
2525+ CommManager::GetInstance(0).GetCommInfoV2().hcclGroupMap.clear();
2526+ CommManager::GetInstance(0).GetCommInfoV2().pComm = nullptr;
2527+ 
2528+ // then: 首次创建成功, 不触发规范报错
2529+ uint32_t nRanks = 1;
2530+ HcclRootInfo rootInfo{};
2531+ uint32_t rank = 0;
2532+ HcclComm commFirst{};
2533+ std::string identifier{};
2534+ g_dupRptErrorCode.clear();
2535+ EXPECT_EQ(HcclCommInitRootInfoV2(nRanks, &rootInfo, rank, &commFirst, identifier), HCCL_SUCCESS);
2536+ EXPECT_TRUE(g_dupRptErrorCode.empty());
2537+ 
2538+ // 相同 rootInfo(即相同 identifier)重复创建: 查重命中, 上报 EI0003 并返回 HCCL_E_PARA
2539+ HcclComm commSecond{};
2540+ EXPECT_EQ(HcclCommInitRootInfoV2(nRanks, &rootInfo, rank, &commSecond, identifier), HCCL_E_PARA);
2541+ EXPECT_EQ(g_dupRptErrorCode, "EI0003");
2542+ ASSERT_EQ(g_dupRptValues.size(), 4); // ccl_op/value/parameter/expect
2543+ EXPECT_EQ(g_dupRptValues[0], "HcclCommInitRootInfo");
2544+ EXPECT_EQ(g_dupRptValues[2], "identifier");
2545+ 
2546+ // 清理现场, 避免残留通信域信息影响后续用例
2547+ CommManager::GetInstance(0).GetCommInfoV2().hcclGroupMap.clear();
2548+ CommManager::GetInstance(0).GetCommInfoV2().pComm = nullptr;
2549+}
2550+ 
2551+// 相同 identifier 重复创建通信域(带 config): HcclCommInitRootInfoConfigV2 查重命中,
2552+// 上报 EI0003 并返回 HCCL_E_PARA
2553+TEST_F(OpbaseTestV2, Ut_HcclCommInitRootInfoConfigV2_When_DuplicateCreation_Expect_Return_HCCL_E_PARA)
2554+{
2555+ // when
2556+ MOCKER(HrtGetDeviceType).stubs().with(mockcpp::any()).will(returnValue((DevType)DevType::DEV_TYPE_950));
2557+ MOCKER(HrtGetDeviceCount).stubs().will(returnValue(1));
2558+ MOCKER_CPP(&HcclCommunicator::Init, HcclResult(HcclCommunicator::*)(const RankTableInfo&))
2559+ .stubs()
2560+ .with(mockcpp::any())
2561+ .will(returnValue(HCCL_SUCCESS));
2562+ MOCKER_CPP(&CommunicatorImpl::SetCommExecuteConfig).stubs().will(ignoreReturnValue());
2563+ MOCKER(RptInputErr).stubs().will(invoke(stub_RptInputErr_capture));
2564+ CommManager::GetInstance(0).GetCommInfoV2().hcclGroupMap.clear();
2565+ CommManager::GetInstance(0).GetCommInfoV2().pComm = nullptr;
2566+ 
2567+ // then: 首次创建成功, 不触发规范报错
2568+ uint32_t nRanks{2};
2569+ HcclRootInfo rootInfo{};
2570+ uint32_t rank{};
2571+ HcclComm commFirst{};
2572+ HcclCommConfig config{};
2573+ string worldgroup = "ut_dup_rootinfo_config";
2574+ PrepareCommConfig(config, 200, worldgroup, 1, 0);
2575+ g_dupRptErrorCode.clear();
2576+ EXPECT_EQ(HcclCommInitRootInfoConfigV2(nRanks, &rootInfo, rank, &config, &commFirst), HCCL_SUCCESS);
2577+ EXPECT_TRUE(g_dupRptErrorCode.empty());
2578+ 
2579+ // 相同 config(即相同 identifier)重复创建: 查重命中, 上报 EI0003 并返回 HCCL_E_PARA
2580+ HcclComm commSecond{};
2581+ EXPECT_EQ(HcclCommInitRootInfoConfigV2(nRanks, &rootInfo, rank, &config, &commSecond), HCCL_E_PARA);
2582+ EXPECT_EQ(g_dupRptErrorCode, "EI0003");
2583+ ASSERT_EQ(g_dupRptValues.size(), 4); // ccl_op/value/parameter/expect
2584+ EXPECT_EQ(g_dupRptValues[0], "HcclCommInitRootInfo");
2585+ EXPECT_EQ(g_dupRptValues[1], worldgroup);
2586+ EXPECT_EQ(g_dupRptValues[2], "identifier");
2587+ 
2588+ // 清理现场, 避免残留通信域信息影响后续用例
2589+ CommManager::GetInstance(0).GetCommInfoV2().hcclGroupMap.clear();
2590+ CommManager::GetInstance(0).GetCommInfoV2().pComm = nullptr;
2591+}
2592+ 
2593+// 相同 identifier 重复创建通信域: CreateCommConfigRootInfo 查重命中,
2594+// 上报 EI0003 并返回 HCCL_E_PARA(该分支位于接口内部, 需预置 map 后直接调用)
2595+TEST_F(OpbaseTestV2, Ut_CreateCommConfigRootInfo_When_DuplicateCreation_Expect_Return_HCCL_E_PARA)
2596+{
2597+ // 预置 identifier 已存在的通信域信息
2598+ MOCKER(RptInputErr).stubs().will(invoke(stub_RptInputErr_capture));
2599+ const string dupIdentifier = "ut_dup_createcommconfig_rootinfo";
2600+ HcclGroupParamsV2 params{};
2601+ CommManager::GetInstance(0).GetCommInfoV2().hcclGroupMap[dupIdentifier] = params;
2602+ 
2603+ uint32_t rank{};
2604+ HcclCommConfig config{};
2605+ HcclCommConfigInit(&config);
2606+ HcclComm comm{};
2607+ g_dupRptErrorCode.clear();
2608+ EXPECT_EQ(CreateCommConfigRootInfo(rank, &config, dupIdentifier, RankTableInfo{}, &comm), HCCL_E_PARA);
2609+ EXPECT_EQ(g_dupRptErrorCode, "EI0003");
2610+ ASSERT_EQ(g_dupRptValues.size(), 4); // ccl_op/value/parameter/expect
2611+ EXPECT_EQ(g_dupRptValues[0], "HcclCommInitRootInfo");
2612+ EXPECT_EQ(g_dupRptValues[1], dupIdentifier);
2613+ EXPECT_EQ(g_dupRptValues[2], "identifier");
2614+ 
2615+ // 清理现场, 避免残留通信域信息影响后续用例
2616+ CommManager::GetInstance(0).GetCommInfoV2().hcclGroupMap.clear();
2617+}
2618+ 
2493TEST_F(OpbaseTestV2, Ut_HcclCommInitAllV2_When_InputValue_Expect_Return_HCCL_SUCCESS)2619TEST_F(OpbaseTestV2, Ut_HcclCommInitAllV2_When_InputValue_Expect_Return_HCCL_SUCCESS)
2494{2620{
2495 // when2621 // when