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

Generated by: LCOV version 2.0-1