LCOV - code coverage report
Current view: top level - base_comm/resources/ccu/ccu_transport - ccu_channel_ctx_pool.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.7 % 118 94
Test Date: 2026-08-18 17:47:01 Functions: 90.0 % 10 9

            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 "ccu_channel_ctx_pool.h"
      12              : 
      13              : #include <unordered_set>
      14              : 
      15              : #include "ccu_device_pub.h"
      16              : #include "orion_adpt_utils.h"
      17              : 
      18              : namespace hcomm {
      19              : 
      20              : constexpr uint32_t CCU_DEFAULT_REQUEST_SQ_SIZE = 128;
      21              : constexpr uint32_t CCU_DEFAULT_REQUEST_CHANNEL_NUM = 1;
      22              : constexpr uint32_t CCU_DEFAULT_REQUEST_JETTY_NUM = 0; // 申请数量为0时,由平台层决定提供数量
      23              : 
      24           29 : CcuChannelCtxPool::CcuChannelCtxPool(int32_t devLogicId) : devLogicId_(devLogicId) {}
      25              : 
      26           29 : CcuChannelCtxPool::~CcuChannelCtxPool()
      27              : {
      28              :     // 对象析构时清空多个map,batchMap_中元素的jettys清空触发ccuJetty析构释放
      29           29 :     (void)ReleaseConfirmedChannelRes();
      30           29 : }
      31              : 
      32           15 : HcclResult CcuChannelCtxPool::ResourceBatch::Init(const std::vector<CcuChannelInfo>& channelInfos)
      33              : {
      34           15 :     const uint32_t channelNum = channelInfos.size();
      35           15 :     channelIdKeys.reserve(channelNum);
      36           15 :     availableChannelIdKeys.reserve(channelNum);
      37           44 :     for (const auto& channelInfo : channelInfos) {
      38           29 :         const auto dieId = channelInfo.dieId;
      39           29 :         const auto channelId = channelInfo.channelId;
      40           29 :         channelIdKeys.emplace_back(dieId, channelId);
      41           29 :         availableChannelIdKeys.emplace_back(dieId, channelId);
      42              : 
      43           58 :         for (const auto& jettyInfo : channelInfo.jettyInfos) {
      44           29 :             const auto taJettyId = jettyInfo.taJettyId;
      45           29 :             const auto jettyIdKey = std::make_pair(dieId, taJettyId);
      46           29 :             if (jettys.find(jettyIdKey) != jettys.end()) {
      47           14 :                 continue;
      48              :             }
      49              : 
      50           15 :             std::unique_ptr<CcuJetty> ccuJetty;
      51           15 :             CHK_RET(CcuCreateJetty(key, jettyInfo, ccuJetty));
      52              : 
      53           15 :             jettys[jettyIdKey] = std::move(ccuJetty);
      54           15 :         }
      55              :     }
      56              : 
      57           15 :     return HcclResult::HCCL_SUCCESS;
      58              : }
      59              : 
      60           15 : HcclResult CcuChannelCtxPool::PrepareCreate(const std::vector<Hccl::LinkData>& links, uint32_t sqSize)
      61              : {
      62           15 :     CHK_PRT_RET(
      63              :         links.empty(),
      64              :         HCCL_INFO("[CcuChannelCtxPool][%s] passed, links is empty, devLogicId[%d].", __func__, devLogicId_),
      65              :         HcclResult::HCCL_SUCCESS);
      66              : 
      67           30 :     for (const auto& link : links) {
      68           15 :         auto it = allocatedChannelIdMap_.find(link);
      69           15 :         if (it != allocatedChannelIdMap_.end()) {
      70            0 :             HCCL_INFO(
      71              :                 "[CcuChannelCtxPool][%s] passed, link[%s] is already allocated, "
      72              :                 "devLogicId[%d].",
      73              :                 __func__, link.Describe().c_str(), devLogicId_);
      74            0 :             continue;
      75              :         }
      76              : 
      77           15 :         const auto& locAddr = link.GetLocalAddr();
      78           15 :         ResourceBatch* batchPtr = nullptr;
      79           15 :         auto ret = GetAvailableBatch(locAddr, batchPtr, sqSize);
      80           15 :         CHK_PRT_RET(
      81              :             ret == HcclResult::HCCL_E_UNAVAIL,
      82              :             HCCL_WARNING(
      83              :                 "[CcuChannelCtxPool][%s] failed to alloc ccu channels, ccu resources "
      84              :                 "are unavailable, locAddr[%s], devLogicId[%d], sqSize[%u].",
      85              :                 __func__, locAddr.Describe().c_str(), devLogicId_, sqSize),
      86              :             ret);
      87           15 :         CHK_RET(ret);
      88              : 
      89           15 :         ChannelIdKey channelIdKey = batchPtr->availableChannelIdKeys.back();
      90           15 :         batchPtr->availableChannelIdKeys.pop_back();
      91           15 :         unconfirmedRecord_.allocations.emplace_back(Allocation{link, channelIdKey, batchPtr});
      92           15 :         allocatedChannelIdMap_[link] = channelIdKey;
      93           15 :         channelRemoteRankIdMap_[channelIdKey] = link.GetRemoteRankId();
      94              : 
      95           15 :         HCCL_INFO(
      96              :             "[CcuChannelCtxPool][%s] allocated new channelId[%u] of die[%u] to link[%s], "
      97              :             "devLogicId[%d], sqSize[%u].",
      98              :             __func__, channelIdKey.second, channelIdKey.first, link.Describe().c_str(), devLogicId_, sqSize);
      99              :     }
     100              : 
     101           15 :     isReleased_ = false;
     102           15 :     return HcclResult::HCCL_SUCCESS;
     103              : }
     104              : 
     105              : // 当前以locAddr为粒度调用,根据locAddr可以找到已申请的批次,如果资源充足则复用,不足则按新批次申请资源
     106           15 : HcclResult CcuChannelCtxPool::GetAvailableBatch(const BatchKey& batchKey, ResourceBatch*& batchPtr, uint32_t sqSize)
     107              : {
     108              :     // 当前以locAddr作为batchKey,不同本端不能复用资源
     109           15 :     if (FindAvailableBatch(batchKey, batchPtr)) {
     110            0 :         return HcclResult::HCCL_SUCCESS;
     111              :     }
     112              :     // 已有的资源不足,需要新增资源,获取的channel数量可能超过申请数量
     113           15 :     CommAddr commAddr{};
     114           15 :     CHK_RET(IpAddressToCommAddr(batchKey, commAddr));
     115              :     // 使用传入的sqSize,如果为0xFFFFFFFF则使用默认值
     116           15 :     uint32_t actualSqSize = (sqSize != 0xFFFFFFFF) ? sqSize : CCU_DEFAULT_REQUEST_SQ_SIZE;
     117              :     const CcuChannelPara channelPara{
     118           15 :         commAddr, CCU_DEFAULT_REQUEST_CHANNEL_NUM, CCU_DEFAULT_REQUEST_JETTY_NUM, actualSqSize};
     119           15 :     std::vector<CcuChannelInfo> channelInfos;
     120           15 :     auto ret = CcuAllocChannels(devLogicId_, channelPara, channelInfos);
     121           15 :     CHK_PRT_RET(
     122              :         ret == HcclResult::HCCL_E_UNAVAIL,
     123              :         HCCL_WARNING(
     124              :             "[CcuChannelCtxPool][%s] failed to alloc ccu channels, ccu resources "
     125              :             "are unavailable, locAddr[%s] devLogicId[%d].",
     126              :             __func__, batchKey.Describe().c_str(), devLogicId_),
     127              :         ret);
     128           15 :     CHK_RET(ret);
     129              :     // 如果新增资源保存失败,手动释放避免泄露
     130           15 :     ret = CreateAndSaveNewBatch(batchKey, channelInfos, batchPtr);
     131           15 :     if (ret != HcclResult::HCCL_SUCCESS) {
     132            0 :         HCCL_ERROR(
     133              :             "[CcuChannelCtxPool][%s] failed, try to release temp ccu resources, locAddr[%s], "
     134              :             "devLogicId[%d], .",
     135              :             __func__, batchKey.Describe().c_str(), devLogicId_);
     136            0 :         for (const auto& channelInfo : channelInfos) {
     137            0 :             const auto dieId = channelInfo.dieId;
     138            0 :             const auto channelId = channelInfo.channelId;
     139            0 :             CHK_RET(CcuReleaseChannel(devLogicId_, dieId, channelId));
     140              :         }
     141            0 :         return ret;
     142              :     }
     143           15 :     return HcclResult::HCCL_SUCCESS;
     144           15 : }
     145              : 
     146           15 : HcclResult CcuChannelCtxPool::CreateAndSaveNewBatch(
     147              :     const BatchKey& batchKey, const std::vector<CcuChannelInfo> channelInfos, ResourceBatch*& batchPtr)
     148              : {
     149              :     // todo: 需要检查资源管理是否存在泄露可能
     150           15 :     auto& batches = batchMap_[batchKey];
     151           15 :     std::unique_ptr<ResourceBatch> newBatch{nullptr};
     152           15 :     newBatch.reset(new (std::nothrow) ResourceBatch(batchKey));
     153           15 :     CHK_PTR_NULL(newBatch);
     154           15 :     CHK_RET(newBatch->Init(channelInfos));
     155           44 :     for (const auto& channelInfo : channelInfos) {
     156           29 :         const auto dieId = channelInfo.dieId;
     157           29 :         const auto channelIdKey = std::make_pair(dieId, channelInfo.channelId);
     158              : 
     159           29 :         std::vector<CcuJetty*> jettys;
     160           58 :         for (const auto& jettyInfo : channelInfo.jettyInfos) {
     161           29 :             const auto jettyIdKey = std::make_pair(dieId, jettyInfo.taJettyId);
     162           29 :             jettys.emplace_back(newBatch->jettys[jettyIdKey].get());
     163              :         }
     164              : 
     165           29 :         channelJettyInfoMap_.emplace(channelIdKey, std::make_pair(channelInfo, jettys));
     166           29 :         usedChannelCntMap_[dieId] += 1;
     167           29 :     }
     168              : 
     169           15 :     batches.push_back(std::move(newBatch));
     170           15 :     ResourceBatch* rawBatch = batches.back().get();
     171              : 
     172           15 :     unconfirmedRecord_.newBatchSet.insert(rawBatch);
     173           15 :     batchPtr = rawBatch;
     174           15 :     return HcclResult::HCCL_SUCCESS;
     175           15 : }
     176              : 
     177           15 : bool CcuChannelCtxPool::FindAvailableBatch(const BatchKey& batchKey, ResourceBatch*& batchPtr) const
     178              : {
     179           15 :     auto it = batchMap_.find(batchKey);
     180           15 :     if (it == batchMap_.end()) {
     181           15 :         return false;
     182              :     }
     183              : 
     184            0 :     auto& batches = it->second;
     185            0 :     if (batches.empty()) {
     186            0 :         return false;
     187              :     }
     188              :     // 当前分配逻辑只有最后一个batch可能还有空闲资源
     189            0 :     auto& lastBatch = batches.back();
     190            0 :     if (lastBatch->availableChannelIdKeys.empty()) {
     191            0 :         return false;
     192              :     }
     193              : 
     194            0 :     batchPtr = lastBatch.get();
     195            0 :     return true;
     196              : }
     197              : 
     198              : HcclResult
     199           15 : CcuChannelCtxPool::GetChannelCtx(const Hccl::LinkData& link, CcuChannelCtxPool::CcuChannelCtx& channelCtx) const
     200              : {
     201           15 :     const auto& it = allocatedChannelIdMap_.find(link);
     202           15 :     CHK_PRT_RET(
     203              :         it == allocatedChannelIdMap_.end(),
     204              :         HCCL_ERROR(
     205              :             "[CcuChannelCtxPool][%s] failed to find allocated channelId of link[%s], ", "devLogicId[%d].", __func__,
     206              :             link.Describe().c_str(), devLogicId_),
     207              :         HcclResult::HCCL_E_NOT_FOUND);
     208              :     // 内部维护数据保证channelJettyInfoMap_记录的资源存在
     209           15 :     channelCtx = channelJettyInfoMap_.at(it->second);
     210           15 :     return HcclResult::HCCL_SUCCESS;
     211              : }
     212              : 
     213           29 : HcclResult CcuChannelCtxPool::ReleaseConfirmedChannelRes()
     214              : {
     215           58 :     for (const auto& infoEntry : channelJettyInfoMap_) {
     216           29 :         const auto& channelIdKey = infoEntry.first;
     217           29 :         const auto dieId = channelIdKey.first;
     218           29 :         const auto channelId = channelIdKey.second;
     219           29 :         CHK_RET(CcuReleaseChannel(devLogicId_, dieId, channelId));
     220              :     }
     221           29 :     isReleased_ = true;
     222           29 :     return HcclResult::HCCL_SUCCESS;
     223              : }
     224              : 
     225            0 : HcclResult CcuChannelCtxPool::GetCcuChannelCtxById(const std::pair<uint8_t, uint32_t>& key, CcuChannelCtx& ctx)
     226              : {
     227            0 :     auto it = channelJettyInfoMap_.find(key);
     228            0 :     if (it == channelJettyInfoMap_.end()) {
     229            0 :         HCCL_ERROR("[%s]fail, key[%u, %u] not found", __func__, key.first, key.second);
     230            0 :         return HCCL_E_NOT_FOUND;
     231              :     }
     232            0 :     ctx = it->second;
     233            0 :     return HCCL_SUCCESS;
     234              : }
     235              : } // namespace hcomm
        

Generated by: LCOV version 2.0-1