LCOV - code coverage report
Current view: top level - legacy/ascend910/framework/common/src/onesided_memory_management - global_mem_manager.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.1 % 177 147
Test Date: 2026-08-18 17:47:01 Functions: 100.0 % 12 12

            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 "global_mem_manager.h"
      12              : 
      13              : #include <string>
      14              : #include "hccl_mem.h"
      15              : 
      16              : namespace hccl {
      17          135 : GlobalMemRegMgr::~GlobalMemRegMgr() {}
      18              : 
      19           54 : GlobalMemRegMgr& GlobalMemRegMgr::GetInstance()
      20              : {
      21              :     // reserve 1 instance for invalid deviceid and host
      22          186 :     static GlobalMemRegMgr instance[MAX_MODULE_DEVICE_NUM + 1];
      23           54 :     s32 deviceLogicID = 0;
      24              : 
      25           54 :     HcclResult hcclRet = hrtGetDeviceRefresh(&deviceLogicID);
      26           54 :     if (hcclRet != HCCL_SUCCESS) {
      27            0 :         HCCL_RUN_WARNING(
      28              :             "GlobalMemRegMgr::GetInstance hrtGetDeviceRefresh failed, ret[%d], "
      29              :             "return reserve instance",
      30              :             hcclRet);
      31            0 :         return instance[MAX_MODULE_DEVICE_NUM];
      32              :     }
      33              : 
      34           54 :     if (static_cast<u32>(deviceLogicID) >= MAX_MODULE_DEVICE_NUM || deviceLogicID <= HOST_DEVICE_ID) {
      35            0 :         HCCL_RUN_WARNING("[Get][Instance]deviceLogicID[%d] is invalid, return reserve instance", deviceLogicID);
      36            0 :         return instance[MAX_MODULE_DEVICE_NUM];
      37              :     }
      38              : 
      39           54 :     HCCL_INFO("GlobalMemRegMgr::GetInstance deviceLogicID[%d].", deviceLogicID);
      40           54 :     return instance[deviceLogicID];
      41              : }
      42              : 
      43            2 : HcclResult GlobalMemRegMgr::Destroy()
      44              : {
      45            2 :     HCCL_INFO("[GlobalMemRegMgr][%s] start.", __func__);
      46            2 :     std::unique_lock<std::mutex> lock(netDevCtxMtx_);
      47            2 :     for (auto& pair : netDevCtxMap_) {
      48            0 :         if (pair.second.first == NicType::DEVICE_NIC_TYPE) {
      49            0 :             socketManager_->ServerDeInit(pair.first.ip, pair.first.listenPort);
      50              :         }
      51            0 :         HcclNetCloseDev(pair.second.second);
      52            0 :         HCCL_INFO("[GlobalMemRegMgr][%s] Close netdev[%p].", __func__, pair.second.second);
      53              :     }
      54            2 :     netDevCtxMap_.clear();
      55            2 :     lock.unlock();
      56            2 :     CHK_RET(DeInitNic());
      57            2 :     HCCL_INFO("[GlobalMemRegMgr][%s] end.", __func__);
      58            2 :     return HCCL_SUCCESS;
      59            2 : }
      60              : 
      61            8 : HcclResult GlobalMemRegMgr::CheckOverlapAndInsert(GlobalMemRecord& memRecord, void** memRecordHandle)
      62              : {
      63              :     // 由于每次插入都会保证不产生重叠,所以只需要检查最接近的两条记录是否有重叠即可
      64            8 :     const auto memInfo = memRecord.PrintInfo();
      65              : 
      66            8 :     auto it = memRecordSet_.lower_bound(memRecord);
      67            8 :     if (it != memRecordSet_.cend()) {
      68            3 :         if (memRecord == *it) {
      69              :             // 已经存在相同的记录,取出地址作为handle
      70            0 :             *memRecordHandle = const_cast<GlobalMemRecord*>(&(*it));
      71            0 :             HCCL_INFO(
      72              :                 "[GlobalMemRegMgr][CheckOverlapAndInsert] The memory[%s] has been registered already.",
      73              :                 memInfo.c_str());
      74            0 :             return HCCL_SUCCESS;
      75              :         }
      76              : 
      77              :         // 检查后一个记录
      78            3 :         if (memRecord.HasOverlap(*it)) {
      79              :             // 后一个记录有重叠,报错
      80            1 :             HCCL_ERROR(
      81              :                 "[GlobalMemRegMgr][CheckOverlapAndInsert] The new memory[%s] overlaps with an existing memory[%s].",
      82              :                 memInfo.c_str(), (*it).PrintInfo().c_str());
      83            1 :             return HCCL_E_PARA;
      84              :         }
      85              :     }
      86              : 
      87              :     // 检查前一个记录
      88            7 :     if (it != memRecordSet_.cbegin()) {
      89            2 :         auto prevIt = std::prev(it);
      90            2 :         if (memRecord.HasOverlap(*prevIt)) {
      91              :             // 前一个记录有重叠,报错
      92            1 :             HCCL_ERROR(
      93              :                 "[GlobalMemRegMgr][CheckOverlapAndInsert] The new memory[%s] overlaps with an existing memory[%s].",
      94              :                 memInfo.c_str(), (*prevIt).PrintInfo().c_str());
      95            1 :             return HCCL_E_PARA;
      96              :         }
      97              :     }
      98              : 
      99              :     // 没有重叠,插入在当前it附近的位置
     100            6 :     auto insertIt = memRecordSet_.insert(it, std::move(memRecord));
     101              : 
     102              :     // 取出地址作为handle
     103            6 :     *memRecordHandle = const_cast<GlobalMemRecord*>(&(*insertIt));
     104              : 
     105            6 :     return HCCL_SUCCESS;
     106            8 : }
     107              : 
     108           10 : HcclResult GlobalMemRegMgr::Reg(const HcclMem* mem, void** memRecordHandle)
     109              : {
     110              :     // 不允许注册空内存,报错退出
     111           10 :     CHK_PTR_NULL(mem);
     112           10 :     CHK_PRT_RET(
     113              :         mem->addr == nullptr, HCCL_ERROR("[GlobalMemRegMgr][Reg] The address of mem[%p] to register is null.", mem),
     114              :         HCCL_E_PARA);
     115            9 :     CHK_PRT_RET(
     116              :         mem->size == 0, HCCL_ERROR("[GlobalMemRegMgr][Reg] The size of mem[%p] to register is 0.", mem), HCCL_E_PARA);
     117              : 
     118            8 :     GlobalMemRecord newRecord(mem);
     119            8 :     const auto memInfo = newRecord.PrintInfo();
     120            8 :     std::unique_lock<std::mutex> lock(lock_);
     121            8 :     CHK_RET(CheckOverlapAndInsert(newRecord, memRecordHandle));
     122            6 :     HCCL_INFO("[GlobalMemRegMgr][Reg] Added a new memory record[%s], handle[%p].", memInfo.c_str(), *memRecordHandle);
     123              : 
     124              :     // 记录地址,便于其他接口进行入参handle合法性校验
     125            6 :     validHandlePtrSet.emplace(*memRecordHandle);
     126              : 
     127            6 :     return HCCL_SUCCESS;
     128            8 : }
     129              : 
     130            5 : HcclResult GlobalMemRegMgr::DeReg(void* memRecordHandle)
     131              : {
     132            5 :     const auto* memRecordPtr = static_cast<GlobalMemRecord*>(memRecordHandle);
     133            5 :     const auto memInfo = memRecordPtr->PrintInfo();
     134            5 :     std::unique_lock<std::mutex> lock(lock_);
     135              : 
     136              :     // 先找到指向这个记录的迭代器
     137            5 :     const auto it = memRecordSet_.find(*memRecordPtr);
     138            5 :     if (it == memRecordSet_.cend()) {
     139              :         // 找不到记录报错退出
     140            1 :         HCCL_ERROR("[GlobalMemRegMgr][DeReg] Cannot found the corresponding record of memory[%s].", memInfo.c_str());
     141            1 :         return HCCL_E_NOT_FOUND;
     142              :     }
     143              : 
     144              :     // 检查内存记录是否还与通信域绑定
     145            4 :     if (memRecordPtr->IsBeingBound()) {
     146              :         // 该内存还与一个或多个通信域绑定,报错并打印绑定的信息
     147            1 :         const auto boundComm = memRecordPtr->GetBoundComm();
     148            1 :         HCCL_ERROR(
     149              :             "[GlobalMemRegMgr][DeReg] Cannot deregistor memory[%s] since it is still bound to comm(s) listed below:",
     150              :             memInfo.c_str());
     151              : 
     152            2 :         for (const auto& commIdentifier : boundComm) {
     153            1 :             HCCL_ERROR("[GlobalMemRegMgr][DeReg][bound comm] %s", commIdentifier.c_str());
     154              :         }
     155              : 
     156            1 :         HCCL_ERROR("[GlobalMemRegMgr][DeReg] Please unbind from all bound comm first.");
     157            1 :         return HCCL_E_PARA;
     158            1 :     }
     159            3 :     HcclResult ret = HCCL_SUCCESS;
     160            3 :     auto regBufInfo = memRecordPtr->GetAllRegBufInfo();
     161            3 :     for (auto& pair : regBufInfo) {
     162              :         do {
     163            0 :             ret = HcclMemDereg(&pair.second); // 需循环调用DeregMem解注册注册内存(一块内存多次Reg的情况,内部有计数)
     164            0 :             CHK_PRT_CONT(
     165              :                 ret != HCCL_SUCCESS && ret != HCCL_E_AGAIN,
     166              :                 HCCL_ERROR(
     167              :                     "[GlobalMemRegMgr][DeReg] Dereg global mem failed, addr[%p] size[%lu].", pair.second.addr,
     168              :                     pair.second.len));
     169            0 :         } while (ret == HCCL_E_AGAIN);
     170              :     }
     171              : 
     172              :     // 清除记录,析构时会触发网络设备的解注册
     173            3 :     memRecordSet_.erase(it);
     174            3 :     HCCL_INFO("[GlobalMemRegMgr][DeReg] Memory[%s] has been deregistered.", memInfo.c_str());
     175              : 
     176              :     // 当内存全部解注册后,主动释放网络资源
     177            3 :     if (memRecordSet_.empty()) {
     178            2 :         CHK_RET(Destroy());
     179              :     }
     180              : 
     181            3 :     validHandlePtrSet.erase(memRecordHandle);
     182            3 :     return HCCL_SUCCESS;
     183            5 : }
     184              : 
     185           17 : HcclResult GlobalMemRegMgr::InitNic()
     186              : {
     187           17 :     std::lock_guard<std::mutex> lock(netDevCtxMtx_);
     188           17 :     if (nicInited_) {
     189           15 :         HCCL_INFO("[InitNic] Nic has been inited. devicePhyId[%u], deviceLogicId[%d]", devicePhyId_, deviceLogicId_);
     190           15 :         return HCCL_SUCCESS;
     191              :     }
     192              : 
     193            2 :     if (devicePhyId_ == INVALID_UINT || deviceLogicId_ == INVALID_INT) {
     194            1 :         CHK_RET(hrtGetDevice(&deviceLogicId_));
     195            1 :         CHK_RET(hrtGetDevicePhyIdByIndex(static_cast<u32>(deviceLogicId_), devicePhyId_));
     196              :     }
     197            2 :     CHK_RET(HcclNetInit(NICDeployment::NIC_DEPLOYMENT_DEVICE, devicePhyId_, static_cast<u32>(deviceLogicId_), false));
     198            2 :     nicInited_ = true;
     199            2 :     socketManager_.reset(new (std::nothrow)
     200            2 :                              HcclSocketManager(NICDeployment::NIC_DEPLOYMENT_DEVICE, deviceLogicId_, devicePhyId_, 0));
     201            2 :     CHK_PTR_NULL(socketManager_);
     202            2 :     HCCL_INFO("[InitNic] Nic init success, devicePhyId[%u], deviceLogicId[%d]", devicePhyId_, deviceLogicId_);
     203            2 :     return HCCL_SUCCESS;
     204           17 : }
     205              : 
     206            4 : HcclResult GlobalMemRegMgr::DeInitNic()
     207              : {
     208            4 :     if (!nicInited_) {
     209            2 :         HCCL_INFO(
     210              :             "[DeInitNic] Nic has been deinited. devicePhyId[%u], deviceLogicId[%d]", devicePhyId_, deviceLogicId_);
     211            2 :         return HCCL_SUCCESS;
     212              :     }
     213              : 
     214            2 :     if (devicePhyId_ == INVALID_UINT || deviceLogicId_ == INVALID_INT) {
     215            0 :         CHK_RET(hrtGetDevice(&deviceLogicId_));
     216            0 :         CHK_RET(hrtGetDevicePhyIdByIndex(static_cast<u32>(deviceLogicId_), devicePhyId_));
     217              :     }
     218            2 :     CHK_RET(HcclNetDeInit(NICDeployment::NIC_DEPLOYMENT_DEVICE, devicePhyId_, static_cast<u32>(deviceLogicId_)));
     219            2 :     nicInited_ = false;
     220            2 :     HCCL_INFO("[DeInitNic] Nic deinit success. devicePhyId[%u], deviceLogicId[%d]", devicePhyId_, deviceLogicId_);
     221            2 :     return HCCL_SUCCESS;
     222              : }
     223              : 
     224            1 : HcclResult GlobalMemRegMgr::CheckOneSidedBackupAndSetDevId(
     225              :     const HcclIpAddress& ipAddr, u32& backupDevPhyId, u32& backupDevLogicId, std::vector<HcclIpAddress>& localIpList,
     226              :     bool& isOneSidedTaskAndBackupInitA3)
     227              : {
     228            1 :     DevType deviceType = DevType::DEV_TYPE_COUNT;
     229            1 :     CHK_RET(hrtGetDeviceType(deviceType));
     230            1 :     if (deviceType != DevType::DEV_TYPE_910_93) {
     231            0 :         isOneSidedTaskAndBackupInitA3 = false;
     232            0 :         HCCL_INFO(
     233              :             "[GlobalMemRegMgr::CheckOneSidedBackupAndSetDevId] deviceType[%d] is not 910_93, One sided backup not "
     234              :             "support",
     235              :             static_cast<u32>(deviceType));
     236            0 :         return HCCL_SUCCESS;
     237              :     }
     238            1 :     CHK_RET(hrtGetPairDevicePhyId(devicePhyId_, backupDevPhyId));
     239            1 :     CHK_RET(hrtRaGetDeviceIP(devicePhyId_, localIpList));
     240            1 :     std::vector<HcclIpAddress> backupIpList;
     241            1 :     std::vector<std::vector<HcclIpAddress>> chipDeviceIPs;
     242            1 :     CHK_RET(hrtRaGetDeviceAllNicIP(chipDeviceIPs));
     243            1 :     if (chipDeviceIPs.empty()) {
     244            0 :         HCCL_RUN_WARNING(
     245              :             "[GlobalMemRegMgr::CheckOneSidedBackupAndSetDevId] chipDeviceIPs is empty, system nic ip may not set.");
     246            0 :         isOneSidedTaskAndBackupInitA3 = false;
     247            0 :         return HCCL_SUCCESS;
     248              :     }
     249            1 :     u32 ipIdex = 1U - (devicePhyId_ % 2U);
     250            3 :     std::copy_if(
     251            2 :         chipDeviceIPs[ipIdex].begin(), chipDeviceIPs[ipIdex].end(), std::back_inserter(backupIpList),
     252            1 :         [](const HcclIpAddress& ip) {
     253            1 :             return !ip.IsIPv6();
     254              :         });
     255            1 :     auto equalToLocal = [&ipAddr](const HcclIpAddress& entry) {
     256            1 :         return entry == ipAddr;
     257            1 :     };
     258            1 :     isOneSidedTaskAndBackupInitA3 = !std::any_of(localIpList.begin(), localIpList.end(), equalToLocal)
     259            1 :                                     && std::any_of(backupIpList.begin(), backupIpList.end(), equalToLocal);
     260            1 :     if (isOneSidedTaskAndBackupInitA3) {
     261            0 :         CHK_RET(hrtGetDeviceIndexByPhyId(backupDevPhyId, backupDevLogicId));
     262              :     }
     263            1 :     HCCL_INFO(
     264              :         "[GlobalMemRegMgr::CheckOneSidedBackupAndSetDevI]devicePhysicID[%u], localIpList[%s], backupDevPhyId[%d], "
     265              :         "backupDeviceIP[0]:[%s],"
     266              :         "isOneSidedTaskAndBackupInitA3[%s]",
     267              :         devicePhyId_, localIpList[0].GetReadableAddress(), backupDevPhyId, backupIpList[0].GetReadableAddress(),
     268              :         isOneSidedTaskAndBackupInitA3 ? "true" : "false");
     269            1 :     return HCCL_SUCCESS;
     270            1 : }
     271              : 
     272              : HcclResult
     273            1 : GlobalMemRegMgr::GetNetDevCtx(NicType nicType, const HcclIpAddress& ipAddr, u32 port, HcclNetDevCtx& netDevCtx)
     274              : {
     275            1 :     if (devicePhyId_ == INVALID_UINT || deviceLogicId_ == INVALID_INT) {
     276            1 :         CHK_RET(hrtGetDevice(&deviceLogicId_));
     277            1 :         CHK_RET(hrtGetDevicePhyIdByIndex(static_cast<u32>(deviceLogicId_), devicePhyId_));
     278              :     }
     279            1 :     HCCL_INFO("[GlobalMemRegMgr][GetNetDevCtx] nicType[%d], ip[%s]", nicType, ipAddr.GetReadableAddress());
     280              : 
     281            1 :     u32 backupDevPhyId = INVALID_INT;
     282            1 :     u32 backupDevLogicId = INVALID_INT;
     283            1 :     bool isOneSidedTaskAndBackupInitA3 = false;
     284            1 :     std::vector<HcclIpAddress> localIpList;
     285            1 :     CHK_RET(CheckOneSidedBackupAndSetDevId(
     286              :         ipAddr, backupDevPhyId, backupDevLogicId, localIpList, isOneSidedTaskAndBackupInitA3));
     287            1 :     HCCL_INFO(
     288              :         "[GlobalMemRegMgr][GetNetDevCtx] nicType[%d], ip[%s], port[%u]", nicType, ipAddr.GetReadableAddress(), port);
     289              : 
     290            1 :     std::lock_guard<std::mutex> lock(netDevCtxMtx_);
     291              :     // 进程粒度open dev,如果已open,直接复用
     292            1 :     PortInfo portInfo(ipAddr, port);
     293            1 :     if (netDevCtxMap_.find(portInfo) != netDevCtxMap_.end()) {
     294            0 :         netDevCtx = netDevCtxMap_[portInfo].second;
     295            0 :         CHK_PTR_NULL(netDevCtx);
     296            0 :         return HCCL_SUCCESS;
     297              :     }
     298              :     HcclNetDevCtx tempNetDevCtx;
     299            1 :     if (isOneSidedTaskAndBackupInitA3) {
     300            0 :         HCCL_INFO(
     301              :             "[GlobalMemRegMgr::GetNetDevCtx] OneSeidedService backupInit: backupDevPhyId[%d], backupDevLogicId[%d], "
     302              :             "localIp[%s], backupIp[%s]",
     303              :             backupDevPhyId, backupDevLogicId, localIpList[0].GetReadableAddress(), ipAddr.GetReadableAddress());
     304            0 :         CHK_RET(HcclNetInit(NICDeployment::NIC_DEPLOYMENT_DEVICE, backupDevPhyId, backupDevLogicId, false, true));
     305            0 :         CHK_RET(
     306              :             HcclNetInit(NICDeployment::NIC_DEPLOYMENT_DEVICE, devicePhyId_, static_cast<u32>(deviceLogicId_), false));
     307            0 :         CHK_RET(HcclNetOpenDev(&tempNetDevCtx, nicType, backupDevPhyId, backupDevLogicId, ipAddr, localIpList[0]));
     308              :     } else {
     309            1 :         CHK_RET(HcclNetOpenDev(&tempNetDevCtx, nicType, devicePhyId_, deviceLogicId_, ipAddr));
     310              :     }
     311            1 :     CHK_PTR_NULL(tempNetDevCtx);
     312            1 :     netDevCtxMap_.insert(std::make_pair(portInfo, std::make_pair(nicType, tempNetDevCtx)));
     313            1 :     netDevCtx = tempNetDevCtx;
     314            1 :     if (nicType == NicType::DEVICE_NIC_TYPE) {
     315            1 :         CHK_RET(socketManager_->ServerInit(netDevCtx, port));
     316              :     }
     317            1 :     HCCL_INFO(
     318              :         "[GlobalMemRegMgr][GetNetDevCtx] nicType[%d] ip[%s] has been Init.", nicType, ipAddr.GetReadableAddress());
     319            1 :     return HCCL_SUCCESS;
     320            1 : }
     321              : 
     322              : } // namespace hccl
        

Generated by: LCOV version 2.0-1