LCOV - code coverage report
Current view: top level - coll_communicator_mgr/resource_mgr/local/my_rank - my_rank.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 77.8 % 780 607
Test Date: 2026-08-29 17:38:31 Functions: 84.3 % 51 43

            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 "my_rank.h"
      12              : #include "hcomm_c_adpt.h"
      13              : #include "endpoint_pair.h"
      14              : #include "hccl_res.h"
      15              : #include "../common/loggers/channel_logger.h" // 日志记录器
      16              : #include "hcclCommDfx.h"
      17              : #include "config/env_config.h"
      18              : #include "env_config/env_config_v2.h"
      19              : #include "channel_process.h"
      20              : #include "ccu_dev_mgr_imp.h"
      21              : #include "ccu_device_res.h"
      22              : #include "ccu_res_desc.h"
      23              : #include "ccu_device_pub.h"
      24              : #include "ccu_res_desc_mgr.h"
      25              : #include "ccu_log.h"
      26              : #include "dlprof_function.h"
      27              : #include "config_log.h"
      28              : #include "comm_engine_utils.h"
      29              : #include "hcom_common.h"
      30              : #include "op_base.h"
      31              : #include "ccu_res.h"
      32              : #include "coll_comm_mgr.h"
      33              : #include "new_rank_info.h"
      34              : 
      35              : #include <acl/acl.h>
      36              : #include "shared_jetty_channel_pool.h"
      37              : 
      38              : using namespace hcomm;
      39              : 
      40              : namespace MyRankUtils {
      41              : 
      42           29 : uint32_t ResolveUbCommDomainQos(const hccl::CommConfig& commConfig)
      43              : {
      44           29 :     if (commConfig.GetConfigHcclQos() == HCCL_COMM_QOS_CONFIG_NOT_SET) {
      45           25 :         return EnvConfig::UB_QOS_DEFAULT;
      46              :     }
      47            4 :     return commConfig.GetConfigHcclQos();
      48              : }
      49              : 
      50           37 : HcommChannelDesc ChannelDescHccl2Hcomm(const HcclChannelDesc& hcclDesc, const hccl::CommConfig& commConfig)
      51              : {
      52           37 :     HcommChannelDesc hcommDesc{};
      53           37 :     (void)HcommChannelDescInit(&hcommDesc, 1);
      54           37 :     hcommDesc.remoteEndpoint = hcclDesc.remoteEndpoint;
      55           37 :     hcommDesc.notifyNum = hcclDesc.notifyNum;
      56           37 :     hcommDesc.memHandles = reinterpret_cast<HcommMemHandle*>(hcclDesc.memHandles);
      57           37 :     hcommDesc.memHandleNum = hcclDesc.memHandleNum;
      58           37 :     (void)memcpy_s(hcommDesc.raws, sizeof(hcommDesc.raws), hcclDesc.raws, sizeof(hcommDesc.raws));
      59              :     // RoCE:透传原始 hcclQos(可为 NOT_SET),由 CheckRoceAttr/ApplyRoceQosCompatToSlTc 决定是否映射 SL/TC
      60           37 :     if (hcclDesc.channelProtocol == COMM_PROTOCOL_ROCE) {
      61            8 :         hcommDesc.qos = commConfig.GetConfigHcclQos();
      62            8 :         hcommDesc.roceAttr.retryCnt = hcclDesc.roceAttr.retryCnt;
      63            8 :         hcommDesc.roceAttr.retryInterval = hcclDesc.roceAttr.retryInterval;
      64            8 :         hcommDesc.roceAttr.sl = hcclDesc.roceAttr.sl;
      65            8 :         hcommDesc.roceAttr.tc = hcclDesc.roceAttr.tc;
      66            8 :         return hcommDesc;
      67              :     }
      68              :     // UB 等:未配置时落默认 4,供下游 Jetty/TP 使用
      69           29 :     hcommDesc.qos = ResolveUbCommDomainQos(commConfig);
      70           29 :     if (hcclDesc.channelProtocol == COMM_PROTOCOL_UB_MEM) {
      71           16 :         hcommDesc.ubMemAttr.pathMode = hcclDesc.ubMemAttr.pathMode;
      72              :     }
      73           29 :     return hcommDesc;
      74              : }
      75              : 
      76              : /* 公共模块函数返回值定义,跟业务层同步 */
      77              : const std::unordered_map<CommProtocol, std::string> HCOM_COMM_PROTOCOL_STR_MAP
      78              :     = {{COMM_PROTOCOL_RESERVED, "RESERVED"}, {COMM_PROTOCOL_HCCS, "HCCS"},     {COMM_PROTOCOL_ROCE, "ROCE"},
      79              :        {COMM_PROTOCOL_PCIE, "PCIE"},         {COMM_PROTOCOL_SIO, "SIO"},       {COMM_PROTOCOL_UB_CTP, "UB_CTP"},
      80              :        {COMM_PROTOCOL_UBC_TP, "UBC_TP"},     {COMM_PROTOCOL_UB_MEM, "UB_MEM"}, {COMM_PROTOCOL_UBOE, "UBOE"},
      81              :        {COMM_PROTOCOL_UB_RTP, "UB_RTP"}};
      82              : 
      83            4 : inline std::string GetCommProtocolEnumStr(CommProtocol protocol)
      84              : {
      85            4 :     auto iter = HCOM_COMM_PROTOCOL_STR_MAP.find(protocol);
      86            4 :     if (iter == HCOM_COMM_PROTOCOL_STR_MAP.end()) {
      87            0 :         return "CommProtocol(" + std::to_string(protocol) + ")";
      88              :     } else {
      89            4 :         return iter->second;
      90              :     }
      91              : }
      92              : 
      93            0 : inline const char* GetTlsTypeStr(EndpointLocType localType)
      94              : {
      95            0 :     return localType == ENDPOINT_LOC_TYPE_HOST ? "HostDpu" : "Device";
      96              : }
      97              : 
      98            0 : inline const char* GetTlsStatusStr(Hccl::TlsStatus tlsStatus)
      99              : {
     100            0 :     if (tlsStatus == Hccl::TlsStatus::ENABLE) {
     101            0 :         return "ENABLE";
     102              :     }
     103            0 :     if (tlsStatus == Hccl::TlsStatus::DISABLE) {
     104            0 :         return "DISABLE";
     105              :     }
     106            0 :     return "UNKNOWN";
     107              : }
     108              : 
     109              : } // namespace MyRankUtils
     110              : 
     111            5 : HcclResult MyRankUtils::FillRoceSrcPortList(
     112              :     const HcclChannelDesc& hcclDesc, HcommChannelDesc& hcommDesc, std::vector<uint16_t>& srcPortBuf)
     113              : {
     114            5 :     hcommDesc.roceAttr.srcPortList = nullptr;
     115            5 :     if (hcommDesc.remoteEndpoint.protocol != COMM_PROTOCOL_ROCE || hcommDesc.exchangeAllMems) {
     116            3 :         HCCL_INFO(
     117              :             "[%s] skip: protocol[%d] exchangeAllMems[%d]", __func__, hcommDesc.remoteEndpoint.protocol,
     118              :             hcommDesc.exchangeAllMems);
     119            3 :         return HCCL_SUCCESS;
     120              :     }
     121            2 :     const auto& qpSrcPortConfig = Hccl::EnvConfig::GetInstance().GetRdmaConfig().GetMultiQpSrcPortConfig();
     122            2 :     if (!qpSrcPortConfig.IsAvailable()) {
     123            0 :         HCCL_INFO(
     124              :             "[%s] skip: multiQpSrcPortConfig not available (env HCCL_RDMA_QP_PORT_CONFIG_PATH unset or "
     125              :             "MultiQpSrcPort.cfg empty)",
     126              :             __func__);
     127            0 :         return HCCL_SUCCESS;
     128              :     }
     129            2 :     Hccl::IpAddress localIp;
     130            2 :     Hccl::IpAddress remoteIp;
     131            2 :     HcclResult localRet = CommAddrToIpAddress(hcclDesc.localEndpoint.commAddr, localIp);
     132            2 :     HcclResult remoteRet = CommAddrToIpAddress(hcclDesc.remoteEndpoint.commAddr, remoteIp);
     133            2 :     CHK_PRT_RET(
     134              :         localRet != HCCL_SUCCESS || remoteRet != HCCL_SUCCESS,
     135              :         HCCL_ERROR("[%s] CommAddrToIpAddress failed: localRet[%d] remoteRet[%d]", __func__, localRet, remoteRet),
     136              :         HCCL_E_INTERNAL);
     137            1 :     auto ports = Hccl::GetMultiQpSrcPortsByIpPair(qpSrcPortConfig, localIp, remoteIp);
     138            1 :     if (ports.empty()) {
     139            0 :         HCCL_INFO(
     140              :             "[%s] skip: no matching ports for localIp[%s] remoteIp[%s]", __func__, localIp.GetIpStr().c_str(),
     141              :             remoteIp.GetIpStr().c_str());
     142            0 :         return HCCL_SUCCESS;
     143              :     }
     144            1 :     u32 queueNum = hcommDesc.roceAttr.queueNum;
     145            1 :     srcPortBuf.resize(queueNum);
     146            5 :     for (u32 j = 0; j < queueNum; ++j) {
     147            4 :         srcPortBuf[j] = ports[j % ports.size()];
     148              :     }
     149            1 :     hcommDesc.roceAttr.srcPortList = srcPortBuf.data();
     150            1 :     HCCL_INFO("[%s] success: queueNum[%u] portCount[%zu]", __func__, queueNum, ports.size());
     151            1 :     return HCCL_SUCCESS;
     152            1 : }
     153              : 
     154              : namespace hccl {
     155              : 
     156              : constexpr uint32_t UNREUSE_CHANNEL_IDX = 0xFFFFFFFF;
     157              : 
     158          286 : MyRank::MyRank(
     159              :     aclrtBinHandle binHandle, uint32_t rankId, const CommConfig& config, const ManagerCallbacks& callbacks,
     160          286 :     RankGraph* rankGraph, const Hccl::RankIpPortMapPtr& rankIpPortMap)
     161          286 :     : binHandle_(binHandle),
     162          286 :       rankId_(rankId),
     163          286 :       config_(config),
     164          286 :       callbacks_(callbacks),
     165          286 :       rankGraph_(rankGraph),
     166          286 :       rankIpPortMap_(rankIpPortMap)
     167          286 : {}
     168              : 
     169          572 : MyRank::~MyRank()
     170              : {
     171          286 :     HCCL_INFO("[MyRank][~MyRank] MyRank deinit, rankId_[%u], devLogicId_[%d]", rankId_, devLogicId_);
     172              :     // 共享 Jetty Channel 不归 rankPairMgr_ 管理,需在 rankPairMgr_ 析构前独立清理
     173          286 :     (void)SharedJettyChannelPool::GetInstance().DestroyAllByMyRank(this);
     174              :     // 先清空反查索引,避免 rankPairMgr_ 析构 EndpointPair 时仍持有指向其的裸指针;
     175              :     // 持锁保证与并发 DestroyChannels 的索引读写一致
     176              :     {
     177          286 :         std::lock_guard<std::mutex> lock(channelIndexMtx_);
     178          286 :         handleToEpPair_.clear();
     179          286 :     }
     180              :     // 析构有时序要求
     181          286 :     rankPairMgr_ = nullptr; // 内部会销毁channel,可能需要返还endpoint与ccu资源
     182          286 :     endpointMgr_ = nullptr; // 内部会销毁endpoint,可能需要返回ccu资源
     183              : 
     184              :     struct ResourceCleanupGuard {
     185          286 :         explicit ResourceCleanupGuard(MyRank& myRank) : myRank_(myRank) {}
     186          286 :         ~ResourceCleanupGuard() noexcept
     187              :         {
     188          286 :             myRank_.ccuInsHandle_ = 0;
     189          286 :             myRank_.assignedCcuInsHandle_ = 0;
     190              : 
     191          286 :             if (myRank_.ccuDrvHandle_) {
     192            1 :                 myRank_.ccuDrvHandle_ = nullptr; // 先减少引用计数,再尝试关闭
     193            1 :                 (void)CcuDeinitFeature(myRank_.devLogicId_);
     194              :                 // 尝试关闭CCU功能,最后一个调用时会关闭CCU驱动
     195              :             }
     196              : 
     197          286 :             myRank_.ReleaseCcuMsCommReservation();
     198              : 
     199          286 :             myRank_.commMems_ = nullptr;
     200          286 :             myRank_.nsRecoveryProcessor_ = nullptr;
     201          286 :         }
     202              : 
     203              :         MyRank& myRank_;
     204          286 :     } cleanupGuard(*this);
     205              : 
     206          286 :     if (ccuInsHandle_ != 0 || assignedCcuInsHandle_ != 0) { // 内部清理CCU资源,关闭CCU通道
     207              :         // 刷新并获取当前线程的 DeviceId
     208           13 :         int32_t threadDevId = INVALID_INT;
     209           13 :         CHK_RET_NULL(HcclDeviceRefresh(threadDevId));
     210           13 :         HCCL_INFO("[%s] curDeviceLogicId[%d], threadDevId[%d]", __func__, devLogicId_, threadDevId);
     211              :         // 先切换为目标 curDeviceLogicId
     212           13 :         bool isDiffDevId = false;
     213           13 :         if (devLogicId_ != threadDevId) {
     214            0 :             CHK_RET_NULL(hrtSetDevice(devLogicId_));
     215            0 :             isDiffDevId = true;
     216              :         }
     217              :         // 销毁通信域自有的 ccuInstance(QueryCcuIns 创建)
     218           13 :         if (ccuInsHandle_ != 0) {
     219            6 :             CHK_PRT(static_cast<HcclResult>(HcommCcuInsDestroy(ccuInsHandle_)));
     220              :         }
     221              :         // 销毁通过 Assign 绑定的 ccuInstance(所有权已转移给通信域)
     222           13 :         if (assignedCcuInsHandle_ != 0 && assignedCcuInsHandle_ != ccuInsHandle_) {
     223            8 :             CHK_PRT(static_cast<HcclResult>(HcommCcuInsDestroy(assignedCcuInsHandle_)));
     224              :         }
     225              :         // 切换回原来的 DeviceId
     226           13 :         if (isDiffDevId) {
     227            0 :             CHK_RET_NULL(hrtSetDevice(threadDevId));
     228            0 :             CHK_PRT(HcclDeviceRefresh(threadDevId));
     229              :         }
     230              :     }
     231          572 : }
     232              : 
     233           10 : HcclResult MyRank::GetLocalTlsStatus(EndpointLocType localType, Hccl::TlsStatus& tlsStatus) const
     234              : {
     235           10 :     tlsStatus = Hccl::TlsStatus::UNKNOWN;
     236           10 :     s32 deviceLogicId = -1;
     237           10 :     u32 devicePhyId = INVALID_UINT;
     238           10 :     CHK_RET(hrtGetDevice(&deviceLogicId));
     239            9 :     CHK_RET(hrtGetDevicePhyIdByIndex(static_cast<u32>(deviceLogicId), devicePhyId));
     240              : 
     241            8 :     RaInfo info{};
     242            8 :     info.mode = localType == ENDPOINT_LOC_TYPE_HOST ? NetworkMode::NETWORK_PEER_ONLINE : NetworkMode::NETWORK_OFFLINE;
     243            8 :     info.phyId = devicePhyId;
     244            8 :     return Hccl::HrtRaGetTlsStatus(&info, tlsStatus);
     245              : }
     246              : 
     247            4 : void MyRank::GetAbnormalChannelTlsStatus(
     248              :     const HcclChannelDesc* channelDescs, const int32_t* statusList, uint32_t channelNum,
     249              :     std::vector<Hccl::TlsStatus>& tlsStatusList) const
     250              : {
     251            4 :     tlsStatusList.assign(channelNum, Hccl::TlsStatus::UNKNOWN);
     252           14 :     for (uint32_t i = 0; i < channelNum; ++i) {
     253           10 :         if (statusList[i] == ChannelStatus::READY) {
     254            3 :             continue;
     255              :         }
     256            7 :         Hccl::TlsStatus tlsStatus = Hccl::TlsStatus::UNKNOWN;
     257            7 :         HcclResult ret = GetLocalTlsStatus(channelDescs[i].localEndpoint.loc.locType, tlsStatus);
     258            7 :         if (ret != HCCL_SUCCESS) {
     259            0 :             HCCL_WARNING("[GetLocalTlsStatus] Can not get TlsStatus, channelIndex[%u], ret[%d]", i, ret);
     260            0 :             continue;
     261              :         }
     262            7 :         tlsStatusList[i] = tlsStatus;
     263              :     }
     264            4 : }
     265              : 
     266           37 : HcclResult MyRank::RegisterCommMemsToEndpoint(EndpointHandle epHandle)
     267              : {
     268           37 :     std::vector<HcclMem> memVec;
     269           37 :     std::vector<std::string> memTag;
     270           37 :     uint64_t version = 0;
     271           37 :     CHK_RET(commMems_->GetAllMemory(memVec, memTag, version));
     272           37 :     HCCL_INFO("[%s] got %zu memory regions to register, version[%llu]", __func__, memVec.size(), version);
     273           37 :     CHK_RET(endpointMgr_->RegisterMemory(epHandle, memTag, memVec, version));
     274           36 :     return HCCL_SUCCESS;
     275           37 : }
     276              : 
     277           37 : HcclResult MyRank::PrepareMemHandles(
     278              :     EndpointHandle epHandle, void** memHandles, uint32_t memHandleNum, std::vector<MemHandle>& memHandleVec)
     279              : {
     280              :     // 从 CommMems 提取该 channel 需要的 tag 列表
     281              :     // GetTagsFromHandles 始终 push cclBuffer;用户 handles 异常时内部跳过,不阻断注册
     282           37 :     std::vector<std::string> memTags;
     283           37 :     CHK_RET(commMems_->GetTagsFromHandles(memHandles, memHandleNum, memTags));
     284              : 
     285              :     // 确保 CommMems 全量内存已注册到该 endpoint(版本一致则跳过)
     286           37 :     CHK_RET(RegisterCommMemsToEndpoint(epHandle));
     287              : 
     288              :     // 从 endpoint 查询指定 tag 的 MemHandle
     289           36 :     CHK_RET(endpointMgr_->GetMemHandlesByTags(epHandle, memTags, memHandleVec));
     290           36 :     return HCCL_SUCCESS;
     291           37 : }
     292              : 
     293            1 : HcclResult MyRank::UnregMemByTag(const std::string& tag)
     294              : {
     295            1 :     CHK_PTR_NULL(endpointMgr_);
     296            1 :     return endpointMgr_->UnregMemByTag(tag);
     297              : }
     298              : 
     299            7 : HcclResult MyRank::ReserveCcuMsCommOrFallback()
     300              : {
     301            7 :     if (opExpansionMode_ != CCU_MS_MODE) {
     302            2 :         return HCCL_SUCCESS;
     303              :     }
     304              : 
     305            5 :     bool reserved = false;
     306            5 :     CHK_RET(CollCommMgr::GetInstance().TryReserveCcuMsComm(devLogicId_, config_.GetConfigCommName(), reserved));
     307            5 :     if (reserved) {
     308            4 :         ccuMsCommReserved_ = true;
     309            4 :         return HCCL_SUCCESS;
     310              :     }
     311              : 
     312            1 :     opExpansionMode_ = CCU_SCHED_MODE;
     313            1 :     HCCL_RUN_WARNING(
     314              :         "[MyRank][%s] CCU_MS comm already exists on device[%d], fallback to CCU_SCHED, rankId[%u].", __func__,
     315              :         devLogicId_, rankId_);
     316            1 :     return HCCL_SUCCESS;
     317              : }
     318              : 
     319          293 : void MyRank::ReleaseCcuMsCommReservation()
     320              : {
     321          293 :     if (!ccuMsCommReserved_) {
     322          288 :         return;
     323              :     }
     324            5 :     CollCommMgr::GetInstance().ReleaseCcuMsComm(devLogicId_, config_.GetConfigCommName());
     325            5 :     ccuMsCommReserved_ = false;
     326              : }
     327              : 
     328            7 : void MyRank::ReconcileCcuMsCommReservation(HcclResult initRet)
     329              : {
     330            7 :     if (initRet != HCCL_SUCCESS || opExpansionMode_ != CCU_MS_MODE) {
     331            7 :         ReleaseCcuMsCommReservation();
     332              :     }
     333            7 : }
     334              : 
     335            7 : HcclResult MyRank::TryInitCcuInstanceOnDemand()
     336              : {
     337            7 :     auto ccuInsType = OpExpansionModeToCcuInstanceType(opExpansionMode_);
     338            7 :     if (ccuInsType == CcuInstanceType::CCU_UNUSED) {
     339            2 :         ccuInsHandle_ = 0;
     340            2 :         return HcclResult::HCCL_SUCCESS;
     341              :     }
     342              : 
     343            5 :     if (mainBoardType_ == Hccl::HcclMainboardId::MAINBOARD_OTHERS) {
     344            5 :         CHK_RET(CcuGetMainboardType(devLogicId_, mainBoardType_));
     345              :     }
     346              : 
     347            5 :     if (mainBoardType_ == Hccl::HcclMainboardId::MAINBOARD_PCIE_STD
     348            5 :         && ccuInsType == CcuInstanceType::CCU_MS) { // 标卡环境下配置CCU_MS拦截报错
     349            0 :         HCCL_ERROR(
     350              :             "[%s] ccuInstanceType[%d] not support in %s", __func__, ccuInsType, mainBoardType_.Describe().c_str());
     351            0 :         return HcclResult::HCCL_E_NOT_SUPPORT;
     352              :     }
     353              : 
     354              :     // 拉起ccu驱动
     355            5 :     if (!ccuDrvHandle_) {
     356            5 :         auto ccuInitRet = CcuInitFeature(devLogicId_, ccuDrvHandle_);
     357              :         // ccu驱动拉起失败,直接回退至aicpu ts
     358            5 :         if (ccuInitRet == CcuResult::CCU_E_DRV_BUSY) {
     359            2 :             opExpansionMode_ = AICPU_TS_MODE;
     360            2 :             ccuInsHandle_ = 0;
     361            2 :             HCCL_RUN_WARNING(
     362              :                 "[MyRank][%s] failed to init ccu driver, "
     363              :                 "fallback to aicpu, rankId[%u].",
     364              :                 __func__, rankId_);
     365            2 :             return HcclResult::HCCL_SUCCESS;
     366              :         }
     367              : 
     368              :         // 预期外返回值属于错误
     369            3 :         if (ccuInitRet != CcuResult::CCU_SUCCESS) {
     370            2 :             HCCL_ERROR("[%s] failed, ret[%d] is not expected.", __func__, ccuInitRet);
     371            2 :             ccuInsHandle_ = 0;
     372            2 :             return static_cast<HcclResult>(ccuInitRet);
     373              :         }
     374              :     }
     375              : 
     376              :     // ccu驱动拉起成功
     377            1 :     return HcclResult::HCCL_SUCCESS;
     378              : }
     379              : 
     380            7 : HcclResult MyRank::TryInitCcuInstance()
     381              : {
     382            7 :     CHK_RET(ReserveCcuMsCommOrFallback());
     383              : 
     384              :     // ccu instance 不在 init 时创建,由 QueryCcuIns 创建或由 Assign 显式绑定;
     385              :     // 此处仅拉起 ccu 驱动。
     386            7 :     HcclResult ret = TryInitCcuInstanceOnDemand();
     387            7 :     ReconcileCcuMsCommReservation(ret);
     388            7 :     return ret;
     389              : }
     390              : 
     391           77 : HcclResult MyRank::GetDevicePortInternal(uint32_t rank, uint32_t* devPort, EndpointLocType locType)
     392              : {
     393           77 :     CHK_PTR_NULL(devPort);
     394           77 :     CHK_PTR_NULL(rankGraph_);
     395              : 
     396              :     DevType devType;
     397           77 :     CHK_RET(hrtGetDeviceType(devType));
     398              :     // v1 模式 (mode_ == 0): 强制转换为 RankGraphV1 调用 GetDevicePort
     399              :     // v2 模式 (mode_ != 0): 使用 rankGraph_->GetDevicePort()
     400           77 :     if (devType == DevType::DEV_TYPE_910B) {
     401            0 :         RankGraphV1* rankGraphV1 = static_cast<RankGraphV1*>(rankGraph_);
     402            0 :         CHK_RET(rankGraphV1->GetDevicePort(rank, devPort));
     403              :     } else {
     404           77 :         CHK_RET(rankGraph_->GetListenPort(rank, devPort, locType));
     405              :     }
     406           77 :     return HCCL_SUCCESS;
     407              : }
     408              : 
     409          204 : HcclResult MyRank::Init(HcclMem cclBuffer, const uint32_t opExpansionMode, uint32_t rankNum)
     410              : {
     411              :     // EXCEPTION_HANDLE_BEGIN
     412          204 :     CHK_RET(hrtGetDevice(&devLogicId_));
     413              : 
     414              :     // ns recovery processor初始化
     415          204 :     EXCEPTION_CATCH(nsRecoveryProcessor_ = std::make_unique<NsRecoveryProcessor>(), return HCCL_E_PTR);
     416              : 
     417              :     // 创建通信内存管理器
     418          204 :     EXCEPTION_CATCH(commMems_ = std::make_unique<CommMems>(config_.GetConfigBufferSize()), return HCCL_E_PTR);
     419              : 
     420              :     // 初始化通信内存
     421          204 :     CHK_RET(commMems_->Init(cclBuffer));
     422              : 
     423          204 :     EXCEPTION_CATCH(engineCtxs_ = std::make_unique<EngineCtxs>(), return HCCL_E_PTR);
     424              : 
     425              :     // 通信域配置config优先级更高,当配置默认展开模式时,读取环境变量配置
     426          204 :     opExpansionMode_ = opExpansionMode;
     427          204 :     if (opExpansionMode_ == DEFAULT_MODE) {
     428              :         // 环境变量模块已处理,当用户未配置时,输出ccu sched模式
     429            1 :         auto accelerator = Hccl::EnvConfig::GetInstance().GetAlgoConfig().GetHcclAccelerator();
     430            1 :         HCCL_RUN_INFO("[MyRank][%s] set op expansion mode by env[%s].", __func__, accelerator.Describe().c_str());
     431            1 :         opExpansionMode_ = static_cast<uint32_t>(accelerator);
     432              :     }
     433              : 
     434              :     // 仅自定义算子ccu流程初始化资源
     435          204 :     if (ccuInsHandle_ == 0 && rankNum != 1 && (opExpansionMode_ == CCU_MS_MODE || opExpansionMode_ == CCU_SCHED_MODE)) {
     436            7 :         const uint32_t originOpExpansionMode = opExpansionMode_; // 记录原始加速模式,避免中间执行修改后丢失
     437            7 :         auto ret = TryInitCcuInstance();
     438            7 :         if (ret != HcclResult::HCCL_SUCCESS) { // 申请成功与回退成功都属于成功,其他均非预期
     439            1 :             HCCL_ERROR(
     440              :                 "[MyRank][%s] failed to init ccu instance, op expansion mode[%u].", __func__, originOpExpansionMode);
     441            1 :             return ret;
     442              :         }
     443              :     }
     444              : 
     445              :     // 创建端点管理器
     446          203 :     EXCEPTION_CATCH(endpointMgr_ = std::make_unique<hcomm::EndpointMgr>(), return HCCL_E_PTR);
     447              : 
     448              :     // rankPairMgr_初始化
     449          203 :     EXCEPTION_CATCH(rankPairMgr_ = std::make_unique<RankPairMgr>(rankIpPortMap_), return HCCL_E_PTR);
     450              : 
     451          203 :     DlProfFunction::GetInstance().DlProfFunctionInit();
     452              :     // EXCEPTION_HANDLE_END
     453          203 :     return HCCL_SUCCESS;
     454              : }
     455              : 
     456           23 : HcclResult MyRank::QueryListenPort(
     457              :     uint32_t localRank, uint32_t remoteRank, const EndpointDesc& localEndpointDesc,
     458              :     const EndpointDesc& remoteEndpointDesc, uint32_t& listenPort, HcommChannelDesc& hcommDesc)
     459              : {
     460              :     // 查询rmtRankId对应的devPort
     461           23 :     uint32_t rmtPort = 0;
     462           23 :     CHK_RET(GetDevicePortInternal(remoteRank, &rmtPort, remoteEndpointDesc.loc.locType));
     463           23 :     if (rmtPort > Hccl::MAX_VALUE_TCPPORT) {
     464            1 :         HCCL_ERROR(
     465              :             "[%s] Invalid port[%u] of Rank[%u], max valid port is %u", __func__, rmtPort, remoteRank,
     466              :             Hccl::MAX_VALUE_TCPPORT);
     467            1 :         return HCCL_E_PARA;
     468              :     }
     469              :     // 查询该socket链接的server端监听的端口(监听方的选择策略需要跟SocketConfig中保持一致)
     470           22 :     Hccl::IpAddress localIpAddr{};
     471           22 :     Hccl::IpAddress remoteIpAddr{};
     472           22 :     CHK_RET(CommAddrToIpAddress(localEndpointDesc.commAddr, localIpAddr));
     473           22 :     CHK_RET(CommAddrToIpAddress(remoteEndpointDesc.commAddr, remoteIpAddr));
     474           22 :     if (localIpAddr < remoteIpAddr) {
     475              :         // 查询localRankId对应的devPort
     476           20 :         CHK_RET(GetDevicePortInternal(localRank, &listenPort, localEndpointDesc.loc.locType));
     477           20 :         hcommDesc.role = HcommSocketRole::HCOMM_SOCKET_ROLE_SERVER;
     478           20 :         if (listenPort > Hccl::MAX_VALUE_TCPPORT) {
     479            0 :             HCCL_ERROR("[%s] Invalid port[%u] of Rank[%u]", __func__, listenPort, localRank);
     480            0 :             return HCCL_E_PARA;
     481              :         }
     482           20 :         hcommDesc.port = static_cast<uint16_t>(listenPort); // HcommChannelDesc.port中填监听端口号
     483              :     } else {
     484            2 :         listenPort = rmtPort;
     485            2 :         hcommDesc.role = HcommSocketRole::HCOMM_SOCKET_ROLE_CLIENT;
     486              :         hcommDesc.port
     487            2 :             = static_cast<uint16_t>(rmtPort); // HcommChannelDesc.port中填对端端口号(此场景下对端端口号也就是监听端口号)
     488              :     }
     489              : 
     490           22 :     return HCCL_SUCCESS;
     491              : }
     492              : 
     493           40 : HcclResult MyRank::GetEndpointPairFromChannel(
     494              :     const HcclChannelDesc& channelDesc, uint32_t channelIndex, uint32_t channelNum, uint32_t& remoteRank,
     495              :     hcomm::EndpointPair*& endpointPair, RankPair*& rankPair)
     496              : {
     497           40 :     remoteRank = channelDesc.remoteRank;
     498           40 :     HCCL_INFO(
     499              :         "[%s][%u/%u] remoteRank[%u] localProtocol[%d] remoteProtocol[%d]", __func__, channelIndex + 1, channelNum,
     500              :         remoteRank, channelDesc.localEndpoint.protocol, channelDesc.remoteEndpoint.protocol);
     501              : 
     502           40 :     const RankIdPair rankIdPair = std::make_pair(rankId_, remoteRank);
     503           40 :     const EndpointDescPair endpointDescPair = std::make_pair(channelDesc.localEndpoint, channelDesc.remoteEndpoint);
     504           40 :     CHK_RET(rankPairMgr_->Get(rankIdPair, rankPair));
     505           40 :     CHK_PTR_NULL(rankPair);
     506           40 :     CHK_RET(rankPair->GetEndpointPair(endpointDescPair, endpointPair));
     507           40 :     CHK_PTR_NULL(endpointPair);
     508           40 :     return HCCL_SUCCESS;
     509              : }
     510              : 
     511           40 : inline std::string AddProtocolToSocketTag(const std::string& socketTag, const HcclChannelDesc* channelDescs)
     512              : {
     513           40 :     std::string newSocketTag = socketTag + "_protocol_" + std::to_string(channelDescs->channelProtocol);
     514           40 :     return newSocketTag;
     515              : }
     516              : 
     517            8 : HcclResult MyRank::BatchServerInitForChannels(
     518              :     const HcclChannelDesc* channelDescs, uint32_t channelNum, const std::string& socketTag,
     519              :     ReuseSocketIdxMap& reuseSocketIdxMap)
     520              : {
     521              :     // 批量获取socket,与server监听隔离开
     522           28 :     for (uint32_t i = 0; i < channelNum; ++i) {
     523           20 :         hcomm::EndpointPair* endpointPair = nullptr;
     524           20 :         RankPair* rankPair = nullptr;
     525           20 :         uint32_t remoteRank = 0;
     526              : 
     527           20 :         CHK_RET(GetEndpointPairFromChannel(channelDescs[i], i, channelNum, remoteRank, endpointPair, rankPair));
     528              : 
     529           20 :         if (reuseSocketIdxMap.find(rankPair) == reuseSocketIdxMap.end()) {
     530           11 :             std::unordered_map<hcomm::EndpointPair*, u32> endpointPair2Idx{};
     531           11 :             endpointPair2Idx.emplace(endpointPair, 0);
     532           11 :             reuseSocketIdxMap.emplace(rankPair, endpointPair2Idx);
     533           20 :         } else if (reuseSocketIdxMap[rankPair].find(endpointPair) == reuseSocketIdxMap[rankPair].end()) {
     534            3 :             reuseSocketIdxMap[rankPair].emplace(endpointPair, 0);
     535              :         }
     536           20 :         u32& reuseIdx = reuseSocketIdxMap[rankPair][endpointPair];
     537              : 
     538              :         uint32_t devicePhyId;
     539              :         uint32_t remoteDevicePhyId;
     540           20 :         rankGraph_->GetDeviceId(rankId_, &devicePhyId);
     541           20 :         rankGraph_->GetDeviceId(remoteRank, &remoteDevicePhyId);
     542              : 
     543           20 :         const std::string socketTagAddProto = AddProtocolToSocketTag(socketTag, &channelDescs[i]);
     544           20 :         auto ret = endpointPair->ServerInit(
     545              :             rankId_, remoteRank, socketTagAddProto, reuseIdx, devicePhyId, remoteDevicePhyId);
     546           20 :         CHK_PRT_RET(
     547              :             ret != HCCL_SUCCESS,
     548              :             HCCL_ERROR(
     549              :                 "[%s] ServerInitFailed, channelIndex[%u], remoteRank[%u], protocol[%d] reuseIdx[%u]", __func__, i,
     550              :                 remoteRank, channelDescs[i].localEndpoint.protocol, reuseIdx),
     551              :             ret);
     552              : 
     553           20 :         HCCL_INFO(
     554              :             "[%s][%u/%u] server listen successfully, remoteRank[%u], reuseIdx[%u]", __func__, i + 1, channelNum,
     555              :             remoteRank, reuseIdx);
     556           20 :     }
     557            8 :     return HCCL_SUCCESS;
     558              : }
     559              : 
     560            8 : HcclResult MyRank::BatchGetSocketsForChannels(
     561              :     const HcclChannelDesc* channelDescs, uint32_t channelNum, const std::string& socketTag,
     562              :     std::vector<HcommChannelDesc>& hcommDescs, ReuseSocketIdxMap& reuseSocketIdxMap)
     563              : {
     564           28 :     for (uint32_t i = 0; i < channelNum; ++i) {
     565           20 :         hcomm::EndpointPair* endpointPair = nullptr;
     566           20 :         RankPair* rankPair = nullptr;
     567           20 :         uint32_t remoteRank = 0;
     568              : 
     569           20 :         CHK_RET(GetEndpointPairFromChannel(channelDescs[i], i, channelNum, remoteRank, endpointPair, rankPair));
     570              : 
     571           20 :         uint32_t listenPort = 0;
     572           20 :         CHK_RET(QueryListenPort(
     573              :             rankId_, remoteRank, channelDescs[i].localEndpoint, channelDescs[i].remoteEndpoint, listenPort,
     574              :             hcommDescs[i]));
     575              : 
     576           20 :         u32& reuseIdx = reuseSocketIdxMap[rankPair][endpointPair];
     577              :         uint32_t devicePhyId;
     578              :         uint32_t remoteDevicePhyId;
     579           20 :         rankGraph_->GetDeviceId(rankId_, &devicePhyId);
     580           20 :         rankGraph_->GetDeviceId(remoteRank, &remoteDevicePhyId);
     581           20 :         HCCL_INFO(
     582              :             "[MyRank][BatchCreateSockets] rankId_[%u] devicePhyId[%u] remoteRank[%u] remoteDevicePhyId[%u]", rankId_,
     583              :             devicePhyId, remoteRank, remoteDevicePhyId);
     584           20 :         Hccl::Socket* socket = nullptr;
     585           20 :         const std::string socketTagAddProto = AddProtocolToSocketTag(socketTag, &channelDescs[i]);
     586           20 :         auto ret = endpointPair->GetConnectedSocket(
     587              :             rankId_, remoteRank, socketTagAddProto, reuseIdx, listenPort, socket, devicePhyId, remoteDevicePhyId);
     588           20 :         CHK_PRT_RET(
     589              :             ret != HCCL_SUCCESS,
     590              :             HCCL_ERROR(
     591              :                 "[%s] failed to get socket, channelIndex[%u], remoteRank[%u], protocol[%d], reuseIdx[%u], tag[%s]",
     592              :                 __func__, i, remoteRank, channelDescs[i].localEndpoint.protocol, reuseIdx, socketTagAddProto.c_str()),
     593              :             ret);
     594           20 :         CHK_PTR_NULL(socket);
     595              : 
     596           20 :         hcommDescs[i].socket = reinterpret_cast<HcommSocket>(socket);
     597              : 
     598           20 :         HCCL_INFO(
     599              :             "[%s][%u/%u] socket created successfully, remoteRank[%u], socket[%p] reuseIdx[%u]", __func__, i + 1,
     600              :             channelNum, remoteRank, socket, reuseIdx);
     601           20 :         reuseIdx++;
     602           20 :     }
     603            8 :     return HCCL_SUCCESS;
     604              : }
     605              : 
     606            8 : HcclResult MyRank::BatchCreateSockets(
     607              :     const HcclChannelDesc* channelDescs, uint32_t channelNum, const std::string& socketTag,
     608              :     std::vector<HcommChannelDesc>& hcommDescs)
     609              : {
     610            8 :     CHK_PTR_NULL(channelDescs);
     611            8 :     CHK_PRT_RET(channelNum == 0, HCCL_ERROR("[%s] invalid param: channelNum is zero", __func__), HCCL_E_PARA);
     612              : 
     613            8 :     ReuseSocketIdxMap reuseSocketIdxMap{};
     614              :     // socket服务器首先监听
     615            8 :     CHK_RET(BatchServerInitForChannels(channelDescs, channelNum, socketTag, reuseSocketIdxMap));
     616              :     // socket添加白名单以及进行连接,获取最后的socket
     617            8 :     CHK_RET(BatchGetSocketsForChannels(channelDescs, channelNum, socketTag, hcommDescs, reuseSocketIdxMap));
     618            8 :     return HCCL_SUCCESS;
     619            8 : }
     620              : 
     621            1 : HcclResult MyRank::BatchExchangeAndCheckConsistency(
     622              :     const HcclChannelDesc* channelDescs, const std::vector<HcommChannelDesc>& hcommDescs, uint32_t channelNum,
     623              :     const std::vector<std::pair<u32, u32>>& newChannels, CommEngine engine)
     624              : {
     625            1 :     CHK_PTR_NULL(channelDescs);
     626            1 :     CHK_PRT_RET(channelNum == 0, HCCL_ERROR("[%s] invalid param: channelNum is zero", __func__), HCCL_E_PARA);
     627              : 
     628              :     // 与非共享路径 MyRank::CreateChannels 一致:仅 DEV_TYPE_950 需要执行通信域一致性校验交换。
     629              :     DevType devType;
     630            1 :     CHK_RET(hrtGetDeviceType(devType));
     631            1 :     if (devType != DevType::DEV_TYPE_950) {
     632            0 :         return HCCL_SUCCESS;
     633              :     }
     634              : 
     635            1 :     auto startConsistency = std::chrono::steady_clock::now();
     636            1 :     CHK_RET(exchangeInfoMgr_.BatchExchangeAndCheckConsistency(
     637              :         channelDescs, hcommDescs, channelNum, newChannels, collCommConfigConsistency_, engine));
     638            0 :     auto endConsistency = std::chrono::steady_clock::now();
     639              :     auto durationConsistency
     640            0 :         = std::chrono::duration_cast<std::chrono::microseconds>(endConsistency - startConsistency).count();
     641            0 :     HCCL_INFO(
     642              :         "[MyRank][%s] BatchExchangeAndCheckConsistency Time Elapsed [%lld]us, channelNum [%u]", __func__,
     643              :         durationConsistency, channelNum);
     644            0 :     return HCCL_SUCCESS;
     645              : }
     646              : 
     647              : constexpr uint32_t MEM_HANDLE_NUM_MAX = 256; // memHandleNum的默认限制最大为256
     648              : constexpr uint32_t NOTIFY_NUM_MAX = 64;      // notifynum 的默认限制最大为64
     649              : 
     650            3 : HcclResult MyRank::CheckChannelParam(CommEngine engine, const HcclChannelDesc* channelDesc, uint32_t channelNum) const
     651              : {
     652            6 :     for (u32 index = 0; index < channelNum; ++index) {
     653            4 :         if (engine == COMM_ENGINE_AIV) {
     654            0 :             CHK_PRT_RET(
     655              :                 (channelDesc->memHandleNum > MEM_HANDLE_NUM_MAX),
     656              :                 HCCL_ERROR(
     657              :                     "[%s]Channeldesc[%u] invalid memHandleNum, memHandleNum[%u], max channel num[%u]", __func__, index,
     658              :                     channelDesc->memHandleNum, MEM_HANDLE_NUM_MAX),
     659              :                 HCCL_E_PARA);
     660            0 :             CHK_PRT_RET(
     661              :                 (channelDesc->memHandleNum != 0 && channelDesc->memHandles == nullptr),
     662              :                 HCCL_ERROR("[%s]Channeldesc[%u] invalid memHandles, memHandles is null", __func__, index), HCCL_E_PARA);
     663              :         } else {
     664            4 :             if (channelDesc->memHandleNum != 0) {
     665            2 :                 HCCL_WARNING(
     666              :                     "[%s]Channeldesc[%u] memHandleNum[%u] is non-zero, memHandle exchange is not supported.", __func__,
     667              :                     index, channelDesc->memHandleNum);
     668              :             }
     669              :         }
     670            4 :         CHK_PRT_RET(
     671              :             channelDesc->notifyNum > NOTIFY_NUM_MAX,
     672              :             HCCL_ERROR(
     673              :                 "[%s]Channeldesc[%u] invalid notifyNum [%u], max notify num[%u]", __func__, index,
     674              :                 channelDesc->notifyNum, NOTIFY_NUM_MAX),
     675              :             HCCL_E_PARA);
     676              :     }
     677              : 
     678            2 :     return HCCL_SUCCESS;
     679              : }
     680              : 
     681              : // 批量创建channels,如果CCU资源不足(如Xn, Cke, channel ctx, jetty ctx, wqebb)会失败,返回HCCL_E_UNAVAIL
     682           13 : HcclResult MyRank::BatchCreateChannels(
     683              :     CommEngine engine, const HcclChannelDesc* channelDescs, uint32_t channelNum,
     684              :     std::vector<HcommChannelDesc>& hcommDescs, ChannelHandle* channelHandles,
     685              :     std::vector<std::vector<MemHandle>>& allHandles)
     686              : {
     687           13 :     CHK_PTR_NULL(channelDescs);
     688           13 :     CHK_PTR_NULL(channelHandles);
     689           13 :     CHK_PRT_RET(channelNum == 0, HCCL_ERROR("[%s] invalid param: channelNum is zero", __func__), HCCL_E_PARA);
     690              : 
     691              :     // 持锁保护 newChannels_/handleToEpPair_;失败路径调用的 DestroyNewChannels 由本函数持锁,内部不再加锁
     692           13 :     std::lock_guard<std::mutex> lock(channelIndexMtx_);
     693              : 
     694           13 :     uint32_t localRank = rankId_;
     695           13 :     CHK_SMART_PTR_NULL(commMems_);
     696           13 :     CHK_PTR_NULL(endpointMgr_);
     697              :     std::unordered_map<RankPair*, std::unordered_map<CommEngine, std::unordered_map<hcomm::EndpointPair*, u32>>>
     698           13 :         reuseChannelIdxMap{};
     699              : 
     700              :     // 记录本轮新申请的channel
     701           13 :     newChannels_.clear();
     702           13 :     bool isAllSuccess = true;
     703              : 
     704           45 :     for (uint32_t i = 0; i < channelNum; ++i) {
     705           34 :         const EndpointDesc& localEndpointDesc = channelDescs[i].localEndpoint;
     706           34 :         const EndpointDesc& remoteEndpointDesc = channelDescs[i].remoteEndpoint;
     707           34 :         uint32_t remoteRank = channelDescs[i].remoteRank;
     708              : 
     709           34 :         HCCL_INFO(
     710              :             "[%s][%u/%u] remoteRank[%u] localProtocol[%d] remoteProtocol[%d] engine[%s]", __func__, i + 1, channelNum,
     711              :             remoteRank, localEndpointDesc.protocol, remoteEndpointDesc.protocol,
     712              :             GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str());
     713              : 
     714           34 :         EndpointHandle epHandle = nullptr;
     715           34 :         auto ret = endpointMgr_->Get(localEndpointDesc, epHandle);
     716           34 :         CHK_PRT_RET(
     717              :             ret != HCCL_SUCCESS,
     718              :             HCCL_ERROR(
     719              :                 "[%s] failed to get endpoint, channelIndex[%u], remoteRank[%u], protocol[%d]", __func__, i, remoteRank,
     720              :                 localEndpointDesc.protocol),
     721              :             ret);
     722           34 :         CHK_PTR_NULL(epHandle);
     723              : 
     724              :         // 启动监听
     725           34 :         uint32_t listenPort = 0;
     726           34 :         CHK_RET(GetDevicePortInternal(localRank, &listenPort, localEndpointDesc.loc.locType));
     727           34 :         if (listenPort == Hccl::DEFAULT_VALUE_TCPPORT) {
     728            2 :             auto portRanges = Hccl::EnvConfig::GetInstance().GetHostNicConfig().GetDeviceSocketPortRange();
     729            2 :             if (!portRanges.empty()) {
     730            1 :                 listenPort = portRanges[0].min;
     731            1 :                 HCCL_INFO(
     732              :                     "[%s] listenPort is default[%u], use port[%u] from HCCL_NPU_SOCKET_PORT_RANGE", __func__,
     733              :                     Hccl::DEFAULT_VALUE_TCPPORT, listenPort);
     734              :             }
     735            2 :         }
     736           34 :         CHK_RET(static_cast<HcclResult>(HcommEndpointStartListen(epHandle, listenPort, nullptr)));
     737              : 
     738           34 :         HCCL_INFO(
     739              :             "[%s][%u/%u] remoteRank[%u] epHandle[%p] protocol[%d]", __func__, i + 1, channelNum, remoteRank, epHandle,
     740              :             localEndpointDesc.protocol);
     741              : 
     742              :         // 注册内存
     743           34 :         CHK_RET(PrepareMemHandles(epHandle, channelDescs[i].memHandles, channelDescs[i].memHandleNum, allHandles[i]));
     744           34 :         HCCL_INFO(
     745              :             "[%s][%u/%u] remoteRank[%u] got %zu user memory handles", __func__, i + 1, channelNum, remoteRank,
     746              :             allHandles[i].size());
     747              : 
     748           34 :         hcommDescs[i].exchangeAllMems = false;
     749           34 :         hcommDescs[i].memHandles = allHandles[i].data();
     750           34 :         hcommDescs[i].memHandleNum = allHandles[i].size();
     751              : 
     752           34 :         hcomm::EndpointPair* endpointPair = nullptr;
     753           34 :         RankIdPair rankIdPair = std::make_pair(localRank, remoteRank);
     754           34 :         EndpointDescPair endpointDescPair = std::make_pair(localEndpointDesc, remoteEndpointDesc);
     755           34 :         RankPair* rankPair = nullptr;
     756           34 :         CHK_RET(rankPairMgr_->Get(rankIdPair, rankPair));
     757           34 :         CHK_PTR_NULL(rankPair);
     758           34 :         CHK_RET(rankPair->GetEndpointPair(endpointDescPair, endpointPair));
     759           34 :         CHK_PTR_NULL(endpointPair);
     760              : 
     761           34 :         if (reuseChannelIdxMap.find(rankPair) == reuseChannelIdxMap.end()) {
     762           19 :             std::unordered_map<CommEngine, std::unordered_map<hcomm::EndpointPair*, u32>> engine2EndpointPairMap{};
     763           19 :             std::unordered_map<hcomm::EndpointPair*, u32> endpointPair2Idx{};
     764           19 :             endpointPair2Idx.emplace(endpointPair, 0);
     765           19 :             engine2EndpointPairMap.emplace(engine, endpointPair2Idx);
     766           19 :             reuseChannelIdxMap.emplace(rankPair, engine2EndpointPairMap);
     767           34 :         } else if (reuseChannelIdxMap[rankPair].find(engine) == reuseChannelIdxMap[rankPair].end()) {
     768            0 :             std::unordered_map<hcomm::EndpointPair*, u32> endpointPair2Idx{};
     769            0 :             endpointPair2Idx.emplace(endpointPair, 0);
     770            0 :             reuseChannelIdxMap[rankPair].emplace(engine, endpointPair2Idx);
     771            0 :         } else if (
     772           15 :             reuseChannelIdxMap[rankPair][engine].find(endpointPair) == reuseChannelIdxMap[rankPair][engine].end()) {
     773            3 :             reuseChannelIdxMap[rankPair][engine].emplace(endpointPair, 0);
     774              :         }
     775              : 
     776           34 :         u32& reuseIdx = reuseChannelIdxMap[rankPair][engine][endpointPair];
     777           34 :         u32 idx = reuseIdx;
     778              :         /* hostNIC -- DeviceNic(transport不复用link/Channel),此流程也是新创建channel,需要计入isNewChannel */
     779           34 :         if (localEndpointDesc.loc.locType != remoteEndpointDesc.loc.locType) {
     780            0 :             idx = UNREUSE_CHANNEL_IDX;
     781              :         }
     782           34 :         bool isNewChannel = (endpointPair->IsChannelNotExist(engine, reuseIdx) || (idx == UNREUSE_CHANNEL_IDX));
     783              : 
     784              :         // CreateChannel 返回 HCCL_E_UNAVAIL 表示资源不足创建失败
     785           34 :         ret = endpointPair->CreateChannel(epHandle, engine, idx, &hcommDescs[i], channelHandles + i);
     786           34 :         if (ret == HCCL_E_TIMEOUT || ret == HCCL_E_INTERNAL) {
     787            0 :             Hccl::TlsStatus tlsStatus = Hccl::TlsStatus::UNKNOWN;
     788            0 :             CHK_PRT_CONT(
     789              :                 GetLocalTlsStatus(localEndpointDesc.loc.locType, tlsStatus) != HCCL_SUCCESS,
     790              :                 HCCL_WARNING("[GetLocalTlsStatus] Can not get TlsStatus"));
     791            0 :             HCCL_ERROR(
     792              :                 "[%s] failed to create channel, channelIndex[%u], localRank[%u], remoteRank[%u], protocol[%s], "
     793              :                 "tlsType[%s], tlsStatus[%s], ret[%d]",
     794              :                 __func__, i, localRank, remoteRank,
     795              :                 MyRankUtils::GetCommProtocolEnumStr(localEndpointDesc.protocol).c_str(),
     796              :                 MyRankUtils::GetTlsTypeStr(localEndpointDesc.loc.locType), MyRankUtils::GetTlsStatusStr(tlsStatus),
     797              :                 ret);
     798              :         }
     799           34 :         if (ret == HCCL_E_UNAVAIL) {
     800              :             // 申请channel因资源不足失败,清理已申请的channel
     801            2 :             HCCL_RUN_WARNING(
     802              :                 "[%s] create channel failed, channelIndex[%u], remoteRank[%u], engine[%s], reuseIdx[%u], need clean "
     803              :                 "new channels",
     804              :                 __func__, i + 1, remoteRank, GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), reuseIdx);
     805            2 :             isAllSuccess = false;
     806            2 :             break;
     807              :         }
     808              :         // 记录新申请的channel信息,用于清理临时资源
     809           32 :         if (isNewChannel) {
     810           22 :             newChannels_.emplace_back(std::make_pair(i, reuseIdx));
     811              :         }
     812              : 
     813           32 :         if (ret != HCCL_SUCCESS) {
     814            0 :             if (ret != HCCL_E_TIMEOUT && ret != HCCL_E_INTERNAL) {
     815            0 :                 HCCL_ERROR(
     816              :                     "[%s] failed to create channel, channelIndex[%u], remoteRank[%u], engine[%s], reuseIndex[%u]",
     817              :                     __func__, i + 1, remoteRank, GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(),
     818              :                     reuseIdx);
     819              :             }
     820            0 :             return ret;
     821              :         }
     822           32 :         if (idx != UNREUSE_CHANNEL_IDX) {
     823           32 :             reuseIdx++;
     824              :         }
     825              : 
     826              :         // 登记 handle -> EndpointPair 反查索引;真实槽位由 EndpointPair::handleToLoc_ 维护
     827           32 :         handleToEpPair_[channelHandles[i]] = endpointPair;
     828              : 
     829           32 :         HCCL_INFO(
     830              :             "[%s][%u/%u] channel created successfully, remoteRank[%u], channelHandle[%p]", __func__, i + 1, channelNum,
     831              :             remoteRank, channelHandles[i]);
     832              :     }
     833              : 
     834              :     // 如果申请失败,清理endpoint pair中记录的channel handle
     835           13 :     if (!isAllSuccess) {
     836            2 :         HCCL_RUN_WARNING(
     837              :             "[%s] create channel failed, destroy new channels num[%zu], engine[%s]", __func__, newChannels_.size(),
     838              :             GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str());
     839            2 :         CHK_RET(DestroyNewChannels(engine, channelDescs, newChannels_));
     840            2 :         return HCCL_E_UNAVAIL;
     841              :     }
     842              : 
     843           11 :     return HCCL_SUCCESS;
     844           13 : }
     845              : 
     846            3 : HcclResult MyRank::DestroyNewChannels(
     847              :     CommEngine engine, const HcclChannelDesc* channelDescs, const std::vector<std::pair<u32, u32>>& newChannels)
     848              : {
     849            3 :     HcclResult firstErr = HCCL_SUCCESS;
     850            3 :     uint32_t localRank = rankId_;
     851           12 :     for (auto idxPairIter = std::rbegin(newChannels); idxPairIter != std::rend(newChannels);
     852            6 :          ++idxPairIter) { // 由于新申请的在申请过的后面,所以要从后往前找reuseIdx销毁
     853            6 :         auto idxPair = *idxPairIter;
     854            6 :         const EndpointDesc& localEndpointDesc = channelDescs[idxPair.first].localEndpoint;
     855            6 :         const EndpointDesc& remoteEndpointDesc = channelDescs[idxPair.first].remoteEndpoint;
     856            6 :         uint32_t remoteRank = channelDescs[idxPair.first].remoteRank;
     857            6 :         hcomm::EndpointPair* endpointPair = nullptr;
     858            6 :         RankIdPair rankIdPair = std::make_pair(localRank, remoteRank);
     859            6 :         EndpointDescPair endpointDescPair = std::make_pair(localEndpointDesc, remoteEndpointDesc);
     860            6 :         RankPair* rankPair = nullptr;
     861            6 :         CHK_RET(rankPairMgr_->Get(rankIdPair, rankPair));
     862            6 :         CHK_PTR_NULL(rankPair);
     863            6 :         CHK_RET(rankPair->GetEndpointPair(endpointDescPair, endpointPair));
     864            6 :         CHK_PTR_NULL(endpointPair);
     865              :         // DestroyChannel 会 erase 向量导致下标变化, 需先取出 handle
     866            6 :         ChannelHandle handleToErase = 0;
     867            6 :         endpointPair->GetChannelHandle(engine, idxPair.second, handleToErase);
     868              :         // 单个 channel 销毁失败不中断其余清理;记录首个错误,最终统一清空本次新建列表
     869            6 :         HcclResult destroyRet = endpointPair->DestroyChannel(engine, idxPair.second);
     870            6 :         if (destroyRet != HCCL_SUCCESS) {
     871            0 :             HCCL_ERROR(
     872              :                 "[%s] DestroyChannel failed, engine[%s] reuseIdx[%u] ret[%d], continue.", __func__,
     873              :                 GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), idxPair.second, destroyRet);
     874            0 :             if (firstErr == HCCL_SUCCESS) {
     875            0 :                 firstErr = destroyRet;
     876              :             }
     877              :         }
     878            6 :         if (handleToErase != 0) {
     879            2 :             handleToEpPair_.erase(handleToErase);
     880              :         }
     881              :     }
     882            3 :     newChannels_.clear();
     883            3 :     return firstErr;
     884              : }
     885              : 
     886              : HcclResult
     887           15 : MyRank::QueryOneChannel(CommEngine engine, const HcclChannelDesc& channelDesc, u32 reuseIdx, ChannelHandle& handle)
     888              : {
     889           15 :     handle = 0;
     890           15 :     const RankIdPair rankIdPair = std::make_pair(rankId_, channelDesc.remoteRank);
     891           15 :     const EndpointDescPair endpointDescPair = std::make_pair(channelDesc.localEndpoint, channelDesc.remoteEndpoint);
     892              : 
     893           15 :     RankPair* rankPair = nullptr;
     894           15 :     if (rankPairMgr_->Find(rankIdPair, rankPair) != HCCL_SUCCESS || rankPair == nullptr) {
     895            3 :         return HCCL_SUCCESS;
     896              :     }
     897           12 :     hcomm::EndpointPair* epPair = nullptr;
     898           12 :     if (rankPair->GetEndpointPair(endpointDescPair, epPair) != HCCL_SUCCESS || epPair == nullptr) {
     899            0 :         return HCCL_SUCCESS;
     900              :     }
     901           12 :     ChannelHandle slotHandle = 0;
     902           12 :     if (epPair->GetChannelHandle(engine, reuseIdx, slotHandle)) {
     903            6 :         handle = slotHandle;
     904              :     }
     905           12 :     return HCCL_SUCCESS;
     906              : }
     907              : 
     908           13 : HcclResult MyRank::QueryChannels(
     909              :     CommEngine engine, const HcclChannelDesc* channelDescs, uint32_t channelNum, ChannelHandle* channels)
     910              : {
     911           13 :     CHK_PTR_NULL(channelDescs);
     912           12 :     CHK_PTR_NULL(channels);
     913           11 :     CHK_PRT_RET(channelNum == 0, HCCL_ERROR("[%s] invalid param: channelNum is zero", __func__), HCCL_E_PARA);
     914              : 
     915           10 :     HCCL_INFO(
     916              :         "[MyRank][%s] Enter engine[%s] channelNum[%u] rankId[%u]", __func__,
     917              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), channelNum, rankId_);
     918              : 
     919              :     // 与 BatchCreateChannels 保持一致的 reuseIdx 累计逻辑
     920              :     std::unordered_map<RankIdPair, std::unordered_map<EndpointDescPair, std::unordered_map<CommEngine, u32>>>
     921           10 :         reuseIdxMap{};
     922              : 
     923           26 :     for (uint32_t i = 0; i < channelNum; ++i) {
     924           16 :         channels[i] = 0;
     925           16 :         const auto& channelDesc = channelDescs[i];
     926           16 :         uint32_t remoteRank = channelDesc.remoteRank;
     927           16 :         const RankIdPair rankIdPair = std::make_pair(rankId_, remoteRank);
     928           16 :         const EndpointDescPair endpointDescPair = std::make_pair(channelDesc.localEndpoint, channelDesc.remoteEndpoint);
     929              : 
     930           16 :         u32& reuseIdx = reuseIdxMap[rankIdPair][endpointDescPair][engine];
     931           16 :         u32 idx = reuseIdx;
     932           16 :         if (channelDesc.localEndpoint.loc.locType != channelDesc.remoteEndpoint.loc.locType) {
     933            1 :             idx = UNREUSE_CHANNEL_IDX;
     934              :         }
     935              : 
     936              :         // 仅当非 UNREUSE 且槽位存在时返回 handle
     937           16 :         if (idx != UNREUSE_CHANNEL_IDX) {
     938           15 :             (void)QueryOneChannel(engine, channelDesc, reuseIdx, channels[i]);
     939              :         }
     940              : 
     941           16 :         HCCL_INFO(
     942              :             "[MyRank][%s] [%u/%u] remoteRank[%u] exist[%s] handle[0x%llx] reuseIdx[%u] unreuse[%d]", __func__, i + 1,
     943              :             channelNum, remoteRank, channels[i] != 0 ? "yes" : "no", channels[i], reuseIdx, idx == UNREUSE_CHANNEL_IDX);
     944              : 
     945              :         // 与 BatchCreateChannels 一致: 非 UNREUSE 才递增 reuseIdx(引用, 直接改 map 内值)
     946           16 :         if (idx != UNREUSE_CHANNEL_IDX) {
     947           15 :             reuseIdx++;
     948              :         }
     949              :     }
     950              : 
     951              :     // 对发生句柄转换的引擎,经平台 H2D 反向映射把 host 句柄转换为用户实际使用的句柄
     952              :     // (device 句柄),保证 Query 返回值与 HcclChannelAcquire 出参一致
     953           10 :     if (engine == COMM_ENGINE_AICPU || engine == COMM_ENGINE_AICPU_TS || engine == COMM_ENGINE_AIV) {
     954            0 :         for (uint32_t i = 0; i < channelNum; ++i) {
     955            0 :             if (channels[i] != 0) {
     956            0 :                 ChannelHandle deviceHandle = 0;
     957            0 :                 if (hcomm::ChannelProcess::ResolveHostHandleToDevice(channels[i], deviceHandle) == HCCL_SUCCESS
     958            0 :                     && deviceHandle != 0) {
     959            0 :                     channels[i] = deviceHandle;
     960              :                 }
     961              :             }
     962              :         }
     963              :     }
     964           10 :     return HCCL_SUCCESS;
     965           10 : }
     966              : 
     967              : // 记录批量销毁过程中的首个错误与对应计数,供 DestroyOneChannel 复用
     968           23 : static void RecordDestroyError(HcclResult& firstErr, u32& errCnt, HcclResult err)
     969              : {
     970           23 :     errCnt++;
     971           23 :     if (firstErr == HCCL_SUCCESS) {
     972           21 :         firstErr = err;
     973              :     }
     974           23 : }
     975              : 
     976           43 : HcclResult MyRank::DestroyOneChannel(
     977              :     ChannelHandle userHandle, u32 index, HcclResult& firstErr, u32& invalidHandleCnt, u32& failedCnt)
     978              : {
     979              :     // 反查索引以 host 句柄为键:AIV/AICPU_TS 入参为 device 句柄,先经 D2H 映射解析为 host 句柄
     980           43 :     ChannelHandle hostHandle = userHandle;
     981           43 :     ChannelHandle resolved = 0;
     982           43 :     if (hcomm::ChannelProcess::ResolveUserHandleToHost(userHandle, resolved) == HCCL_SUCCESS && resolved != 0) {
     983            0 :         hostHandle = resolved;
     984              :     }
     985           43 :     auto it = handleToEpPair_.find(hostHandle);
     986           43 :     if (it == handleToEpPair_.end()) {
     987           12 :         HCCL_ERROR("[%s] channel handle[0x%llx] not found, channelIndex[%u].", __func__, userHandle, index);
     988           12 :         RecordDestroyError(firstErr, invalidHandleCnt, HCCL_E_NOT_FOUND);
     989           12 :         return HCCL_SUCCESS;
     990              :     }
     991           31 :     hcomm::EndpointPair* epPair = it->second;
     992           31 :     if (epPair == nullptr) {
     993              :         // 反查索引条目为空指针(异常数据),清理并按无效句柄容错
     994            1 :         HCCL_ERROR("[%s] channel handle[0x%llx] endpoint pair is null, channelIndex[%u].", __func__, userHandle, index);
     995            1 :         handleToEpPair_.erase(it);
     996            1 :         RecordDestroyError(firstErr, invalidHandleCnt, HCCL_E_NOT_FOUND);
     997            1 :         return HCCL_SUCCESS;
     998              :     }
     999           30 :     CommEngine engine = COMM_ENGINE_RESERVED;
    1000           30 :     u32 reuseIdx = 0;
    1001           30 :     if (!epPair->FindChannelLoc(hostHandle, engine, reuseIdx)) {
    1002            1 :         HCCL_ERROR("[%s] channel handle[0x%llx] FindChannelLoc failed, channelIndex[%u].", __func__, userHandle, index);
    1003            1 :         RecordDestroyError(firstErr, invalidHandleCnt, HCCL_E_NOT_FOUND);
    1004            1 :         return HCCL_SUCCESS;
    1005              :     }
    1006              :     // 暂只支持 CCU 引擎: 其他场景的 channel 销毁无法保证资源完整释放
    1007           29 :     if (engine != COMM_ENGINE_CCU) {
    1008            7 :         HCCL_WARNING(
    1009              :             "[%s] channel handle[0x%llx] engine[%s] not supported, only CCU engine supported, channelIndex[%u].",
    1010              :             __func__, userHandle, GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), index);
    1011            7 :         RecordDestroyError(firstErr, failedCnt, HCCL_E_NOT_SUPPORT);
    1012            7 :         return HCCL_SUCCESS;
    1013              :     }
    1014           22 :     HcclResult destroyRet = epPair->DestroyChannel(engine, reuseIdx);
    1015           22 :     if (destroyRet != HCCL_SUCCESS) {
    1016            2 :         HCCL_ERROR("[%s] DestroyChannel failed, handle[0x%llx] ret[%d], continue.", __func__, hostHandle, destroyRet);
    1017            2 :         RecordDestroyError(firstErr, failedCnt, destroyRet);
    1018            2 :         return HCCL_SUCCESS;
    1019              :     }
    1020           20 :     handleToEpPair_.erase(it);
    1021           20 :     return HCCL_SUCCESS;
    1022              : }
    1023              : 
    1024           36 : HcclResult MyRank::DestroyChannels(const ChannelHandle* channels, uint32_t channelNum)
    1025              : {
    1026           36 :     CHK_PTR_NULL(channels);
    1027           35 :     CHK_PRT_RET(channelNum == 0, HCCL_ERROR("[%s] invalid param: channelNum is zero", __func__), HCCL_E_PARA);
    1028              : 
    1029           34 :     std::lock_guard<std::mutex> lock(channelIndexMtx_);
    1030              : 
    1031           34 :     HCCL_INFO("[MyRank][%s] Enter channelNum[%u] rankId[%u]", __func__, channelNum, rankId_);
    1032              : 
    1033           34 :     HcclResult firstErr = HCCL_SUCCESS;
    1034           34 :     u32 invalidHandleCnt = 0;
    1035           34 :     u32 failedCnt = 0;
    1036              : 
    1037           77 :     for (uint32_t i = 0; i < channelNum; ++i) {
    1038           43 :         (void)DestroyOneChannel(channels[i], i, firstErr, invalidHandleCnt, failedCnt);
    1039              :     }
    1040              : 
    1041           34 :     if (firstErr != HCCL_SUCCESS) {
    1042           21 :         u32 destroyedCnt = channelNum - invalidHandleCnt - failedCnt;
    1043           21 :         HCCL_ERROR(
    1044              :             "[%s] finished with errors, total[%u] destroyed[%u] failed[%u] invalidHandle[%u] firstErr[%d].", __func__,
    1045              :             channelNum, destroyedCnt, failedCnt, invalidHandleCnt, static_cast<s32>(firstErr));
    1046           21 :         return firstErr;
    1047              :     }
    1048           13 :     return HCCL_SUCCESS;
    1049           34 : }
    1050              : 
    1051              : HcclResult
    1052            2 : MyRank::BatchConnectChannels(const HcclChannelDesc* channelDescs, ChannelHandle* channelHandles, uint32_t channelNum)
    1053              : {
    1054            2 :     auto timeout = std::chrono::seconds(Hccl::EnvConfig::GetInstance().GetSocketConfig().GetLinkTimeOut());
    1055            2 :     auto startTime = std::chrono::steady_clock::now();
    1056              : 
    1057            2 :     HCCL_INFO(
    1058              :         "[%s] start connecting channels, channelNum[%u], timeout[%lld]sec", __func__, channelNum, timeout.count());
    1059              : 
    1060            2 :     std::vector<int32_t> statusVec(channelNum, 0);
    1061            2 :     int32_t* statusList = statusVec.data();
    1062            2 :     uint32_t retryCount = 0;
    1063              :     while (true) {
    1064      1461862 :         HcclResult ret = hcomm::ChannelProcess::ChannelGetStatus(channelHandles, channelNum, statusList);
    1065              : 
    1066              :         // 卫语句:先处理异常情况
    1067              : 
    1068              :         // 1. 检查超时
    1069      1461862 :         if ((std::chrono::steady_clock::now() - startTime) >= timeout) {
    1070              :             auto elapsed
    1071            2 :                 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startTime)
    1072            2 :                       .count();
    1073            2 :             HCCL_ERROR(
    1074              :                 "[%s] channel connect timeout after %lld sec, channelNum[%u], elapsed[%lld]ms, retryCount[%u]",
    1075              :                 __func__, timeout.count(), channelNum, elapsed, retryCount);
    1076           14 :             RPT_INPUT_ERR(
    1077              :                 true, "EI0006", std::vector<std::string>({"reason"}),
    1078              :                 std::vector<std::string>({GET_SOCKET_TIMEOUT_REASON_CLOSE_DETECT}));
    1079            2 :             std::vector<Hccl::TlsStatus> tlsStatusList(channelNum, Hccl::TlsStatus::UNKNOWN);
    1080            2 :             GetAbnormalChannelTlsStatus(channelDescs, statusList, channelNum, tlsStatusList);
    1081            2 :             logger::ChannelLogger::PrintChannelErrorDetails(
    1082              :                 rankId_, channelNum, channelDescs, channelHandles, statusList, static_cast<uint64_t>(elapsed),
    1083            2 :                 tlsStatusList.data());
    1084            2 :             return HCCL_E_TIMEOUT;
    1085            2 :         }
    1086              : 
    1087              :         // 2. 处理重试(去除频繁的重试日志,一秒可能重试上千次)
    1088      1461860 :         if (ret == HCCL_E_AGAIN) {
    1089      1461860 :             retryCount++;
    1090      1461860 :             continue;
    1091              :         }
    1092              : 
    1093              :         // 3. 处理资源不足(属于可预期回退场景)
    1094            0 :         if (ret == HCCL_E_UNAVAIL) {
    1095              :             auto elapsed
    1096            0 :                 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startTime)
    1097            0 :                       .count();
    1098            0 :             HCCL_WARNING(
    1099              :                 "[%s] channel connect resource unavailable, channelNum[%u], elapsed[%lld]ms, retryCount[%u]", __func__,
    1100              :                 channelNum, elapsed, retryCount);
    1101            0 :             return ret;
    1102              :         }
    1103              : 
    1104              :         // 4. 处理失败
    1105            0 :         if (ret != HCCL_SUCCESS) {
    1106              :             auto elapsed
    1107            0 :                 = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startTime)
    1108            0 :                       .count();
    1109            0 :             HCCL_ERROR(
    1110              :                 "[%s] channel connect failed, channelNum[%u], ret[%d], elapsed[%lld]ms, retryCount[%u]", __func__,
    1111              :                 channelNum, ret, elapsed, retryCount);
    1112            0 :             std::vector<Hccl::TlsStatus> tlsStatusList(channelNum, Hccl::TlsStatus::UNKNOWN);
    1113            0 :             GetAbnormalChannelTlsStatus(channelDescs, statusList, channelNum, tlsStatusList);
    1114            0 :             logger::ChannelLogger::PrintChannelErrorDetails(
    1115              :                 rankId_, channelNum, channelDescs, channelHandles, statusList, static_cast<uint64_t>(elapsed),
    1116            0 :                 tlsStatusList.data());
    1117            0 :             return ret;
    1118            0 :         }
    1119              : 
    1120              :         // 5. 正常情况:所有通道连接成功
    1121              :         auto elapsed
    1122            0 :             = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - startTime)
    1123            0 :                   .count();
    1124            0 :         HCCL_INFO(
    1125              :             "[%s] all channels connected successfully, channelNum[%u], elapsed[%lld]ms, retryCount[%u]", __func__,
    1126              :             channelNum, elapsed, retryCount);
    1127            0 :         break;
    1128      1461860 :     }
    1129            0 :     return HCCL_SUCCESS;
    1130            4 : }
    1131              : 
    1132           15 : HcclResult MyRank::ConfigSqDepthByExpansionMode(CommEngine engine, HcommChannelDesc& hcommDesc) const
    1133              : {
    1134           15 :     const u32 configuredSqDepth = config_.GetConfigSqDepth();
    1135           15 :     if (configuredSqDepth != HCCL_COMM_SQ_DEPTH_CONFIG_NOT_SET) {
    1136            7 :         const CommProtocol remoteProtocol = hcommDesc.remoteEndpoint.protocol;
    1137            7 :         if (engine == COMM_ENGINE_AIV
    1138            4 :             && (remoteProtocol == COMM_PROTOCOL_UBC_TP || remoteProtocol == COMM_PROTOCOL_UBC_CTP
    1139            2 :                 || remoteProtocol == COMM_PROTOCOL_UBG)) {
    1140            3 :             hcommDesc.ubAttr.sqDepth = configuredSqDepth;
    1141            3 :             return HCCL_SUCCESS;
    1142              :         } else {
    1143            4 :             HCCL_WARNING(
    1144              :                 "[%s] configured sqDepth[%u] is not supported when engine[%s] protocol[%s].", __func__,
    1145              :                 configuredSqDepth, GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(),
    1146              :                 MyRankUtils::GetCommProtocolEnumStr(remoteProtocol).c_str());
    1147              :         }
    1148              :     }
    1149              : 
    1150           12 :     constexpr u32 CCU_MS_MODE_DEPTH = 128;
    1151           12 :     constexpr u32 CCU_SCHED_MODE_DEPTH = 16;
    1152           12 :     if (engine == COMM_ENGINE_CCU) {
    1153            7 :         if (opExpansionMode_ == CCU_MS_MODE) {
    1154            2 :             hcommDesc.ubAttr.sqDepth = CCU_MS_MODE_DEPTH;
    1155            5 :         } else if (opExpansionMode_ == CCU_SCHED_MODE) {
    1156            4 :             hcommDesc.ubAttr.sqDepth = CCU_SCHED_MODE_DEPTH;
    1157              :         } else {
    1158            1 :             HCCL_ERROR("[%s] unexpected op expansion mode[%u] for ccu,", __func__, opExpansionMode_);
    1159            1 :             return HCCL_E_INTERNAL;
    1160              :         }
    1161              :     }
    1162           11 :     return HCCL_SUCCESS;
    1163              : }
    1164              : 
    1165            0 : void MyRank::LogChannelCreationInfo(
    1166              :     CommEngine engine, const std::string& commTag, const HcclChannelDesc* channelDescs, uint32_t channelNum,
    1167              :     const ChannelHandle* hostChannelHandleList) const
    1168              : {
    1169            0 :     for (u32 i = 0; i < channelNum; ++i) {
    1170            0 :         u32 remoteRank = channelDescs[i].remoteRank;
    1171            0 :         HcclCommDfx::AddChannelRemoteRankId(commTag, hostChannelHandleList[i], remoteRank);
    1172              :         // 打印UB通道建链信息
    1173            0 :         if (channelDescs[i].localEndpoint.loc.locType == ENDPOINT_LOC_TYPE_DEVICE
    1174            0 :             && channelDescs[i].remoteEndpoint.loc.locType == ENDPOINT_LOC_TYPE_DEVICE) {
    1175            0 :             HCCL_CONFIG_DEBUG(
    1176              :                 HCCL_RES,
    1177              :                 "create channel info:channel handle[%s] comm tag[%s] protocol[%s]"
    1178              :                 " local rank[%u] local dev phyid[%u] remote rank[%u] remote dev phyid[%u] engine[%s]",
    1179              :                 std::to_string(hostChannelHandleList[i]).c_str(), commTag.c_str(),
    1180              :                 MyRankUtils::GetCommProtocolEnumStr(channelDescs[i].localEndpoint.protocol).c_str(), rankId_,
    1181              :                 channelDescs[i].localEndpoint.loc.device.devPhyId, remoteRank,
    1182              :                 channelDescs[i].remoteEndpoint.loc.device.devPhyId,
    1183              :                 GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str());
    1184            0 :         } else {
    1185            0 :             HCCL_CONFIG_DEBUG(
    1186              :                 HCCL_RES,
    1187              :                 "create channel info:channel handle[%s] comm tag[%s] protocol[%s]"
    1188              :                 " local rank[%u] remote rank[%u] engine[%s]",
    1189              :                 std::to_string(hostChannelHandleList[i]).c_str(), commTag.c_str(),
    1190              :                 MyRankUtils::GetCommProtocolEnumStr(channelDescs[i].localEndpoint.protocol).c_str(), rankId_,
    1191              :                 remoteRank, GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str());
    1192              :         }
    1193              :     }
    1194            0 : }
    1195              : 
    1196            0 : HcclResult MyRank::FinalizeChannelsByEngine(
    1197              :     CommEngine engine, const std::string& commTag, uint32_t channelNum, std::vector<HcommChannelDesc>& hcommDescs,
    1198              :     ChannelHandle* hostChannelHandleList, ChannelHandle* channelHandles)
    1199              : {
    1200            0 :     if (engine == COMM_ENGINE_AICPU || engine == COMM_ENGINE_AICPU_TS) {
    1201              :         // 新增:添加 kernelLaunchAicpuCommInit 调用
    1202            0 :         if (!callbacks_.getAicpuCommState()) {
    1203            0 :             HCCL_INFO("MyRank::%s kernelLaunchAicpuCommInit start.", __func__);
    1204            0 :             HcclResult ret = callbacks_.kernelLaunchAicpuCommInit();
    1205            0 :             CHK_PRT_RET(
    1206              :                 ret != HCCL_SUCCESS, HCCL_ERROR("[%s] kernelLaunchAicpuCommInit failed, return [%d].", __func__, ret),
    1207              :                 ret);
    1208            0 :             callbacks_.setAicpuCommState(true);
    1209              :         }
    1210            0 :         HcommChannelDesc* hcommDesc = hcommDescs.data();
    1211            0 :         CHK_RET(ChannelProcess::ChannelKernelLaunchForComm(
    1212              :             channelHandles, hostChannelHandleList, hcommDesc, channelNum, commTag, binHandle_));
    1213              : 
    1214              :         // ns recovery
    1215            0 :         nsRecoveryProcessor_->AddNsRecoveryData(engine, channelHandles, hostChannelHandleList, channelNum, commTag);
    1216              : 
    1217            0 :         return HCCL_SUCCESS;
    1218              :     }
    1219              : 
    1220            0 :     if (engine == COMM_ENGINE_CPU || engine == COMM_ENGINE_CCU || engine == COMM_ENGINE_AIV) {
    1221            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1222              :             channelHandles, channelNum * sizeof(ChannelHandle), hostChannelHandleList,
    1223              :             channelNum * sizeof(ChannelHandle)));
    1224            0 :         return HCCL_SUCCESS;
    1225              :     }
    1226              : 
    1227            0 :     HCCL_ERROR(
    1228              :         "[MyRank][%s] unsupported comm engine[%s].", __func__,
    1229              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str());
    1230            0 :     return HCCL_E_NOT_SUPPORT;
    1231              : }
    1232              : 
    1233            6 : HcclResult MyRank::CreateChannels(
    1234              :     CommEngine engine, const std::string& commTag, const HcclChannelDesc* channelDescs, uint32_t channelNum,
    1235              :     ChannelHandle* channelHandles)
    1236              : {
    1237            6 :     CHK_PTR_NULL(channelDescs);
    1238            5 :     CHK_PTR_NULL(channelHandles);
    1239            4 :     CHK_PRT_RET(channelNum == 0, HCCL_ERROR("[%s] invalid param: channelNum is zero", __func__), HCCL_E_PARA);
    1240              : 
    1241            3 :     HCCL_INFO(
    1242              :         "[CreateChannels][Enter] engine[%s] commTag[%s] channelNum[%u] rankId[%u]",
    1243              :         GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), commTag.c_str(), channelNum, rankId_);
    1244              : 
    1245              :     // 参数检查
    1246            3 :     CHK_RET(CheckChannelParam(engine, channelDescs, channelNum));
    1247              : 
    1248            2 :     std::vector<ChannelHandle> hostChannelHandles(channelNum);
    1249            2 :     ChannelHandle* hostChannelHandleList = hostChannelHandles.data();
    1250              : 
    1251            2 :     auto& rdmaConfig = Hccl::EnvConfig::GetInstance().GetRdmaConfig();
    1252            4 :     std::vector<HcommChannelDesc> hcommDescs(channelNum);
    1253            4 :     std::vector<std::vector<MemHandle>> allHandles(channelNum);
    1254              :     // srcPortBuffers 作为 hcommDescs[i].roceAttr.srcPortList 的底层 buffer,由 FillRoceSrcPortList 填充;
    1255              :     // 生命周期需覆盖到通道构造完成(HostCpuRoceChannel 构造时深拷贝到自身 srcPortBuf_)。
    1256            2 :     std::vector<std::vector<uint16_t>> srcPortBuffers(channelNum);
    1257            5 :     for (u32 i = 0; i < channelNum; ++i) {
    1258            3 :         hcommDescs[i] = MyRankUtils::ChannelDescHccl2Hcomm(channelDescs[i], config_);
    1259            3 :         hcommDescs[i].roceAttr.qpThreshold = rdmaConfig.GetRdmaMultiQpThreshold();
    1260            3 :         CHK_RET(ConfigSqDepthByExpansionMode(engine, hcommDescs[i]));
    1261              : 
    1262            3 :         CHK_RET(MyRankUtils::FillRoceSrcPortList(channelDescs[i], hcommDescs[i], srcPortBuffers[i]));
    1263              :     }
    1264              : 
    1265            2 :     auto start = std::chrono::steady_clock::now();
    1266            2 :     std::string socketTag = commTag + "_engine_" + std::to_string(engine);
    1267            2 :     CHK_RET(BatchCreateSockets(channelDescs, channelNum, socketTag, hcommDescs));
    1268            2 :     CHK_RET_UNAVAIL(
    1269              :         BatchCreateChannels(engine, channelDescs, channelNum, hcommDescs, hostChannelHandleList, allHandles));
    1270              : 
    1271              :     // 锁内快照本次新建列表:connect 阶段不再持 channelIndexMtx_,避免长耗时 IO 阻塞
    1272              :     // Query/Destroy;回滚时基于快照重新取锁清理,保证 newChannels_ 读写均在锁内
    1273            2 :     std::vector<std::pair<u32, u32>> newChannelsSnapshot;
    1274              :     {
    1275            2 :         std::lock_guard<std::mutex> lock(channelIndexMtx_);
    1276            2 :         newChannelsSnapshot = newChannels_;
    1277            2 :     }
    1278              : 
    1279            2 :     if (!newChannelsSnapshot.empty()) {
    1280            1 :         HcclResult connRet = BatchConnectChannels(channelDescs, hostChannelHandleList, channelNum);
    1281            1 :         if (connRet != HCCL_SUCCESS && engine == COMM_ENGINE_CCU) {
    1282              :             // CCU 场景额外回滚本次新建的 channel,避免资源残留
    1283            1 :             HCCL_RUN_WARNING(
    1284              :                 "[%s] BatchConnectChannels failed[%d], engine[%s], new channels num[%u]", __func__, connRet,
    1285              :                 GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str(), newChannelsSnapshot.size());
    1286            1 :             std::lock_guard<std::mutex> lock(channelIndexMtx_);
    1287            1 :             HcclResult destroyRet = DestroyNewChannels(engine, channelDescs, newChannelsSnapshot);
    1288            1 :             if (destroyRet != HCCL_SUCCESS) {
    1289            0 :                 HCCL_ERROR(
    1290              :                     "[%s] DestroyNewChannels failed[%d] during rollback, connRet[%d], "
    1291              :                     "residual newChannels[%zu] may leak.",
    1292              :                     __func__, destroyRet, connRet, newChannels_.size());
    1293              :             }
    1294            1 :         }
    1295            1 :         CHK_RET(connRet);
    1296            0 :         auto end = std::chrono::steady_clock::now();
    1297            0 :         auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
    1298            0 :         HCCL_RUN_INFO(
    1299              :             "[MyRank][CreateChannels] CreateChannels Time Elapsed [%lld]us, channelNum [%u]", duration, channelNum);
    1300              :     }
    1301              : 
    1302              :     // 借用hcommDescs.socket,完成一致性校验必要的数据交换
    1303            1 :     CHK_RET(BatchExchangeAndCheckConsistency(channelDescs, hcommDescs, channelNum, newChannels_, engine));
    1304              : 
    1305              :     // 添加初始化时进行填表
    1306            0 :     LogChannelCreationInfo(engine, commTag, channelDescs, channelNum, hostChannelHandleList);
    1307              : 
    1308            0 :     return FinalizeChannelsByEngine(engine, commTag, channelNum, hcommDescs, hostChannelHandleList, channelHandles);
    1309            2 : }
    1310              : 
    1311            1 : HcclResult MyRank::ChannelGetHcclBuffer(ChannelHandle channel, void** buffer, uint64_t* size)
    1312              : {
    1313            1 :     CHK_PTR_NULL(buffer);
    1314            1 :     CHK_PTR_NULL(size);
    1315              : 
    1316            1 :     u32 memNum = 0;
    1317            1 :     CommMem* remoteMem = nullptr;
    1318            1 :     char** memTags = nullptr;
    1319            1 :     CHK_RET(static_cast<HcclResult>(HcommChannelGetRemoteMems(channel, &memNum, &remoteMem, &memTags)));
    1320            1 :     if (memNum > 0) {
    1321            0 :         CHK_PTR_NULL(remoteMem);
    1322              :         // AicpuTsHccsChannel不使用memTag,返回为空,默认索引0为cclBuffer
    1323            0 :         if (memTags == nullptr) {
    1324            0 :             *buffer = remoteMem[0].addr;
    1325            0 :             *size = remoteMem[0].size;
    1326            0 :             HCCL_INFO("[%s] Found HcclBuffer : addr=%p, size=%llu", __func__, *buffer, *size);
    1327            0 :             return HCCL_SUCCESS;
    1328              :         }
    1329            0 :         for (u32 i = 0; i < memNum; ++i) {
    1330            0 :             std::string tag = memTags[i];
    1331            0 :             if (tag == "HcclBuffer") {
    1332            0 :                 *buffer = remoteMem[i].addr;
    1333            0 :                 *size = remoteMem[i].size;
    1334            0 :                 HCCL_INFO("[%s] Found HcclBuffer : addr=%p, size=%llu", __func__, *buffer, *size);
    1335            0 :                 return HCCL_SUCCESS;
    1336              :             }
    1337            0 :             HCCL_INFO("[%s] Found %s : addr=%p, size=%llu", __func__, memTags[i], remoteMem[i].addr, remoteMem[i].size);
    1338            0 :         }
    1339              :     }
    1340            1 :     HCCL_ERROR("[%s] HcclBuffer not found.", __func__);
    1341            1 :     return HCCL_E_INTERNAL;
    1342              : }
    1343              : 
    1344              : HcclResult
    1345            4 : MyRank::ChannelGetRemoteMems(ChannelHandle channel, uint32_t* memNum, CommMem** remoteMem, char*** memTags) const
    1346              : {
    1347            4 :     CHK_PTR_NULL(remoteMem);
    1348            3 :     CHK_PTR_NULL(memTags);
    1349            2 :     CHK_PTR_NULL(memNum);
    1350            1 :     CHK_RET(static_cast<HcclResult>(HcommChannelGetRemoteMems(channel, memNum, remoteMem, memTags)));
    1351              :     // 添加空指针检查,防止返回的指针为空
    1352            1 :     if (*memNum > 0) {
    1353            0 :         CHK_PTR_NULL(*remoteMem);
    1354            0 :         CHK_PTR_NULL(*memTags);
    1355              :     }
    1356            1 :     HCCL_INFO("[%s] success. memNum[%u]", __func__, *memNum);
    1357            1 :     return HCCL_SUCCESS;
    1358              : }
    1359              : 
    1360            4 : HcclResult MyRank::ChannelGetRemoteMems(
    1361              :     ChannelHandle channel, uint32_t* memNum, CommMem** remoteMem, std::vector<std::string>& memTags) const
    1362              : {
    1363            4 :     CHK_PTR_NULL(remoteMem);
    1364            3 :     CHK_PTR_NULL(memNum);
    1365            2 :     char** rawTags = nullptr;
    1366            2 :     CHK_RET(static_cast<HcclResult>(HcommChannelGetRemoteMems(channel, memNum, remoteMem, &rawTags)));
    1367              :     // 添加空指针检查,防止返回的指针为空
    1368            2 :     if (*memNum > 0) {
    1369            1 :         CHK_PTR_NULL(*remoteMem);
    1370            1 :         CHK_PTR_NULL(rawTags);
    1371            1 :         memTags.reserve(*memNum);
    1372            3 :         for (uint32_t i = 0; i < *memNum; ++i) {
    1373            2 :             memTags.emplace_back(rawTags[i] == nullptr ? "" : rawTags[i]);
    1374              :         }
    1375              :     }
    1376            2 :     HCCL_INFO("[%s] success. memNum[%u]", __func__, *memNum);
    1377            2 :     return HCCL_SUCCESS;
    1378              : }
    1379              : 
    1380            0 : std::vector<ChannelHandle> MyRank::GetAllChannelList()
    1381              : {
    1382            0 :     ChannelTable channelTable = rankPairMgr_->GetChannelTable();
    1383            0 :     std::vector<ChannelHandle> channelList;
    1384            0 :     for (const auto& rankPair : channelTable) {
    1385            0 :         for (const auto& endPointPair : rankPair.second) {
    1386            0 :             for (const auto& comEngines : endPointPair.second) {
    1387            0 :                 channelList.insert(channelList.end(), comEngines.second.begin(), comEngines.second.end());
    1388              :             }
    1389              :         }
    1390              :     }
    1391              : 
    1392            0 :     return channelList;
    1393            0 : }
    1394              : 
    1395          164 : void MyRank::SetKfcControlTransfer(
    1396              :     std::shared_ptr<HDCommunicate> kfcControlTransferH2D, std::shared_ptr<HDCommunicate> kfcStatusTransferD2H)
    1397              : {
    1398          164 :     if (nsRecoveryProcessor_ == nullptr) {
    1399            1 :         HCCL_ERROR("[MyRank][SetKfcControlTransfer] nsRecoveryProcessor_ is null, cannot set KFC control transfer.");
    1400            1 :         return;
    1401              :     }
    1402          163 :     nsRecoveryProcessor_->SetKfcControlTransfer(kfcControlTransferH2D, kfcStatusTransferD2H);
    1403              : }
    1404              : 
    1405            0 : HcclResult MyRank::StopLaunch()
    1406              : {
    1407            0 :     HCCL_INFO("[NsRecovery][StopLaunch] MyRank::StopLaunch start!");
    1408            0 :     auto ret = nsRecoveryProcessor_->StopLaunch();
    1409            0 :     if (ret != HcclResult::HCCL_SUCCESS) {
    1410            0 :         HCCL_ERROR("[NsRecovery][StopLaunch] MyRank::StopLaunch failed, ret = 0x%016llx", HCCL_ERROR_CODE(ret));
    1411              :     }
    1412            0 :     HCCL_INFO("[NsRecovery][StopLaunch] MyRank::StopLaunch success!");
    1413            0 :     return ret;
    1414              : }
    1415              : 
    1416            0 : HcclResult MyRank::Clean()
    1417              : {
    1418            0 :     HCCL_INFO("[NsRecovery][Clean] MyRank::Clean start!");
    1419            0 :     auto channelList = GetAllChannelList();
    1420            0 :     if (channelList.empty()) {
    1421            0 :         HCCL_INFO("[NsRecovery][Clean] Channel list empty, No need to clean!");
    1422            0 :         return HcclResult::HCCL_SUCCESS;
    1423              :     }
    1424            0 :     auto ret = ChannelProcess::ChannelClean(channelList.data(), channelList.size());
    1425            0 :     if (ret != HcclResult::HCCL_SUCCESS) {
    1426            0 :         HCCL_ERROR("[NsRecovery][Clean] MyRank::Clean failed, ret = 0x%016llx", HCCL_ERROR_CODE(ret));
    1427            0 :         return ret;
    1428              :     }
    1429              : 
    1430            0 :     ret = nsRecoveryProcessor_->Clean();
    1431            0 :     if (ret != HcclResult::HCCL_SUCCESS) {
    1432            0 :         HCCL_ERROR("[NsRecovery][Clean] MyRank::Clean failed, ret = 0x%016llx", HCCL_ERROR_CODE(ret));
    1433            0 :         return ret;
    1434              :     }
    1435              : 
    1436            0 :     HCCL_INFO("[NsRecovery][Clean] MyRank::Clean success!");
    1437            0 :     return HcclResult::HCCL_SUCCESS;
    1438            0 : }
    1439              : 
    1440            0 : HcclResult MyRank::Resume()
    1441              : {
    1442            0 :     HCCL_INFO("[NsRecovery][Resume] MyRank::Resume start!");
    1443            0 :     auto channelList = GetAllChannelList();
    1444            0 :     if (channelList.empty()) {
    1445            0 :         HCCL_INFO("[NsRecovery][Resume] Resume list empty, No need to resume!");
    1446            0 :         return HcclResult::HCCL_SUCCESS;
    1447              :     }
    1448              : 
    1449            0 :     auto ret = ChannelProcess::ChannelResume(channelList.data(), channelList.size());
    1450            0 :     if (ret != HcclResult::HCCL_SUCCESS) {
    1451            0 :         HCCL_ERROR("[NsRecovery][Resume] MyRank::Resume failed, ret = 0x%016llx", HCCL_ERROR_CODE(ret));
    1452            0 :         return ret;
    1453              :     }
    1454              : 
    1455            0 :     ret = nsRecoveryProcessor_->Resume(binHandle_);
    1456            0 :     if (ret != HcclResult::HCCL_SUCCESS) {
    1457            0 :         HCCL_ERROR("[NsRecovery][Resume] MyRank::Resume failed, ret = 0x%016llx", HCCL_ERROR_CODE(ret));
    1458            0 :         return ret;
    1459              :     }
    1460              : 
    1461            0 :     HCCL_INFO("[NsRecovery][Resume] MyRank::Resume success!");
    1462            0 :     return HCCL_SUCCESS;
    1463            0 : }
    1464              : 
    1465            7 : CollCommConfigConsistency& MyRank::GetCollCommConfigConsistency() { return collCommConfigConsistency_; }
    1466              : 
    1467              : } // namespace hccl
        

Generated by: LCOV version 2.0-1