| @@ -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)获取地址。 |
| 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)获取地址。 | ||
[MEDIUM] 资料同步:HcclCommSymWinRegister.md交叉引用未随接口语义拆分更新 问题分析:
建议修复:
将 HcclCommSymWinRegister.md 第30行的 ![]() ![]() | |||
| 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 | */ |
| 33 | extern HcclResult HcclSymWinGetPeerPointer(HcclCommSymWindow winHandle, size_t offset, uint32_t peerRank, void** ptr); | 33 | extern 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 | 46 | ||
| 36 | } | 47 | } |
| 37 | 48 | ||
| @@ -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) { | ||||||||||||
[MEDIUM] HcclSymWinGetPeerPointer新增的URMA拒绝分支缺少UT覆盖 问题分析:
建议修复: 在 ut_aicpu_symmetric_memory.cc 补充对称用例:
![]() ![]() | |||||||||||||
| 40 | + HCCL_ERROR("[HcclSymWinGetPeerPointer] not support URMA mode, winHandle[%p] is URMA mode.", winHandle); | ||||||||||||
| 41 | + *ptr = nullptr; | ||||||||||||
| 42 | + return HCCL_E_NOT_SUPPORT; | ||||||||||||
| 43 | + } | ||||||||||||
🟠 High Priority 在 变更行 → 受影响的契约: 旧代码在 URMA 分支中会正确设置 失效模式: 调用方检查返回值得到 建议:返回错误码或至少将 *ptr 置为 nullptr,避免调用方在成功返回值下使用未初始化的指针。 改动建议
![]() ![]() | |||||||||||||
| 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) | ||||||||||||
[MEDIUM] 新增对外API实现落在src/legacy/,与「legacy不承接新特性」架构约束冲突 问题分析:
建议修复:
![]() ![]() | |||||||||||||
| 62 | +{ | ||||||||||||
| 63 | + CHK_PTR_NULL(winHandle); | ||||||||||||
| 64 | + CHK_PTR_NULL(ptr); | ||||||||||||
| 65 | + SymmetricWindow* symWin = static_cast<SymmetricWindow*>(winHandle); | ||||||||||||
| 66 | + if (symWin->mode != SymmetricMemoryMode::URMA) { | ||||||||||||
[MEDIUM] 单rank URMA窗口devWin内容未初始化,本接口防御检查基于不确定数据 问题分析:
建议修复: 单rank分支注册时先填充最小合法内容(mode/remoteMems/remoteMemNum 置零)再返回,确保防御检查可靠生效:
(注:窗口构造为存量代码,但本PR新增的对外API扩大了该未初始化窗口的暴露面,建议随本PR一并加固或在检视回复中说明单rank场景的调用约束。) ![]() ![]() | |||||||||||||
| 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 | + } | ||||||||||||
🟠 High Priority 在 变更行 → 受影响的契约: 这是新增的 API 函数,其语义为"获取远端对称内存指针"。当调用方在非 URMA 模式的窗口上调用此函数时,函数声明操作成功但 失效模式: 调用方检查返回值为 建议:返回错误码或将 *ptr 置为 nullptr,避免在非 URMA 模式下返回成功但不设置输出参数。 改动建议
![]() ![]() | |||||||||||||
| 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 | 94 | ||||||||||||
| 82 | } | 95 | } | ||||||||||
| 83 | 96 | ||||||||||||
| @@ -15,6 +15,7 @@ set(src_to_test_list | |||
| 15 | ut_hccl_mem_alloc.cc | 15 | ut_hccl_mem_alloc.cc |
| 16 | ut_hccl_communicator_host.cc | 16 | ut_hccl_communicator_host.cc |
| 17 | ut_aicpu_communicator.cc | 17 | ut_aicpu_communicator.cc |
| 18 | + ut_aicpu_symmetric_memory.cc | ||
| 18 | ) | 19 | ) |
| 19 | 20 | ||
| 20 | add_executable(hccl_utest_framework_symmetric_memory ${src_to_test_list}) | 21 | add_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 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 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 | +} | ||


[LOW] URMA模式提示语放在A3条件块内,目标读者错位
问题分析:
<!-- npu="A3" id6 -->条件块内。建议修复: 将该URMA提示移到950可见的位置(或公共正文),确保950用户误用本接口时能看到改用
HcclSymWinGetRemoteAddr的指引;A3块内只保留HCCS相关说明。