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

Generated by: LCOV version 2.0-1