已合并
[feat] 支持HcclSymWinGetRemoteAddr接口 #4430
RocketHcgs创建于 8月5日
[feat] 支持HcclSymWinGetRemoteAddr接口 #4430
已合并
RocketHcgs创建于 8月5日
7 个文件变更+284-37
@@ -3,7 +3,7 @@
3## 产品支持情况3## 产品支持情况
4 4 
5<!-- npu="950" id1 -->5<!-- npu="950" id1 -->
6-- Ascend 950PR/Ascend 950DT:支持6+- Ascend 950PR/Ascend 950DT:支持
7<!-- end id1 -->7<!-- end id1 -->
8<!-- npu="A3" id2 -->8<!-- npu="A3" id2 -->
9- Atlas A3 训练系列产品/Atlas A3 推理系列产品:支持9- Atlas A3 训练系列产品/Atlas A3 推理系列产品:支持
@@ -23,7 +23,7 @@
23根据对称内存窗口资源句柄和偏移,获取指定rank ID的对称内存窗口中该偏移对应的地址指针。23根据对称内存窗口资源句柄和偏移,获取指定rank ID的对称内存窗口中该偏移对应的地址指针。
24 24 
25<!-- npu="A3" id6 -->25<!-- npu="A3" id6 -->
26-针对Atlas A3 训练系列产品/Atlas A3 推理系列产品,本接口支持HCCS链路通信场景;针Ascend 950PR/Ascend 950DT,本接口支持URMA场景26+针对Atlas A3 训练系列产品/Atlas A3 推理系列产品,本接口支持HCCS链路通信场景,返回应的有效地址指针;若窗口为URMA模式,本接口将返回错误并将*ptr置为nullptr,此时应改用[HcclSymWinGetRemoteAddr](HcclSymWinGetRemoteAddr.md)获取地址
严正行
严正行严正行12 天前

[LOW] URMA模式提示语放在A3条件块内,目标读者错位

问题分析

  • 第26行:「若窗口为URMA模式,本接口将返回错误并将*ptr置为nullptr,此时应改用HcclSymWinGetRemoteAddr获取地址」包裹在 <!-- npu="A3" id6 --> 条件块内。
  • A3对称内存为HCCS模式(legacy路径窗口mode=HCCS),不存在URMA窗口,这句提示对A3读者是不会触发的死条件;而950读者在该页面渲染的内容里看不到这句指引(950的对应块已删除)。

建议修复: 将该URMA提示移到950可见的位置(或公共正文),确保950用户误用本接口时能看到改用 HcclSymWinGetRemoteAddr 的指引;A3块内只保留HCCS相关说明。

likedislike
RocketHcgs
RocketHcgs
11 天前 评论:
27<!-- end id6 -->27<!-- end id6 -->
28 28 
29## 函数原型29## 函数原型
@@ -47,16 +47,9 @@ HcclResult HcclSymWinGetPeerPointer(HcclCommSymWindow winHandle, size_t offset,
47 47 
48## 约束说明48## 约束说明
49 49 
50-<!-- npu="950" id7 -->50+<!-- npu="A3" id7 -->
51-- 针对Ascend 950PR/Ascend 950DT,仅支持URMA场景。该场景下:
52- - 调用该接口前需确保对称内存窗口已完成注册,且相关UB/URMA通信通道已完成建链和远端内存信息更新。
53- 
54- 使用集合通信接口时,相关通道创建和远端内存信息更新由集合通信内部完成;使用独立通信通道资源接口时,需在通道创建成功后再调用该接口。
55- - 传入的winHandle必须为已注册的有效对称内存窗口句柄。若通过[HcclCommSymWinGet](HcclCommSymWinGet.md)获取窗口句柄时未命中,返回的winHandle为空,不能继续传入本接口;若对应peerRank的远端内存信息尚未完成更新,本接口将返回错误。
56-<!-- end id7 -->
57-<!-- npu="A3" id8 -->
58- 针对Atlas A3 训练系列产品/Atlas A3 推理系列产品,仅支持HCCS链路通信场景。51- 针对Atlas A3 训练系列产品/Atlas A3 推理系列产品,仅支持HCCS链路通信场景。
59-<!-- end id8 -->52+<!-- end id7 -->
60- 该接口仅支持通信算子展开模式为AI CPU的场景。53- 该接口仅支持通信算子展开模式为AI CPU的场景。
61- 该接口仅支持在Device侧调用。54- 该接口仅支持在Device侧调用。
62 55 
@@ -0,0 +1,75 @@
1+# HcclSymWinGetRemoteAddr
2+ 
3+## 产品支持情况
4+ 
5+<!-- npu="950" id1 -->
6+- Ascend 950PR/Ascend 950DT:支持
7+<!-- end id1 -->
8+<!-- npu="A3" id2 -->
9+- Atlas A3 训练系列产品/Atlas A3 推理系列产品:不支持
10+<!-- end id2 -->
11+<!-- npu="910b" id3 -->
12+- Atlas A2 训练系列产品/Atlas A2 推理系列产品:不支持
13+<!-- end id3 -->
14+<!-- npu="310p" id4 -->
15+- Atlas 推理系列产品:不支持
16+<!-- end id4 -->
17+<!-- npu="910" id5 -->
18+- Atlas 训练系列产品:不支持
19+<!-- end id5 -->
20+ 
21+## 功能说明
22+ 
23+根据对称内存窗口资源句柄和偏移,获取指定rank ID的远端对称内存窗口中该偏移对应的地址指针。
24+ 
25+<!-- npu="950" id6 -->
26+针对Ascend 950PR/Ascend 950DT,本接口支持URMA场景。
27+<!-- end id6 -->
28+ 
29+## 函数原型
30+ 
31+```c
32+HcclResult HcclSymWinGetRemoteAddr(HcclCommSymWindow winHandle, size_t offset, uint32_t peerRank, void** ptr)
33+```
34+ 
35+## 参数说明
36+ 
37+| 参数名 | 输入/输出 | 描述 |
38+| --- | --- | --- |
39+| winHandle | 输入 | 对称内存窗口资源句柄。<br>HcclCommSymWindow类型的定义可参见[HcclCommSymWindow](./data_type_definition/HcclCommSymWindow.md)。 |
40+| offset | 输入 | 使用[HcclCommSymWinGet](HcclCommSymWinGet.md)获取到的偏移量。 |
41+| peerRank | 输入 | rank ID,取值范围:[0, rankSize)。 |
42+| ptr | 输出 | 指向“远端对称内存窗口中对应地址”的指针。 |
43+ 
44+## 返回值
45+ 
46+[HcclResult](./data_type_definition/HcclResult.md):接口成功返回HCCL_SUCCESS,其他失败。
47+ 
48+## 约束说明
49+ 
50+<!-- npu="950" id7 -->
51+- 针对Ascend 950PR/Ascend 950DT,仅支持URMA场景。该场景下:
52+ - 调用该接口前需确保对称内存窗口已完成注册,且相关URMA通信通道已完成建链和远端内存信息更新。
53+ 
54+ 使用集合通信接口时,相关通道创建和远端内存信息更新由集合通信内部完成;使用独立通信通道资源接口时,需在通道创建成功后再调用该接口。
55+ - 传入的winHandle必须为已注册的有效对称内存窗口句柄。若通过[HcclCommSymWinGet](HcclCommSymWinGet.md)获取窗口句柄时未命中,返回的winHandle为空,不能继续传入本接口;若对应peerRank的远端内存信息尚未完成更新,本接口将返回错误。
56+ - 若窗口非URMA模式,本接口将返回错误并将*ptr置为nullptr,此时应改用[HcclSymWinGetPeerPointer](HcclSymWinGetPeerPointer.md)获取地址。
严正行
严正行严正行12 天前

[MEDIUM] 资料同步:HcclCommSymWinRegister.md交叉引用未随接口语义拆分更新

问题分析

  • 本PR将950 URMA场景的远端地址获取从 HcclSymWinGetPeerPointer 迁移到 HcclSymWinGetRemoteAddr,且 HcclSymWinGetPeerPointer 对URMA模式窗口已返回 HCCL_E_NOT_SUPPORT(aicpu_symmetric_memory.cc 第39-43行)。
  • docs/zh/api_ref/comm_mgr_c/HcclCommSymWinRegister.md 第30行(950 URMA场景说明)仍写「在远端内存信息更新完成前,不应调用HcclSymWinGetPeerPointer获取远端地址」,隐含更新完成后即可用该接口获取远端地址,与合入后行为不符——950用户按该指引调用将始终得到 NOT_SUPPORT。

建议修复: 将 HcclCommSymWinRegister.md 第30行的 HcclSymWinGetPeerPointer 引用改为 HcclSymWinGetRemoteAddr(链接同步改为 HcclSymWinGetRemoteAddr.md),与本PR的接口语义拆分保持一致。

likedislike
57+<!-- end id7 -->
58+- 该接口仅支持通信算子展开模式为AI CPU的场景。
59+- 该接口仅支持在Device侧调用。
60+ 
61+## 调用示例
62+ 
63+HOST侧注册完对称内存window以后,将window作为AI CPU kernel的参数传递到AI CPU kernel,该函数需要编译到Device AI CPU侧执行,以下是伪代码描述:
64+ 
65+```c
66+AicpuKernelFunc(param):
67+// 从param中获取对称window
68+HcclCommSymWindow temp_win = param.win;
69+void *remote_ptr;
70+uint32_t peerRankId = 1;
71+// 使用win + offset + peerRank获取到peerRank对应的远端地址
72+HcclSymWinGetRemoteAddr(temp_win, 0, peerRankId, &remote_ptr);
73+// 获取出来的地址可以使用数据面local copy直接读写,thread和size需调用者准备好
74+HcommLocalCopyOnThread(thread, remote_ptr, src_ptr, size);
75+```
@@ -42,6 +42,7 @@
42 - [HcclCommSymWinDeregister](HcclCommSymWinDeregister.md)42 - [HcclCommSymWinDeregister](HcclCommSymWinDeregister.md)
43 - [HcclCommSymWinGet](HcclCommSymWinGet.md)43 - [HcclCommSymWinGet](HcclCommSymWinGet.md)
44 - [HcclSymWinGetPeerPointer](HcclSymWinGetPeerPointer.md)44 - [HcclSymWinGetPeerPointer](HcclSymWinGetPeerPointer.md)
45+ - [HcclSymWinGetRemoteAddr](HcclSymWinGetRemoteAddr.md)
45 46 
46- [组调用](group_call.md)47- [组调用](group_call.md)
47 - [HcclGroupStart](HcclGroupStart.md)48 - [HcclGroupStart](HcclGroupStart.md)
@@ -32,6 +32,17 @@ extern "C" {
32 */32 */
33extern HcclResult HcclSymWinGetPeerPointer(HcclCommSymWindow winHandle, size_t offset, uint32_t peerRank, void** ptr);33extern HcclResult HcclSymWinGetPeerPointer(HcclCommSymWindow winHandle, size_t offset, uint32_t peerRank, void** ptr);
34 34 
35+/**
36+ * @brief Get remote symmetric memory pointer (for URMA).
37+ *
38+ * @param winHandle A pointer identifying the registered memory window handle.
39+ * @param offset A size_t identifying the offset of symmetric memory heap.
40+ * @param peerRank A u_integer identifying the identify for the peer rank.
41+ * @param ptr A pointer identifying the remote symmetric memory heap address.
42+ * @return HcclResult
43+ */
44+extern HcclResult HcclSymWinGetRemoteAddr(HcclCommSymWindow winHandle, size_t offset, uint32_t peerRank, void** ptr);
45+ 
35#ifdef __cplusplus46#ifdef __cplusplus
36}47}
37#endif // __cplusplus48#endif // __cplusplus
@@ -35,7 +35,12 @@ HcclResult HcclSymWinGetPeerPointer(HcclCommSymWindow winHandle, size_t offset,
35{35{
36 CHK_PTR_NULL(winHandle);36 CHK_PTR_NULL(winHandle);
37 CHK_PTR_NULL(ptr);37 CHK_PTR_NULL(ptr);
38- SymmetricWindow* symWin = reinterpret_cast<SymmetricWindow*>(winHandle);38+ SymmetricWindow* symWin = static_cast<SymmetricWindow*>(winHandle);
39+ if (symWin->mode == SymmetricMemoryMode::URMA) {
严正行
严正行严正行12 天前

[MEDIUM] HcclSymWinGetPeerPointer新增的URMA拒绝分支缺少UT覆盖

问题分析

  • 第39-43行:本PR为 HcclSymWinGetPeerPointer 新增了 mode==URMA 时返回 HCCL_E_NOT_SUPPORT 并置 *ptr=nullptr 的行为变更分支(此前URMA模式返回成功并输出远端地址)。
  • 新增的 ut_aicpu_symmetric_memory.cc 仅覆盖 HcclSymWinGetRemoteAddr(8个用例),HcclSymWinGetPeerPointer 的URMA拒绝分支无任何UT;ut_aicpu_communicator.cc 第109-110行的既有调用也不校验返回值且窗口mode未初始化,无法覆盖该分支。
  • 该分支属于对外API行为变更点,是回归风险位置。

建议修复: 在 ut_aicpu_symmetric_memory.cc 补充对称用例:

// 测试目的:PeerPointer在URMA模式下不再支持,预期返回HCCL_E_NOT_SUPPORT且*ptr置为nullptr
TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetPeerPointer_When_ModeIsURMA_Expect_ReturnIsHCCL_E_NOT_SUPPORT)
{
    SymmetricWindow win{};
    win.mode = SymmetricMemoryMode::URMA;
    void* ptr = reinterpret_cast<void*>(0xDEAD);
    HcclResult ret = HcclSymWinGetPeerPointer(reinterpret_cast<HcclCommSymWindow>(&win), 0, 0, &ptr);
    EXPECT_EQ(ret, HCCL_E_NOT_SUPPORT);
    EXPECT_EQ(ptr, nullptr);
}
likedislike
RocketHcgs
RocketHcgs
11 天前 评论:
40+ HCCL_ERROR("[HcclSymWinGetPeerPointer] not support URMA mode, winHandle[%p] is URMA mode.", winHandle);
41+ *ptr = nullptr;
42+ return HCCL_E_NOT_SUPPORT;
43+ }
atomgit-bot
atomgit-botatomgit-bot8月5日

🟠 High Priority

HcclSymWinGetPeerPointer 中,当 symWin->mode == SymmetricMemoryMode::URMA 时(第39行),函数仅打印一条 WARNING 后返回 HCCL_SUCCESS,但未对输出参数 *ptr 赋值。

变更行 → 受影响的契约: 旧代码在 URMA 分支中会正确设置 *ptr = reinterpret_cast<void*>(...) + offset 再返回。新代码将该逻辑移除,但返回了 HCCL_SUCCESS 且不写入 *ptr

失效模式: 调用方检查返回值得到 HCCL_SUCCESS,认为操作成功并使用未初始化的 *ptr(或保持调用前的旧值),导致:

建议:返回错误码或至少将 *ptr 置为 nullptr,避免调用方在成功返回值下使用未初始化的指针。

改动建议
43
+ if (symWin->mode == SymmetricMemoryMode::URMA) {
44
+ HCCL_WARNING("[HcclSymWinGetPeerPointer] winHandle[%p] is URMA mode, use HcclSymWinGetRemoteMem instead.", winHandle);
45
+ *ptr = nullptr;
46
+ return HCCL_E_NOT_SUPPORT;
43
47
  }
应用建议
likedislike
39 CHK_PRT_RET(44 CHK_PRT_RET(
40 peerRank >= symWin->rankSize,45 peerRank >= symWin->rankSize,
41 HCCL_ERROR("[HcclSymWinGetPeerPointer] Invalid peerRank: %d. rankSize[%u]", peerRank, symWin->rankSize),46 HCCL_ERROR("[HcclSymWinGetPeerPointer] Invalid peerRank: %d. rankSize[%u]", peerRank, symWin->rankSize),
@@ -44,31 +49,6 @@ HcclResult HcclSymWinGetPeerPointer(HcclCommSymWindow winHandle, size_t offset,
44 offset >= symWin->userSize,49 offset >= symWin->userSize,
45 HCCL_ERROR("[%s] Invalid offset: %llu. userSize[%llu]", __func__, offset, symWin->userSize), HCCL_E_PARA);50 HCCL_ERROR("[%s] Invalid offset: %llu. userSize[%llu]", __func__, offset, symWin->userSize), HCCL_E_PARA);
46 51 
47- if (symWin->mode == SymmetricMemoryMode::URMA) {
48- CHK_PTR_NULL(symWin->remoteMems);
49- CHK_PRT_RET(
50- peerRank >= symWin->remoteMemNum,
51- HCCL_ERROR(
52- "[HcclSymWinGetPeerPointer] Invalid peerRank: %d. remoteMemNum[%u]", peerRank, symWin->remoteMemNum),
53- HCCL_E_PARA);
54- CommMem& remoteMem = symWin->remoteMems[peerRank];
55- CHK_PRT_RET(
56- remoteMem.addr == nullptr || remoteMem.type == COMM_MEM_TYPE_INVALID,
57- HCCL_ERROR(
58- "[HcclSymWinGetPeerPointer] remote mem is invalid, peerRank[%u], addr[%p], type[%d].", peerRank,
59- remoteMem.addr, remoteMem.type),
60- HCCL_E_PARA);
61- CHK_PRT_RET(
62- offset >= remoteMem.size,
63- HCCL_ERROR("[%s] Invalid offset: %llu. remoteMemSize[%llu]", __func__, offset, remoteMem.size),
64- HCCL_E_PARA);
65- *ptr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(remoteMem.addr) + offset);
66- HCCL_INFO(
67- "[HcclSymWinGetPeerPointer] Get URMA Ptr[%p] from winHandle[%p], peerRank[%d], offset[%llu]", *ptr,
68- winHandle, peerRank, offset);
69- return HCCL_SUCCESS;
70- }
71- 
72 size_t peerOffset = peerRank * symWin->stride + offset;52 size_t peerOffset = peerRank * symWin->stride + offset;
73 *ptr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(symWin->baseVa) + peerOffset);53 *ptr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(symWin->baseVa) + peerOffset);
74 HCCL_INFO(54 HCCL_INFO(
@@ -78,6 +58,39 @@ HcclResult HcclSymWinGetPeerPointer(HcclCommSymWindow winHandle, size_t offset,
78 return HCCL_SUCCESS;58 return HCCL_SUCCESS;
79}59}
80 60 
61+HcclResult HcclSymWinGetRemoteAddr(HcclCommSymWindow winHandle, size_t offset, uint32_t peerRank, void** ptr)
严正行
严正行严正行12 天前

[MEDIUM] 新增对外API实现落在src/legacy/,与「legacy不承接新特性」架构约束冲突

问题分析

  • 第61行:HcclSymWinGetRemoteAddr 是本PR新增的对外C接口(include/hccl/hccl_sym_win.h 已在 CMakeLists.txt 与 CommLib.xml 对外发布),实现落在 src/legacy/ascend910/framework/device/framework/
  • 仓库AGENTS.md架构约束明确:src/legacy/ 仅历史兼容,不承接新特性,新特性应落 base_comm/coll_communicator_mgr/
  • 对称内存存量代码确在legacy下(先例243682c2e A5 symmetric memory),本PR是在存量模块上新增对外API入口而非bug修复。

建议修复

  • 若对称内存模块维持原位演进策略,请在PR描述或检视回复中说明该模块的架构演进口径(后续是否随coll_communicator_mgr归一);
  • 若无豁免依据,新对外接口的实现位置应遵循架构约束规划,避免legacy目录继续承接新特性膨胀。
likedislike
62+{
63+ CHK_PTR_NULL(winHandle);
64+ CHK_PTR_NULL(ptr);
65+ SymmetricWindow* symWin = static_cast<SymmetricWindow*>(winHandle);
66+ if (symWin->mode != SymmetricMemoryMode::URMA) {
严正行
严正行严正行12 天前

[MEDIUM] 单rank URMA窗口devWin内容未初始化,本接口防御检查基于不确定数据

问题分析

  • 第65-66行:本接口通过 static_cast<SymmetricWindow*>(winHandle) 读取 mode/remoteMems/remoteMemNum 做防御检查。
  • SymmetricMemory::RegisterUrmaSymmetricMem(symmetric_memory.cc 第823-828行)在 isSingleRank_ 分支仅 hrtMalloc(devWin, sizeof(SymmetricWindow)) 后直接返回,未填充任何字段——devWin指向的device内存为分配残留值(非零初始化)。
  • 若残留 mode 恰好等于 URMA(1),第66行的模式检查被绕过:remoteMems 为野指针,CHK_PTR_NULL 可能通过,remoteMemNum 为垃圾值,最终可能基于垃圾 remoteMem.addr 计算地址并返回 HCCL_SUCCESS,静默输出错误地址比崩溃更难定位。
  • 本接口文档承诺「若窗口非URMA模式,本接口将返回错误并将*ptr置为nullptr」,该防御承诺对未初始化窗口不可靠。

建议修复: 单rank分支注册时先填充最小合法内容(mode/remoteMems/remoteMemNum 置零)再返回,确保防御检查可靠生效:

if (isSingleRank_) {
    HCCL_INFO("[SymmetricMemory][RegisterUrmaSymmetricMem] single rank communicator");
    CHK_RET(hrtMalloc(devWin, sizeof(SymmetricWindow)));
    SymmetricWindow initWin{}; // mode=HCCS(0), remoteMems=nullptr, remoteMemNum=0
    CHK_RET(hrtMemSyncCopy(*devWin, sizeof(SymmetricWindow), &initWin, sizeof(SymmetricWindow),
        HcclRtMemcpyKind::HCCL_RT_MEMCPY_KIND_HOST_TO_DEVICE));
    singleRankUrmaWindows_.emplace(*devWin);
    return HCCL_SUCCESS;
}

(注:窗口构造为存量代码,但本PR新增的对外API扩大了该未初始化窗口的暴露面,建议随本PR一并加固或在检视回复中说明单rank场景的调用约束。)

likedislike
RocketHcgs
RocketHcgs
11 天前 评论:
67+ HCCL_ERROR("[HcclSymWinGetRemoteAddr] only support URMA mode, winHandle[%p] is not URMA mode.", winHandle);
68+ *ptr = nullptr;
69+ return HCCL_E_NOT_SUPPORT;
70+ }
atomgit-bot
atomgit-botatomgit-bot8月5日

🟠 High Priority

HcclSymWinGetRemoteMem 中,当 symWin->mode != SymmetricMemoryMode::URMA 时(第61行),函数仅打印 WARNING 后返回 HCCL_SUCCESS,但未对输出参数 *ptr 赋值。

变更行 → 受影响的契约: 这是新增的 API 函数,其语义为"获取远端对称内存指针"。当调用方在非 URMA 模式的窗口上调用此函数时,函数声明操作成功但 *ptr 未被初始化。

失效模式: 调用方检查返回值为 HCCL_SUCCESS 后使用未初始化的 *ptr,可能导致段错误或静默数据损坏。虽然目前该函数尚无外部调用方(仅声明和定义),但作为公开 API 这是一个潜伏的缺陷。

建议:返回错误码或将 *ptr 置为 nullptr,避免在非 URMA 模式下返回成功但不设置输出参数。

改动建议
70
+ if (symWin->mode != SymmetricMemoryMode::URMA) {
71
+ HCCL_WARNING("[HcclSymWinGetRemoteMem] winHandle[%p] is not URMA mode.", winHandle);
72
+ *ptr = nullptr;
73
+ return HCCL_E_NOT_SUPPORT;
70
74
  }
应用建议
likedislike
71+ CHK_PTR_NULL(symWin->remoteMems);
72+ CHK_PRT_RET(
73+ peerRank >= symWin->remoteMemNum,
74+ HCCL_ERROR("[HcclSymWinGetRemoteAddr] Invalid peerRank: %d. remoteMemNum[%u]", peerRank, symWin->remoteMemNum),
75+ HCCL_E_PARA);
76+ CommMem& remoteMem = symWin->remoteMems[peerRank];
77+ CHK_PRT_RET(
78+ remoteMem.addr == nullptr || remoteMem.type == COMM_MEM_TYPE_INVALID,
79+ HCCL_ERROR(
80+ "[HcclSymWinGetRemoteAddr] remote mem is invalid, peerRank[%u], addr[%p], type[%d].", peerRank,
81+ remoteMem.addr, remoteMem.type),
82+ HCCL_E_PARA);
83+ CHK_PRT_RET(
84+ offset >= remoteMem.size,
85+ HCCL_ERROR("[%s] Invalid offset: %llu. remoteMemSize[%llu]", __func__, offset, remoteMem.size), HCCL_E_PARA);
86+ *ptr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(remoteMem.addr) + offset);
87+ HCCL_INFO(
88+ "[HcclSymWinGetRemoteAddr] Get URMA Ptr[%p] from winHandle[%p], peerRank[%d], offset[%llu]", *ptr, winHandle,
89+ peerRank, offset);
90+ 
91+ return HCCL_SUCCESS;
92+}
93+ 
81#ifdef __cplusplus94#ifdef __cplusplus
82}95}
83#endif // __cplusplus96#endif // __cplusplus
@@ -15,6 +15,7 @@ set(src_to_test_list
15 ut_hccl_mem_alloc.cc15 ut_hccl_mem_alloc.cc
16 ut_hccl_communicator_host.cc16 ut_hccl_communicator_host.cc
17 ut_aicpu_communicator.cc17 ut_aicpu_communicator.cc
18+ ut_aicpu_symmetric_memory.cc
18)19)
19 20 
20add_executable(hccl_utest_framework_symmetric_memory ${src_to_test_list})21add_executable(hccl_utest_framework_symmetric_memory ${src_to_test_list})
@@ -0,0 +1,153 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+#include "gtest/gtest.h"
12+#include <mockcpp/mockcpp.hpp>
13+ 
14+#ifndef private
15+#define private public
16+#define protected public
17+#endif
18+#include "symmetric_memory.h"
19+#undef private
20+#undef protected
21+#include "hccl_sym_win.h"
22+ 
23+using namespace hccl;
24+ 
25+namespace {
26+// 构造一个 mode 为 URMA 的 SymmetricWindow,仅填充本接口访问的字段(mode/remoteMems/remoteMemNum),其余置零。
27+SymmetricWindow BuildUrmaSymmetricWindow(CommMem* remoteMems, u32 remoteMemNum)
28+{
29+ SymmetricWindow win{};
30+ win.mode = SymmetricMemoryMode::URMA;
31+ win.remoteMems = remoteMems;
32+ win.remoteMemNum = remoteMemNum;
33+ return win;
34+}
35+ 
36+// 构造一个合法的 CommMem。
37+CommMem BuildValidCommMem(void* addr, uint64_t size, CommMemType type = COMM_MEM_TYPE_DEVICE)
38+{
39+ CommMem mem{};
40+ mem.type = type;
41+ mem.addr = addr;
42+ mem.size = size;
43+ return mem;
44+}
45+} // namespace
46+ 
47+class AicpuSymmetricMemoryTest : public testing::Test {
48+protected:
49+ static void SetUpTestCase() { std::cout << "AicpuSymmetricMemoryTest SetUP" << std::endl; }
50+ static void TearDownTestCase() { std::cout << "AicpuSymmetricMemoryTest TearDown" << std::endl; }
51+ virtual void SetUp() { std::cout << "AicpuSymmetricMemoryTest Test SetUP" << std::endl; }
52+ virtual void TearDown()
53+ {
54+ GlobalMockObject::verify();
55+ std::cout << "AicpuSymmetricMemoryTest Test TearDown" << std::endl;
56+ }
57+};
58+ 
59+// 测试目的:winHandle为空指针时参数校验失败,预期返回HCCL_E_PTR
60+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_WinHandleIsNull_Expect_ReturnIsHCCL_E_PTR)
61+{
62+ void* ptr = nullptr;
63+ HcclResult ret = HcclSymWinGetRemoteAddr(nullptr, 0, 0, &ptr);
64+ EXPECT_EQ(ret, HCCL_E_PTR);
65+}
66+ 
67+// 测试目的:输出指针ptr为空时参数校验失败,预期返回HCCL_E_PTR
68+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_PtrIsNull_Expect_ReturnIsHCCL_E_PTR)
69+{
70+ SymmetricWindow win{};
71+ HcclResult ret = HcclSymWinGetRemoteAddr(reinterpret_cast<HcclCommSymWindow>(&win), 0, 0, nullptr);
72+ EXPECT_EQ(ret, HCCL_E_PTR);
73+}
74+ 
75+// 测试目的:窗口模式非URMA时不支持该接口,预期返回HCCL_E_NOT_SUPPORT且*ptr置为nullptr
76+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_ModeIsNotURMA_Expect_ReturnIsHCCL_E_NOT_SUPPORT)
77+{
78+ SymmetricWindow win{};
79+ win.mode = SymmetricMemoryMode::HCCS; // 非 URMA
80+ void* ptr = reinterpret_cast<void*>(0xDEAD); // 哨兵值
81+ HcclResult ret = HcclSymWinGetRemoteAddr(reinterpret_cast<HcclCommSymWindow>(&win), 0, 0, &ptr);
82+ EXPECT_EQ(ret, HCCL_E_NOT_SUPPORT);
83+ EXPECT_EQ(ptr, nullptr); // 验证 *ptr 被置为 nullptr
84+}
85+ 
86+// 测试目的:URMA模式下remoteMems为空指针时参数校验失败,预期返回HCCL_E_PTR
87+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_RemoteMemsIsNull_Expect_ReturnIsHCCL_E_PTR)
88+{
89+ SymmetricWindow win = BuildUrmaSymmetricWindow(nullptr, 0);
90+ void* ptr = nullptr;
91+ HcclResult ret = HcclSymWinGetRemoteAddr(reinterpret_cast<HcclCommSymWindow>(&win), 0, 0, &ptr);
92+ EXPECT_EQ(ret, HCCL_E_PTR);
93+}
94+ 
95+// 测试目的:peerRank越界(>=remoteMemNum)时参数校验失败,预期返回HCCL_E_PARA
96+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_PeerRankOutOfRange_Expect_ReturnIsHCCL_E_PARA)
97+{
98+ CommMem remoteMems[2] = {};
99+ SymmetricWindow win = BuildUrmaSymmetricWindow(remoteMems, 2);
100+ void* ptr = nullptr;
101+ // peerRank=2 等于 remoteMemNum, >= 成立
102+ HcclResult ret = HcclSymWinGetRemoteAddr(reinterpret_cast<HcclCommSymWindow>(&win), 0, 2, &ptr);
103+ EXPECT_EQ(ret, HCCL_E_PARA);
104+}
105+ 
106+// 测试目的:远端内存addr为空指针时参数校验失败,预期返回HCCL_E_PARA(覆盖||短路左侧)
107+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_RemoteMemAddrIsNull_Expect_ReturnIsHCCL_E_PARA)
108+{
109+ CommMem remoteMems[2] = {};
110+ remoteMems[1] = BuildValidCommMem(nullptr, 1024, COMM_MEM_TYPE_DEVICE);
111+ SymmetricWindow win = BuildUrmaSymmetricWindow(remoteMems, 2);
112+ void* ptr = nullptr;
113+ HcclResult ret = HcclSymWinGetRemoteAddr(reinterpret_cast<HcclCommSymWindow>(&win), 0, 1, &ptr);
114+ EXPECT_EQ(ret, HCCL_E_PARA);
115+}
116+ 
117+// 测试目的:远端内存type为COMM_MEM_TYPE_INVALID时参数校验失败,预期返回HCCL_E_PARA(覆盖||短路右侧)
118+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_RemoteMemTypeIsInvalid_Expect_ReturnIsHCCL_E_PARA)
119+{
120+ CommMem remoteMems[2] = {};
121+ remoteMems[1] = BuildValidCommMem(reinterpret_cast<void*>(0x5000000), 1024, COMM_MEM_TYPE_INVALID);
122+ SymmetricWindow win = BuildUrmaSymmetricWindow(remoteMems, 2);
123+ void* ptr = nullptr;
124+ HcclResult ret = HcclSymWinGetRemoteAddr(reinterpret_cast<HcclCommSymWindow>(&win), 0, 1, &ptr);
125+ EXPECT_EQ(ret, HCCL_E_PARA);
126+}
127+ 
128+// 测试目的:offset越界(>=remoteMem.size)时参数校验失败,预期返回HCCL_E_PARA
129+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_OffsetOutOfSize_Expect_ReturnIsHCCL_E_PARA)
130+{
131+ CommMem remoteMems[2] = {};
132+ remoteMems[1] = BuildValidCommMem(reinterpret_cast<void*>(0x5000000), 1024, COMM_MEM_TYPE_DEVICE);
133+ SymmetricWindow win = BuildUrmaSymmetricWindow(remoteMems, 2);
134+ void* ptr = nullptr;
135+ // offset=1024 等于 size, >= 成立
136+ HcclResult ret = HcclSymWinGetRemoteAddr(reinterpret_cast<HcclCommSymWindow>(&win), 1024, 1, &ptr);
137+ EXPECT_EQ(ret, HCCL_E_PARA);
138+}
139+ 
140+// 测试目的:全部参数合法时获取远端内存地址,预期返回HCCL_SUCCESS且*ptr等于remoteMem.addr+offset
141+TEST_F(AicpuSymmetricMemoryTest, Ut_HcclSymWinGetRemoteAddr_When_AllValid_Expect_ReturnIsHCCL_SUCCESS)
142+{
143+ const uint64_t offset = 256;
144+ const uint64_t size = 1024;
145+ void* baseAddr = reinterpret_cast<void*>(0x5000000);
146+ CommMem remoteMems[2] = {};
147+ remoteMems[1] = BuildValidCommMem(baseAddr, size, COMM_MEM_TYPE_DEVICE);
148+ SymmetricWindow win = BuildUrmaSymmetricWindow(remoteMems, 2);
149+ void* ptr = nullptr;
150+ HcclResult ret = HcclSymWinGetRemoteAddr(reinterpret_cast<HcclCommSymWindow>(&win), offset, 1, &ptr);
151+ EXPECT_EQ(ret, HCCL_SUCCESS);
152+ EXPECT_EQ(ptr, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(baseAddr) + offset));
153+}