LCOV - code coverage report
Current view: top level - base_comm/resources/endpoint_pairs - endpoint_pair.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 96.1 % 155 149
Test Date: 2026-08-25 19:18:03 Functions: 100.0 % 16 16

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 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 "endpoint_pair.h"
      12              : #include "socket_config.h"
      13              : #include "hcomm_c_adpt.h"
      14              : #include "orion_adpt_utils.h"
      15              : #include "channel_process.h"
      16              : #include "comm_engine_utils.h"
      17              : 
      18              : #include "hcom_common.h"
      19              : #include "exception_handler.h"
      20              : 
      21              : namespace hcomm {
      22              : 
      23           39 : EndpointPair::~EndpointPair()
      24              : {
      25           78 :     for (auto& channels : channelHandles_) {
      26           39 :         if (channels.second.empty()) {
      27           17 :             continue;
      28              :         }
      29           22 :         (void)ChannelProcess::ChannelDestroy(channels.second.data(), channels.second.size());
      30              :     }
      31           39 : }
      32              : 
      33           38 : HcclResult EndpointPair::Init()
      34              : {
      35           38 :     std::lock_guard<std::mutex> lock(channelMtx_);
      36           38 :     EXCEPTION_CATCH(socketMgr_ = std::make_unique<SocketMgr>(), return HCCL_E_PTR);
      37           38 :     channelHandles_.clear();
      38              :     s32 devLogicId;
      39           38 :     CHK_RET(hrtGetDevice(&devLogicId));
      40           38 :     CHK_RET(hrtGetDevicePhyIdByIndex(static_cast<u32>(devLogicId), devicePhyId_));
      41              : 
      42           38 :     return HCCL_SUCCESS;
      43           38 : }
      44              : 
      45            3 : HcclResult EndpointPair::GetHostSocketWithRank(
      46              :     const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, const uint32_t listenPort,
      47              :     u32 reuseIdx, Hccl::Socket*& socket)
      48              : {
      49            3 :     uint32_t connectMode = 0;
      50            3 :     Hccl::LinkData linkData = BuildDefaultLinkData();
      51            3 :     CHK_RET(EndpointDescPairToLinkData(localEndpointDesc_, remoteEndpointDesc_, linkData, reuseIdx));
      52            3 :     std::string linkTag = socketTag;
      53            3 :     if (linkData.GetReuseIdx() != "0") {
      54            0 :         linkTag += ("_" + linkData.GetReuseIdx());
      55              :     }
      56              : 
      57              :     DevType devType;
      58            3 :     CHK_RET(hrtGetDeviceType(devType));
      59            3 :     if (devType == DevType::DEV_TYPE_910B && localEndpointDesc_.loc.locType != remoteEndpointDesc_.loc.locType) {
      60            0 :         connectMode = 1;
      61              :     }
      62              : 
      63              :     /* A2: host nic(cpu roce channel) -- device nic(transport ibv)时,两边ip地址格式不一样,判断大小算法不匹配
      64              :      * 修改成按照rank id大小判断server和client */
      65            3 :     Hccl::SocketConfig socketConfig = Hccl::SocketConfig(linkData, listenPort, linkTag, connectMode, myRank, rmtRank);
      66            3 :     CHK_RET(socketMgr_->GetHostSocket(socketConfig, socket));
      67            3 :     return HCCL_SUCCESS;
      68            3 : }
      69              : 
      70           20 : HcclResult EndpointPair::EnsureSocketMgrCompat(const uint32_t myRank, const std::string& socketTag)
      71              : {
      72              :     {
      73           20 :         std::lock_guard<std::mutex> lock(socketMgrMtx_);
      74           20 :         if (socketMgrCompat_) {
      75           12 :             return HCCL_SUCCESS;
      76              :         }
      77           20 :     }
      78              : 
      79            8 :     int32_t devLogicId = HcclGetThreadDeviceId();
      80            8 :     uint32_t devPhyId{0};
      81            8 :     CHK_RET(hrtGetDevicePhyIdByIndex(static_cast<uint32_t>(devLogicId), devPhyId));
      82            8 :     std::unique_ptr<Hccl::SocketManager> newMgr = nullptr;
      83            8 :     EXCEPTION_CATCH(
      84              :         newMgr = std::make_unique<Hccl::SocketManager>(myRank, devPhyId, devLogicId, socketTag), return HCCL_E_PTR);
      85            8 :     CHK_PTR_NULL(rankIpPortMap_);
      86            8 :     newMgr->SetDeviceServerListenPortMap(*rankIpPortMap_);
      87              : 
      88              :     {
      89            8 :         std::lock_guard<std::mutex> lock(socketMgrMtx_);
      90            8 :         if (socketMgrCompat_) {
      91            0 :             return HCCL_SUCCESS;
      92              :         }
      93            8 :         socketMgrCompat_ = std::move(newMgr);
      94            8 :     }
      95              : 
      96            8 :     return HCCL_SUCCESS;
      97            8 : }
      98              : 
      99           40 : Hccl::SocketConfig EndpointPair::BuildSocketConfig(const Hccl::LinkData& linkData, const std::string& socketTag)
     100              : {
     101           40 :     std::string linkTag = socketTag;
     102           40 :     if (linkData.GetReuseIdx() != "0") {
     103            6 :         linkTag += ("_" + linkData.GetReuseIdx());
     104              :     }
     105           80 :     return Hccl::SocketConfig(linkData.GetRemoteRankId(), linkData, linkTag);
     106           40 : }
     107              : 
     108           23 : HcclResult EndpointPair::HandleHostSocketOrBuildLinkData(
     109              :     const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx,
     110              :     const uint32_t listenPort, Hccl::Socket*& socket, uint32_t devicePhyId, uint32_t remoteDevicePhyId,
     111              :     Hccl::LinkData& linkData, bool& isHost)
     112              : {
     113           23 :     if (localEndpointDesc_.loc.locType == EndpointLocType::ENDPOINT_LOC_TYPE_HOST) {
     114            3 :         std::string socketTagPrefix = socketTag;
     115            3 :         if (myRank <= rmtRank) {
     116            2 :             socketTagPrefix += "_" + std::to_string(myRank) + "_" + std::to_string(rmtRank);
     117              :         } else {
     118            1 :             socketTagPrefix += "_" + std::to_string(rmtRank) + "_" + std::to_string(myRank);
     119              :         }
     120            3 :         CHK_RET(this->GetHostSocketWithRank(myRank, rmtRank, socketTagPrefix, listenPort, reuseIdx, socket));
     121            3 :         isHost = true;
     122            3 :         return HCCL_SUCCESS;
     123            3 :     }
     124           20 :     isHost = false;
     125           20 :     CHK_RET(EndpointDescPairToLinkDataWithRankIds(
     126              :         myRank, rmtRank, localEndpointDesc_, remoteEndpointDesc_, linkData, devicePhyId, remoteDevicePhyId, reuseIdx));
     127           20 :     return HCCL_SUCCESS;
     128              : }
     129              : 
     130           23 : HcclResult EndpointPair::GetSocketInternal(
     131              :     const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx,
     132              :     const uint32_t listenPort, Hccl::Socket*& socket, uint32_t devicePhyId, uint32_t remoteDevicePhyId,
     133              :     bool connectMode)
     134              : {
     135           23 :     Hccl::LinkData linkData = BuildDefaultLinkData();
     136           23 :     bool isHost = false;
     137           23 :     CHK_RET(HandleHostSocketOrBuildLinkData(
     138              :         myRank, rmtRank, socketTag, reuseIdx, listenPort, socket, devicePhyId, remoteDevicePhyId, linkData, isHost));
     139           23 :     if (isHost) {
     140            3 :         return HCCL_SUCCESS;
     141              :     }
     142              :     EXCEPTION_HANDLE_BEGIN
     143           20 :     Hccl::SocketConfig socketConfig = BuildSocketConfig(linkData, socketTag);
     144           20 :     if (connectMode) {
     145           20 :         CHK_PTR_NULL(socketMgrCompat_);
     146           20 :         socketMgrCompat_->ConnectSockets(socketConfig);
     147              :     } else {
     148            0 :         CHK_RET(EnsureSocketMgrCompat(myRank, socketTag));
     149            0 :         socketMgrCompat_->BatchCreateSockets(socketConfig);
     150              :     }
     151           20 :     socket = socketMgrCompat_->GetConnectedSocket(socketConfig);
     152           20 :     CHK_PTR_NULL(socket);
     153           20 :     EXCEPTION_HANDLE_END
     154           20 :     return HCCL_SUCCESS;
     155              : }
     156              : 
     157           21 : HcclResult EndpointPair::ServerInit(
     158              :     const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx, uint32_t devicePhyId,
     159              :     uint32_t remoteDevicePhyId)
     160              : {
     161           21 :     if (localEndpointDesc_.loc.locType == EndpointLocType::ENDPOINT_LOC_TYPE_HOST) {
     162              :         // host网卡不走device的socket监听
     163            1 :         return HCCL_SUCCESS;
     164              :     }
     165              :     // server监听
     166           20 :     Hccl::LinkData linkData = BuildDefaultLinkData();
     167           20 :     CHK_RET(EndpointDescPairToLinkDataWithRankIds(
     168              :         myRank, rmtRank, localEndpointDesc_, remoteEndpointDesc_, linkData, devicePhyId, remoteDevicePhyId, reuseIdx));
     169              :     EXCEPTION_HANDLE_BEGIN
     170           20 :     CHK_RET(EnsureSocketMgrCompat(myRank, socketTag));
     171           20 :     Hccl::SocketConfig socketConfig = BuildSocketConfig(linkData, socketTag);
     172              :     // 调用sock的server监听接口
     173           20 :     socketMgrCompat_->ServerListen(socketConfig);
     174           20 :     EXCEPTION_HANDLE_END
     175              : 
     176           20 :     return HCCL_SUCCESS;
     177              : }
     178              : 
     179           21 : HcclResult EndpointPair::GetConnectedSocket(
     180              :     const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx,
     181              :     const uint32_t listenPort, Hccl::Socket*& socket, uint32_t devicePhyId, uint32_t remoteDevicePhyId)
     182              : {
     183              :     // 该接口内进行建链和获取socket
     184           21 :     return GetSocketInternal(
     185           21 :         myRank, rmtRank, socketTag, reuseIdx, listenPort, socket, devicePhyId, remoteDevicePhyId, true);
     186              : }
     187              : 
     188            2 : HcclResult EndpointPair::GetSocket(
     189              :     const uint32_t myRank, const uint32_t rmtRank, const std::string& socketTag, u32 reuseIdx,
     190              :     const uint32_t listenPort, Hccl::Socket*& socket, uint32_t devicePhyId, uint32_t remoteDevicePhyId)
     191              : {
     192              :     // 临时方案:支持混跑新增,非Roce场景走orion socketMgr实现server socket复用
     193            2 :     return GetSocketInternal(
     194            2 :         myRank, rmtRank, socketTag, reuseIdx, listenPort, socket, devicePhyId, remoteDevicePhyId, false);
     195              : }
     196              : 
     197           34 : HcclResult EndpointPair::CreateChannel(
     198              :     EndpointHandle endpointHandle, CommEngine engine, u32 reuseIdx, HcommChannelDesc* channelDescs,
     199              :     ChannelHandle* channels)
     200              : {
     201           34 :     std::lock_guard<std::mutex> lock(channelMtx_);
     202           34 :     if (channelHandles_.find(engine) == channelHandles_.end() || channelHandles_[engine].size() <= reuseIdx) {
     203           24 :         CHK_RET_UNAVAIL(
     204              :             static_cast<HcclResult>(HcommCollectiveChannelCreate(endpointHandle, engine, channelDescs, 1, channels)));
     205           22 :         channelHandles_[engine].push_back(channels[0]);
     206              :         // 记录真实槽位下标:UNREUSE 通道的入参 reuseIdx 为 0xFFFFFFFF,实际槽位是 push_back 后的下标
     207           22 :         handleToLoc_[channels[0]] = {engine, static_cast<u32>(channelHandles_[engine].size() - 1)};
     208           22 :         return HCCL_SUCCESS;
     209              :     }
     210              : 
     211           10 :     channels[0] = channelHandles_[engine][reuseIdx];
     212           10 :     if (channelDescs->memHandleNum > 1) {
     213            0 :         CHK_RET(static_cast<HcclResult>(
     214              :             HcommChannelUpdateMemInfo(channelDescs->memHandles + 1, channelDescs->memHandleNum - 1, channels[0])));
     215              :     }
     216           10 :     return HCCL_SUCCESS;
     217           34 : }
     218              : 
     219              : // 找到对应的channelhandle,调用HcommChannelDestroy销毁平台层对象,并删除channelHandles_中的channelHandle元素
     220           30 : HcclResult EndpointPair::DestroyChannel(CommEngine engine, u32 reuseIdx)
     221              : {
     222           30 :     std::lock_guard<std::mutex> lock(channelMtx_);
     223           30 :     if (channelHandles_.find(engine) == channelHandles_.end() || channelHandles_[engine].size() <= reuseIdx) {
     224            1 :         HCCL_WARNING(
     225              :             "EndpointPair::DestroyChannel: engine[%s] reuseIdx[%u], channelHandle size[%u],"
     226              :             "channel not found, skip destroy channel",
     227              :             GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), reuseIdx, channelHandles_[engine].size());
     228            1 :         return HCCL_SUCCESS;
     229              :     }
     230           29 :     HCCL_INFO(
     231              :         "EndpointPair::DestroyChannel: engine[%s] reuseIdx[%u], channelHandle size[%u],"
     232              :         "start destroy channel",
     233              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), reuseIdx, channelHandles_[engine].size());
     234           29 :     ChannelHandle channelHandle = channelHandles_[engine][reuseIdx];
     235              :     // 无论 HcommChannelDestroy 成功与否,底层 channel 对象已被从全局 map 移除(channel 不可用),
     236              :     // host 侧索引必须同步清理,避免后续复用到失效 handle
     237           29 :     HcclResult destroyRet = static_cast<HcclResult>(HcommChannelDestroy(&channelHandle, 1));
     238           29 :     if (destroyRet != HCCL_SUCCESS) {
     239            2 :         HCCL_WARNING(
     240              :             "EndpointPair::DestroyChannel: HcommChannelDestroy failed, ret[%d], still clean host index.", destroyRet);
     241              :     }
     242              :     // 先删反查索引再 erase 向量: erase 会使后续元素下标前移
     243           29 :     handleToLoc_.erase(channelHandle);
     244              :     // 去掉channelHandles_中reuseIdx位置的channelHandle
     245           29 :     channelHandles_[engine].erase(channelHandles_[engine].begin() + reuseIdx);
     246              :     // 同 engine 后续 handle 因 erase 下标前移, 需同步修正反查索引
     247           29 :     auto& handlesVec = channelHandles_[engine];
     248           41 :     for (u32 idx = reuseIdx; idx < handlesVec.size(); ++idx) {
     249           12 :         auto locIt = handleToLoc_.find(handlesVec[idx]);
     250           12 :         if (locIt != handleToLoc_.end()) {
     251           10 :             locIt->second.second = idx;
     252              :         }
     253              :     }
     254           29 :     HCCL_INFO(
     255              :         "EndpointPair::DestroyChannel: engine[%s] reuseIdx[%u] destroy channel success,"
     256              :         "channelHandle size[%u]",
     257              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), reuseIdx, channelHandles_[engine].size());
     258           29 :     return destroyRet;
     259           30 : }
     260              : 
     261              : // 检查channel是否存在,channel不存在则返回true
     262           34 : bool EndpointPair::IsChannelNotExist(CommEngine engine, u32 reuseIdx)
     263              : {
     264           34 :     std::lock_guard<std::mutex> lock(channelMtx_);
     265           68 :     return channelHandles_.find(engine) == channelHandles_.end() || channelHandles_[engine].size() <= reuseIdx;
     266           34 : }
     267              : 
     268            1 : std::unordered_map<CommEngine, std::vector<ChannelHandle>> EndpointPair::GetChannelHandles() const
     269              : {
     270            1 :     std::lock_guard<std::mutex> lock(channelMtx_);
     271            2 :     return channelHandles_;
     272            1 : }
     273              : 
     274           18 : bool EndpointPair::GetChannelHandle(CommEngine engine, u32 reuseIdx, ChannelHandle& handle) const
     275              : {
     276           18 :     std::lock_guard<std::mutex> lock(channelMtx_);
     277           18 :     auto it = channelHandles_.find(engine);
     278           18 :     if (it == channelHandles_.end() || reuseIdx >= it->second.size()) {
     279            6 :         return false;
     280              :     }
     281           12 :     handle = it->second[reuseIdx];
     282           12 :     return true;
     283           18 : }
     284              : 
     285           30 : bool EndpointPair::FindChannelLoc(ChannelHandle handle, CommEngine& engine, u32& reuseIdx) const
     286              : {
     287           30 :     std::lock_guard<std::mutex> lock(channelMtx_);
     288           30 :     auto it = handleToLoc_.find(handle);
     289           30 :     if (it == handleToLoc_.end()) {
     290            1 :         return false;
     291              :     }
     292           29 :     engine = it->second.first;
     293           29 :     reuseIdx = it->second.second;
     294           29 :     return true;
     295           30 : }
     296              : 
     297              : } // namespace hcomm
        

Generated by: LCOV version 2.0-1