LCOV - code coverage report
Current view: top level - legacy/ascend950/unified_platform/ccu/ccu_device - ccu_res_batch_allocator.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.6 % 434 380
Test Date: 2026-07-28 12:11:00 Functions: 100.0 % 28 28

            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_res_batch_allocator.h"
      12              : 
      13              : #include <array>
      14              : #include <memory>
      15              : #include <utility>
      16              : #include <iterator>
      17              : #include <algorithm>
      18              : 
      19              : #include "hccl_common_v2.h"
      20              : #include "exception_util.h"
      21              : #include "internal_exception.h"
      22              : 
      23              : #include "ccu_component.h"
      24              : #include "ccu_res_specs.h"
      25              : 
      26              : namespace Hccl {
      27              : 
      28              : constexpr uint32_t REQ_RES_TYPE_NUM = 10;
      29              : constexpr uint32_t BLOCK_RES_TYPE_NUM = 3;
      30              : constexpr uint32_t CONS_RES_TYPE_NUM = 1;
      31              : constexpr uint32_t DISCRETE_RES_TYPE_NUM = 5;
      32              : constexpr uint32_t NON_BLOCK_TYPE_NUM = CONS_RES_TYPE_NUM + DISCRETE_RES_TYPE_NUM;
      33              : constexpr uint32_t CCUA_NUM = 4;
      34              : 
      35           30 : CcuResBatchAllocator &CcuResBatchAllocator::GetInstance(const int32_t deviceLogicId)
      36              : {
      37           96 :     static CcuResBatchAllocator ccuResBatchAllocator[MAX_MODULE_DEVICE_NUM + 1];
      38              : 
      39           30 :     if (deviceLogicId < 0 || static_cast<uint32_t>(deviceLogicId) > MAX_MODULE_DEVICE_NUM) {
      40            0 :         THROW<InvalidParamsException>("[CcuResBatchAllocator][%s] failed, "
      41              :             "devLogicId[%d] should be less than %u.",
      42              :             __func__, deviceLogicId, MAX_MODULE_DEVICE_NUM);
      43              :     }
      44              : 
      45           30 :     ccuResBatchAllocator[deviceLogicId].devLogicId = deviceLogicId;
      46           30 :     return ccuResBatchAllocator[deviceLogicId];
      47              : }
      48              : 
      49            7 : void CcuResBatchAllocator::Init()
      50              : {
      51            7 :     if (preAllocated) {
      52            5 :         return;
      53              :     }
      54              : 
      55            2 :     dieEnableFlags = CcuComponent::GetInstance(devLogicId).GetDieEnableFlags();
      56            2 :     if (!dieEnableFlags[0] && !dieEnableFlags[1]) {
      57            0 :         THROW<InternalException>("[CcuResBatchAllocator][%s] failed, "
      58              :             "CcuResBatchAllocator devLogicId[%d] no usable die.",
      59              :             __func__, devLogicId);
      60              :     }
      61              : 
      62            2 :     auto ret = PreAllocBlockRes();
      63            2 :     if (ret != HcclResult::HCCL_SUCCESS) {
      64            0 :         THROW<InternalException>("[CcuResBatchAllocator][%s] failed, "
      65              :             "deviceLogicId[%d] pre-allocate block resource failed.",
      66              :             __func__, devLogicId);
      67              :     }
      68              : 
      69            2 :     ret = missionMgr.PreAlloc(devLogicId, resStrategys[0].missionNum, dieEnableFlags);
      70            2 :     if (ret != HcclResult::HCCL_SUCCESS) {
      71            0 :         THROW<InternalException>("[CcuResBatchAllocator][%s] failed, "
      72              :             "deviceLogicId[%d] pre-allocate mission block resource failed.",
      73              :             __func__, devLogicId);
      74              :     }
      75              : 
      76            2 :     preAllocated = true;
      77              : }
      78              : 
      79            2 : void CcuResBatchAllocator::Deinit()
      80              : {
      81            2 :     missionMgr.Reset();
      82            6 :     for (uint8_t dieId = 0; dieId < MAX_CCU_IODIE_NUM; dieId++) {
      83            4 :         resBlocks[dieId].clear();
      84              :     }
      85              : 
      86            2 :     handleMap.clear();
      87            2 :     preAllocated = false;
      88            2 : }
      89              : 
      90            4 : uint32_t CcuResBatchAllocator::GetPreAllocatedMaxBlockNum(const uint8_t dieId) const
      91              : {
      92            4 :     CcuResSpecifications &ccuResSepcs = CcuResSpecifications::GetInstance(devLogicId);
      93              : 
      94            4 :     uint32_t loopNum = 0;
      95            4 :     (void)ccuResSepcs.GetLoopEngineNum(dieId, loopNum);
      96            4 :     uint32_t maxLoopBlockNum = loopNum / resStrategys[dieId].loopNum;
      97              : 
      98            4 :     uint32_t msNum = 0;
      99            4 :     (void)ccuResSepcs.GetMsNum(dieId, msNum);
     100            4 :     uint32_t maxMsBlockNum = msNum / resStrategys[dieId].msNum;
     101              : 
     102            4 :     uint32_t ckeNum = 0;
     103            4 :     (void)ccuResSepcs.GetCkeNum(dieId, ckeNum);
     104            4 :     uint32_t maxCkeBlockNum = ckeNum / resStrategys[dieId].ckeNum;
     105              : 
     106            4 :     const uint32_t minBlockNum = std::min({maxLoopBlockNum, maxMsBlockNum, maxCkeBlockNum});
     107           12 :     HCCL_INFO("[CcuResBatchAllocator][%s] batch allocator will alloc [%u] "
     108              :         "blocks ccu resoures, devLogicId[%d] dieId[%u].", __func__,
     109              :         minBlockNum, devLogicId, dieId);
     110            4 :     return minBlockNum;
     111              : }
     112              : 
     113            2 : HcclResult CcuResBatchAllocator::PreAllocBlockRes()
     114              : {
     115            2 :     CcuComponent &ccuComponent = CcuComponent::GetInstance(devLogicId);
     116            2 :     const bool isAX = CcuResSpecifications::GetInstance(devLogicId).GetAXFlag();
     117            6 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     118            4 :         if (!dieEnableFlags[i]) {
     119            0 :             HCCL_WARNING("[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u] is not enable, "
     120              :                 "will not pre-allocate block resource.", __func__, devLogicId, i);
     121            0 :             continue;
     122            0 :         }
     123              : 
     124            4 :         uint32_t blockNum = GetPreAllocatedMaxBlockNum(i);
     125              :         const std::array<std::pair<ResType, uint32_t>, BLOCK_RES_TYPE_NUM> blockResReqs = {
     126            4 :             std::make_pair(ResType::LOOP, blockNum * resStrategys[i].loopNum),
     127            4 :             std::make_pair(ResType::MS, blockNum * resStrategys[i].msNum),
     128            4 :             std::make_pair(ResType::CKE, blockNum * resStrategys[i].ckeNum),
     129           12 :         };
     130              : 
     131           16 :         for (auto &resReq : blockResReqs) {
     132           12 :             const uint32_t reqNum = resReq.second;
     133           12 :             if (reqNum == 0) {
     134            0 :                 HCCL_WARNING("[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u], "
     135              :                     "resType[%s], request num is 0, passed.", __func__,
     136              :                     devLogicId, i, resReq.first.Describe().c_str());
     137            0 :                 continue;
     138            0 :             }
     139              : 
     140           12 :             vector<ResInfo> tempResInfos;
     141           12 :             auto ret = ccuComponent.AllocRes(i, resReq.first, reqNum, true, tempResInfos);
     142           12 :             if (ret != HcclResult::HCCL_SUCCESS) {
     143            0 :                 HCCL_WARNING("[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     144              :                     "failed to pre allocate block type resource, resType[%s], num[%u].",
     145              :                     __func__, devLogicId, i, resReq.first.Describe().c_str(), reqNum);
     146            0 :                 return ret;
     147              :             }
     148              : 
     149           12 :             const bool AxDie0MsFlag = (isAX && i == 0 && resReq.first == ResType::MS);
     150              : 
     151           12 :             vector<BlockInfo> tempBlocks;
     152           12 :             const uint32_t startId = tempResInfos[0].startId;
     153           12 :             if (blockNum == 0) {
     154            0 :                 HCCL_ERROR("[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     155              :                            "the blockNum is zero.", __func__, devLogicId, i);
     156            0 :                 return HcclResult::HCCL_E_INTERNAL;
     157              :             }
     158          156 :             for (uint32_t k = 0; k < blockNum; k++) {
     159          144 :                 BlockInfo blockInfo;
     160          144 :                 blockInfo.id        = k;
     161          144 :                 blockInfo.startId   = startId + k * resReq.second / blockNum;
     162          144 :                 blockInfo.num       = resReq.second / blockNum;
     163              :                 // A+X形态,PCIE连接到IOdie0,导致IOdie0上连接PCIE的CCUA0无法使用,分配MS资源时需要跳过CCUA0
     164              :                 // 给要分给CCUA0的块,设置成已分配过,防止后续分给算法使用
     165          144 :                 blockInfo.allocated = AxDie0MsFlag ? (k % CCUA_NUM == 0) : false;
     166          144 :                 blockInfo.handle    = 0;
     167          144 :                 tempBlocks.emplace_back(blockInfo);
     168              :             }
     169           12 :             resBlocks[i].emplace_back(tempBlocks);
     170           12 :         }
     171              :     }
     172              : 
     173            2 :     return HcclResult::HCCL_SUCCESS;
     174              : }
     175              : 
     176            9 : static bool CheckReqValid(const CcuResReq &req, int32_t devLogicId,
     177              :     std::array<bool, MAX_CCU_IODIE_NUM> &dieEnableFlags)
     178              : {
     179            9 :     bool ifValid = false;
     180           27 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     181              :         const std::array<uint32_t, REQ_RES_TYPE_NUM> reqs = {
     182           18 :             req.loopEngineReq[i],
     183           18 :             req.blockLoopEngineReq[i],
     184           18 :             req.msReq[i],
     185           18 :             req.blockMsReq[i],
     186           18 :             req.ckeReq[i],
     187           18 :             req.blockCkeReq[i],
     188           18 :             req.continuousXnReq[i],
     189           18 :             req.xnReq[i],
     190           18 :             req.gsaReq[i],
     191           18 :             req.missionReq.req[i]
     192           18 :         };
     193              : 
     194           36 :         const bool ifReqEmpty = std::all_of(std::begin(reqs), std::end(reqs),
     195          135 :             [](uint32_t x) { return x == 0; });
     196           18 :         if (!dieEnableFlags[i] && !ifReqEmpty) { // 当前die未使能,但请求资源
     197            0 :             HCCL_WARNING("[CcuResBatchAllocator][%s] failed, dieId[%u] is not enable, "
     198              :                 "but resource request is not empty, devLogicId[%d].",
     199              :                 __func__, i, devLogicId);
     200            0 :             return false;
     201              :         }
     202              : 
     203              :         // 当前die使能,并且请求资源即合法
     204           18 :         if (dieEnableFlags[i] && !ifReqEmpty) {
     205           10 :             ifValid = true;
     206              :         }
     207              :     }
     208              : 
     209            9 :     if (!ifValid) {
     210            3 :         HCCL_WARNING("[CcuResBatchAllocator][%s] all dies resource request is empty, "
     211              :             "devLogicId[%d].", __func__, devLogicId);
     212              :     }
     213              : 
     214            9 :     return ifValid;
     215              : }
     216              : 
     217            9 : HcclResult CcuResBatchAllocator::AllocResHandle(const CcuResReq &resReq,
     218              :     CcuResHandle &resHandle)
     219              : {
     220            9 :     if (!CheckReqValid(resReq, devLogicId, dieEnableFlags)) {
     221            1 :         resHandle = nullptr;
     222            3 :         HCCL_ERROR("[CcuResBatchAllocator][%s] failed, devLogicId[%d], invalid resource "
     223              :             "request, all resource request is empty.", __func__, devLogicId);
     224            1 :         return HcclResult::HCCL_E_PARA;
     225              :     }
     226              : 
     227            8 :     auto resRepoPtr = std::make_unique<CcuResRepository>();
     228            8 :     uintptr_t handleKey  = reinterpret_cast<uintptr_t>(resRepoPtr.get());
     229              :     // 申请分配临时资源
     230            8 :     HcclResult ret = TryAllocResHandle(handleKey, resReq, resRepoPtr);
     231            8 :     if (ret != HcclResult::HCCL_SUCCESS) {
     232            4 :         resHandle = nullptr;
     233           12 :         HCCL_WARNING("[CcuResBatchAllocator][%s] failed, devLogicId[%d], failed to "
     234              :             "allocate resource handle, release temporary resources of this request.",
     235              :             __func__, devLogicId);
     236              : 
     237              :         // 释放申请的临时资源,由CcuResRepo对象对应的智能指针管理
     238            4 :         HcclResult releaseRet = ReleaseResource(resRepoPtr);
     239            4 :         if (releaseRet != HcclResult::HCCL_SUCCESS) {
     240            0 :             HCCL_ERROR("[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     241              :                 "failed to release temporary resources of this request.",
     242              :                 __func__, devLogicId);
     243            0 :             return releaseRet;
     244              :         }
     245              : 
     246           12 :         HCCL_INFO("[CcuResBatchAllocator][%s] devLogicId[%d], "
     247              :             "temporary resources released.", __func__, devLogicId);
     248            4 :         return ret;
     249              :     }
     250              :     // 保存资源信息
     251            4 :     resHandle = reinterpret_cast<CcuResHandle>(resRepoPtr.get());
     252            4 :     handleMap[handleKey] = std::move(resRepoPtr);
     253              : 
     254            4 :     return HcclResult::HCCL_SUCCESS;
     255            8 : }
     256              : 
     257           17 : static HcclResult HandleBlockRes(const uintptr_t handleKey, const uint32_t num,
     258              :     const uint32_t blockSize, std::vector<BlockInfo> &blocks,
     259              :     std::vector<ResInfo> &resInfos)
     260              : {
     261           17 :     if (blockSize == 0) {
     262            0 :         return HcclResult::HCCL_E_INTERNAL;
     263              :     }
     264           17 :     uint32_t blockNum     = 1 + (num - 1) / blockSize;
     265           17 :     uint32_t blockMaxSize = blocks.size();
     266           17 :     uint32_t blockStartId = blockMaxSize;
     267           17 :     uint32_t freeNum      = 0;
     268           17 :     bool     allocatable  = false;
     269          105 :     for (size_t k = 0; k < blockMaxSize; k++) {
     270              :         // 如果当前块已分配,说明当前分配不够,重置分配数量与起始id
     271          102 :         if (blocks[k].allocated) {
     272           15 :             blockStartId = blockMaxSize;
     273           15 :             freeNum = 0;
     274           15 :             continue;
     275              :         }
     276              :         // 如果是首个可分配块,记录起始id
     277           87 :         if (blockStartId == blockMaxSize) {
     278           17 :             blockStartId = k;
     279              :         }
     280              :         // 当前块未分配,更新可分配数量
     281           87 :         freeNum++;
     282              :         // 可分配数量足够则分配成功
     283           87 :         if (freeNum >= blockNum) {
     284           14 :             allocatable = true;
     285           14 :             break;
     286              :         }
     287              :     }
     288           17 :     if (!allocatable) {
     289            3 :         return HcclResult::HCCL_E_UNAVAIL;
     290              :     }
     291              :     // 更新所有新分配的块的信息
     292           87 :     for (size_t k = blockStartId; k < blockStartId + blockNum; k++) {
     293           73 :         blocks[k].handle    = handleKey;
     294           73 :         blocks[k].allocated = true;
     295              :     }
     296           14 :     resInfos.emplace_back(ResInfo{blocks[blockStartId].startId, blockNum * blockSize});
     297           14 :     return HcclResult::HCCL_SUCCESS;
     298              : }
     299              : 
     300            3 : static void DumpBlockResInfo(ResType resType, const std::vector<BlockInfo> &blocks)
     301              : {
     302            9 :     HCCL_INFO("Dump ResType[%s] block resources info: ", resType.Describe().c_str());
     303            3 :     uint32_t blockNum = blocks.size();
     304           31 :     for (size_t k = 0; k < blockNum; k++) {
     305           84 :         HCCL_INFO("Block[id[%u], startId[%u], num[%u], handle(uintptr_t)[%llu], allocated[%d]]",
     306              :             blocks[k].id, blocks[k].startId, blocks[k].num, blocks[k].handle,
     307              :             static_cast<int>(blocks[k].allocated));
     308              :     }
     309            3 : }
     310              : 
     311            8 : HcclResult CcuResBatchAllocator::AllocBlockRes(const uintptr_t handleKey,
     312              :     const CcuResReq &resReq, std::unique_ptr<CcuResRepository> &resRepoPtr)
     313              : {
     314              :     using ResTypeReqNumBlockNumFunc =
     315              :         std::tuple<ResType::Value, uint32_t, uint32_t, std::vector<ResInfo> &>;
     316              : 
     317           22 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     318           15 :         if (!dieEnableFlags[i]) {
     319            0 :             HCCL_WARNING("[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u] is not enable, "
     320              :                 "will not allocate block resource.", __func__, devLogicId, i);
     321            0 :             continue;
     322            0 :         }
     323              : 
     324              :         std::array<ResTypeReqNumBlockNumFunc, BLOCK_RES_TYPE_NUM> blockReqParas = {
     325            0 :             std::make_tuple(ResType::LOOP, resReq.blockLoopEngineReq[i],
     326           15 :                 resStrategys[i].loopNum, std::ref(resRepoPtr->blockLoopEngine[i])),
     327            0 :             std::make_tuple(ResType::MS, resReq.blockMsReq[i],
     328           15 :                 resStrategys[i].msNum, std::ref(resRepoPtr->blockMs[i])),
     329            0 :             std::make_tuple(ResType::CKE, resReq.blockCkeReq[i],
     330           15 :                 resStrategys[i].ckeNum, std::ref(resRepoPtr->blockCke[i]))
     331           45 :         };
     332              :         
     333           58 :         for (uint32_t j = 0; j < BLOCK_RES_TYPE_NUM; j++) {
     334           44 :             const auto &req = blockReqParas[j];
     335           44 :             const uint32_t num = std::get<1>(req);
     336           44 :             if (num == 0) {
     337           33 :                 continue;
     338              :             }
     339              : 
     340           11 :             const ResType resType = std::get<0>(req);
     341           11 :             const uint32_t blockSize = std::get<2>(req);
     342           11 :             auto &blocks = resBlocks[i][j];
     343           11 :             auto &resInfos = std::get<3>(req);
     344           11 :             auto ret = HandleBlockRes(handleKey, num, blockSize, blocks, resInfos);
     345           11 :             if (ret != HcclResult::HCCL_SUCCESS) {
     346            3 :                 HCCL_WARNING("[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     347              :                     "failed to allocate [%s] block resource, remaining block resources are "
     348              :                     "not enough, request num[%u].", __func__, devLogicId, i,
     349              :                     resType.Describe().c_str(), num);
     350            1 :                 DumpBlockResInfo(std::get<0>(req), resBlocks[i][j]);
     351            1 :                 return ret;
     352              :             }
     353              :         }
     354              :     }
     355            7 :     return HcclResult::HCCL_SUCCESS;
     356              : }
     357              : 
     358            9 : HcclResult CcuResBatchAllocator::AllocConsecutiveRes(const CcuResReq &resReq,
     359              :     std::unique_ptr<CcuResRepository> &resRepoPtr) const
     360              : {
     361              :     using ResTypeReqNumResInfoTuple = std::tuple<ResType, uint32_t, std::vector<ResInfo>&>;
     362              :  
     363            9 :     CcuComponent &ccuComponent = CcuComponent::GetInstance(devLogicId);
     364           23 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     365           16 :         if (!dieEnableFlags[i]) {
     366            6 :             HCCL_WARNING("[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u] is not enable, "
     367              :                 "will not allocate consecutive resource.", __func__, devLogicId, i);
     368            2 :             continue;
     369            2 :         }
     370              : 
     371              :         std::array<ResTypeReqNumResInfoTuple, CONS_RES_TYPE_NUM> reqParas = {
     372           14 :             std::make_tuple(ResType::XN, resReq.continuousXnReq[i],
     373           14 :                 std::ref(resRepoPtr->continuousXn[i]))
     374           14 :         };
     375              : 
     376           26 :         for (const auto &req : reqParas) {
     377           14 :             if (std::get<1>(req) == 0) {
     378           12 :                 continue;
     379              :             }
     380              : 
     381            2 :             vector<ResInfo> resInfos;
     382            2 :             auto ret = ccuComponent.AllocRes(i, std::get<0>(req), std::get<1>(req),
     383              :                 true, resInfos);
     384            2 :             if (ret != HcclResult::HCCL_SUCCESS) {
     385            6 :                 HCCL_WARNING("[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     386              :                     "failed to allocate %s resource, num[%u].", __func__, devLogicId, i,
     387              :                     std::get<0>(req).Describe().c_str(), std::get<1>(req));
     388            2 :                 return ret;
     389              :             }
     390            0 :             std::get<2>(req) = resInfos; // 2: resRepotPtr to resource
     391            2 :         }
     392              :     }
     393              : 
     394            7 :     return HcclResult::HCCL_SUCCESS;
     395              : }
     396              : 
     397            6 : HcclResult CcuResBatchAllocator::AllocDiscreteRes(const CcuResReq &resReq,
     398              :     std::unique_ptr<CcuResRepository> &resRepoPtr) const
     399              : {
     400              :     using ResTypeReqNumResInfoTuple = std::tuple<ResType, uint32_t, std::vector<ResInfo>&>;
     401              : 
     402            6 :     CcuComponent &ccuComponent = CcuComponent::GetInstance(devLogicId);
     403           16 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     404           11 :         if (!dieEnableFlags[i]) {
     405            3 :             HCCL_WARNING("[CcuResBatchAllocator][%s] devLogicId[%d] dieId[%u] is not enable, "
     406              :                 "will not allocate discrete resource.", __func__, devLogicId, i);
     407            1 :             continue;
     408            1 :         }
     409              : 
     410              :         std::array<ResTypeReqNumResInfoTuple, DISCRETE_RES_TYPE_NUM> reqParas = {
     411           10 :             std::make_tuple(ResType::LOOP, resReq.loopEngineReq[i],
     412           10 :                 std::ref(resRepoPtr->loopEngine[i])),
     413           10 :             std::make_tuple(ResType::MS, resReq.msReq[i], std::ref(resRepoPtr->ms[i])),
     414           10 :             std::make_tuple(ResType::CKE, resReq.ckeReq[i], std::ref(resRepoPtr->cke[i])),
     415           10 :             std::make_tuple(ResType::XN, resReq.xnReq[i], std::ref(resRepoPtr->xn[i])),
     416           10 :             std::make_tuple(ResType::GSA, resReq.gsaReq[i], std::ref(resRepoPtr->gsa[i]))
     417           50 :         };
     418              : 
     419           55 :         for (const auto &req : reqParas) {
     420           46 :             if (std::get<1>(req) == 0) {
     421           36 :                 continue;
     422              :             }
     423              : 
     424           10 :             vector<ResInfo> resInfos;
     425           10 :             auto ret = ccuComponent.AllocRes(i, std::get<0>(req), std::get<1>(req),
     426              :                 false, resInfos);
     427           10 :             if (ret != HcclResult::HCCL_SUCCESS) {
     428            3 :                 HCCL_WARNING("[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     429              :                     "failed to allocate %s resource, num[%u].", __func__, devLogicId, i,
     430              :                     std::get<0>(req).Describe().c_str(), std::get<1>(req));
     431            1 :                 return ret;
     432              :             }
     433            9 :             std::get<2>(req) = resInfos; // 2: resRepotPtr to resource
     434           10 :         }
     435              :     }
     436              : 
     437            5 :     return HcclResult::HCCL_SUCCESS;
     438              : }
     439              : 
     440           10 : HcclResult CcuResBatchAllocator::TryAllocResHandle(const uintptr_t handleKey,
     441              :     const CcuResReq &resReq, std::unique_ptr<CcuResRepository> &resRepoPtr)
     442              : {
     443           10 :     std::unique_lock<std::mutex> lock(innerMutex);
     444              : 
     445           10 :     HcclResult ret = AllocBlockRes(handleKey, resReq, resRepoPtr);
     446           10 :     if (ret != HcclResult::HCCL_SUCCESS) {
     447            3 :         HCCL_WARNING("[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     448              :             "failed to allocate block type resource.", __func__, devLogicId);
     449            1 :         return ret;
     450              :     }
     451              : 
     452            9 :     ret = missionMgr.Alloc(handleKey, resReq.missionReq, resRepoPtr->mission);
     453            9 :     if (ret != HcclResult::HCCL_SUCCESS) {
     454            6 :         HCCL_WARNING("[CcuResBatchAllocator][%s] devLogicId[%d], failed to allocate "
     455              :             "mission resource, remaining block resources are not enough.",
     456              :             __func__, devLogicId);
     457            2 :         return ret;
     458              :     }
     459              : 
     460            7 :     ret = AllocConsecutiveRes(resReq, resRepoPtr);
     461            7 :     if (ret != HcclResult::HCCL_SUCCESS) {
     462            3 :         HCCL_WARNING("[CcuResBatchAllocator][%s] devLogicId[%d], failed to allocate "
     463              :             "consecutive resource.", __func__, devLogicId);
     464            1 :         return ret;
     465              :     }
     466              : 
     467            6 :     ret = AllocDiscreteRes(resReq, resRepoPtr);
     468            6 :     if (ret != HcclResult::HCCL_SUCCESS) {
     469            3 :         HCCL_WARNING("[CcuResBatchAllocator][%s] devLogicId[%d], failed to allocate "
     470              :             "discrete resource.", __func__, devLogicId);
     471            1 :         return ret;
     472              :     }
     473              : 
     474            5 :     return HcclResult::HCCL_SUCCESS;
     475           10 : }
     476              : 
     477           14 : static void ReleaseBlockRes(const uint32_t blockSize, std::vector<BlockInfo> &blocks,
     478              :     std::vector<ResInfo> &resInfos)
     479              : {
     480           14 :     if (blockSize == 0) {  // 除零保护
     481            0 :         return;
     482              :     }
     483           14 :     uint32_t startId = resInfos[0].startId;
     484           14 :     uint32_t num     = resInfos[0].num;
     485           14 :     uint32_t startBlockId = (startId - blocks[0].startId) / blockSize;
     486           14 :     uint32_t blockNum     = num / blockSize;
     487              : 
     488           87 :     for (uint32_t k = startBlockId; k < startBlockId + blockNum; k++) {
     489           73 :         blocks[k].handle    = 0;
     490           73 :         blocks[k].allocated = false;
     491              :     }
     492           14 :     resInfos.clear();
     493              : }
     494              : 
     495            6 : HcclResult CcuResBatchAllocator::ReleaseResHandle(const CcuResHandle &handle)
     496              : {
     497            6 :     std::unique_lock<std::mutex> lock(innerMutex);
     498              : 
     499            6 :     uintptr_t handleKey = reinterpret_cast<uintptr_t>(handle);
     500            6 :     if (handleMap.find(handleKey) == handleMap.end()) {
     501            6 :         HCCL_ERROR("[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     502              :             "failed to find resource repository, invalid resource handle(uintptr_t)[%llu]",
     503              :             __func__, devLogicId, handleKey);
     504            2 :         return HcclResult::HCCL_E_PARA;
     505              :     }
     506              : 
     507            4 :     std::unique_ptr<CcuResRepository> &resRepoPtr = handleMap[handleKey];
     508              : 
     509            4 :     auto ret = ReleaseResource(resRepoPtr);
     510            4 :     if (ret != HcclResult::HCCL_SUCCESS) {
     511            0 :         HCCL_ERROR("[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     512              :             "failed[%u] to release resource.", __func__, devLogicId, ret);
     513            0 :         return ret;
     514              :     }
     515              : 
     516            4 :     handleMap.erase(handleKey);
     517            4 :     return HcclResult::HCCL_SUCCESS;
     518            6 : }
     519              : 
     520            8 : HcclResult CcuResBatchAllocator::ReleaseResource(std::unique_ptr<CcuResRepository> &resRepoPtr)
     521              : {
     522            8 :     ReleaseBlockResource(resRepoPtr);
     523            8 :     missionMgr.Release(resRepoPtr->mission);
     524            8 :     HcclResult ret = ReleaseNonBlockTypeRes(resRepoPtr);
     525            8 :     if (ret != HcclResult::HCCL_SUCCESS) {
     526            0 :         HCCL_ERROR("[CcuResBatchAllocator][%s] failed, devLogicId[%d], "
     527              :             "failed[%u] to release discrete resource.", __func__, devLogicId, ret);
     528            0 :         return ret;
     529              :     }
     530              : 
     531            8 :     return HcclResult::HCCL_SUCCESS;
     532              : }
     533              : 
     534            8 : void CcuResBatchAllocator::ReleaseBlockResource(std::unique_ptr<CcuResRepository> &resRepoPtr)
     535              : {
     536              :     using BlockSizeResNum = std::pair<uint32_t, std::vector<ResInfo>&>;
     537              : 
     538           24 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     539           16 :         if (!dieEnableFlags[i]) {
     540            0 :             continue;
     541              :         }
     542              : 
     543              :         const std::array<BlockSizeResNum, BLOCK_RES_TYPE_NUM> blockReqParas = {
     544           16 :             std::make_pair(resStrategys[i].loopNum, std::ref(resRepoPtr->blockLoopEngine[i])),
     545           16 :             std::make_pair(resStrategys[i].msNum, std::ref(resRepoPtr->blockMs[i])),
     546           16 :             std::make_pair(resStrategys[i].ckeNum, std::ref(resRepoPtr->blockCke[i]))
     547              :         };
     548              : 
     549           64 :         for (uint32_t j = 0; j < BLOCK_RES_TYPE_NUM; j++) {
     550           48 :             auto req = blockReqParas[j];
     551           48 :             std::vector<ResInfo> &resInfos = req.second;
     552           48 :             if (resInfos.size() == 0) {
     553           38 :                 continue;
     554              :             }
     555              : 
     556           10 :             ReleaseBlockRes(req.first, resBlocks[i][j], resInfos);
     557              :         }
     558              :     }
     559            8 : }
     560              : 
     561              : using ResTypeResInfo = std::pair<ResType, std::vector<ResInfo>*>;
     562            9 : static auto EraseReverse(std::vector<ResInfo>& vec,
     563              :                         std::vector<ResInfo>::reverse_iterator it)
     564              :     -> std::vector<ResInfo>::reverse_iterator
     565              : {
     566              :     return std::vector<ResInfo>::reverse_iterator(
     567           18 :         vec.erase(std::next(it).base())
     568            9 :     );
     569              : }
     570              : 
     571           16 : static HcclResult DoReleaseNonBlockTypeRes(
     572              :     int32_t devLogicId, uint8_t dieId,
     573              :     std::array<ResTypeResInfo, NON_BLOCK_TYPE_NUM>& infoParas)
     574              : {
     575           16 :     CcuComponent& ccuComponent = CcuComponent::GetInstance(devLogicId);
     576              : 
     577          112 :     for (auto& infos : infoParas) {
     578           96 :         const ResType resType = infos.first;
     579           96 :         std::vector<ResInfo>* resInfosPtr = infos.second;
     580           96 :         if (resInfosPtr == nullptr || resInfosPtr->empty()) {
     581           87 :             continue;
     582              :         }
     583            9 :         std::vector<ResInfo>& resInfos = *resInfosPtr;
     584              :         // 倒序删除,减少vector元素移动
     585           18 :         for (auto it = resInfos.rbegin(); it != resInfos.rend(); ) {
     586            9 :             const uint32_t num = it->num;
     587            9 :             if (num == 0) {
     588            0 :                 it = EraseReverse(resInfos, it);
     589            0 :                 continue;
     590              :             }
     591              : 
     592            9 :             const uint32_t startId = it->startId;
     593            9 :             auto ret = ccuComponent.ReleaseRes(dieId, resType, startId, num);
     594            9 :             if (ret != HcclResult::HCCL_SUCCESS) {
     595            0 :                 HCCL_ERROR("[CcuResBatchAllocator][%s] failed, devLogicId[%d] dieId[%u], "
     596              :                     "failed to release %s resource, startId[%u], num[%u].", __func__,
     597              :                     devLogicId, dieId, resType.Describe().c_str(), startId, num);        
     598            0 :                 return ret;
     599              :             }
     600              : 
     601            9 :             it = EraseReverse(resInfos, it);
     602              :         }
     603              :     }
     604           16 :     return HcclResult::HCCL_SUCCESS;
     605              : }
     606              : 
     607            8 : HcclResult CcuResBatchAllocator::ReleaseNonBlockTypeRes(
     608              :     std::unique_ptr<CcuResRepository>& resRepoPtr) const
     609              : {
     610           24 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     611           16 :         if (!dieEnableFlags[i]) {
     612            0 :             continue;
     613              :         }
     614              : 
     615              :         std::array<ResTypeResInfo, NON_BLOCK_TYPE_NUM> infoParas = {{
     616           16 :             {ResType::LOOP, &resRepoPtr->loopEngine[i]},
     617           16 :             {ResType::MS, &resRepoPtr->ms[i]},
     618           16 :             {ResType::CKE, &resRepoPtr->cke[i]},
     619           16 :             {ResType::XN, &resRepoPtr->continuousXn[i]},
     620           16 :             {ResType::XN, &resRepoPtr->xn[i]},
     621           16 :             {ResType::GSA, &resRepoPtr->gsa[i]}
     622           96 :         }};
     623              :     
     624           16 :         CHK_RET(DoReleaseNonBlockTypeRes(devLogicId, i, infoParas));
     625              :     }
     626              : 
     627            8 :     return HcclResult::HCCL_SUCCESS;
     628              : }
     629              : 
     630            4 : HcclResult CcuResBatchAllocator::GetResource(const CcuResHandle &handle,
     631              :     CcuResRepository &ccuResRepo)
     632              : {
     633            4 :     std::unique_lock<std::mutex> lock(innerMutex);
     634              : 
     635            4 :     uintptr_t handleKey = reinterpret_cast<uintptr_t>(handle);
     636            4 :     if (handleMap.find(handleKey) == handleMap.end()) {
     637            6 :         HCCL_ERROR("[CcuResBatchAllocator][%s] devLogicId[%d], failed to find "
     638              :             "resource repository, invalid resource handle(uintptr_t)[%lu]",
     639              :             __func__, devLogicId, handleKey);
     640            2 :         return HcclResult::HCCL_E_PARA;
     641              :     }
     642              : 
     643            2 :     ccuResRepo = *(handleMap[handleKey].get());
     644            2 :     return HcclResult::HCCL_SUCCESS;
     645            4 : }
     646              : 
     647            2 : static HcclResult PreAllocMissionRes(int32_t devLogicId,
     648              :     std::array<bool, MAX_CCU_IODIE_NUM> &dieEnableFlags,
     649              :     std::array<uint32_t, MAX_CCU_IODIE_NUM> &missionNums,
     650              :     std::array<uint32_t, MAX_CCU_IODIE_NUM> &missionStartIds)
     651              : {
     652            2 :     auto &ccuResSepcs = CcuResSpecifications::GetInstance(devLogicId);
     653            2 :     auto &ccuComponent = CcuComponent::GetInstance(devLogicId);
     654            6 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     655            4 :         if (!dieEnableFlags[i]) {
     656            0 :             missionNums[i]     = 0;
     657            0 :             missionStartIds[i] = 0;
     658            0 :             continue;
     659              :         }
     660              : 
     661            4 :         (void)ccuResSepcs.GetMissionNum(i, missionNums[i]);
     662            4 :         vector<ResInfo> tempResInfos;
     663            4 :         auto ret = ccuComponent.AllocRes(i, ResType::MISSION, missionNums[i],
     664              :             true, tempResInfos);
     665            4 :         if (ret != HcclResult::HCCL_SUCCESS) {
     666            0 :             HCCL_WARNING("[CcuMissionMgr][%s] devLogicId[%d] dieId[%u], failed[%u] "
     667              :                 "to pre allocate mission resource, num[%u]", __func__, devLogicId,
     668              :                 i, ret, missionNums[i]);
     669            0 :             return ret;
     670              :         }
     671            4 :         missionStartIds[i] = tempResInfos[0].startId;
     672            4 :     }
     673              : 
     674            2 :     return HcclResult::HCCL_SUCCESS;
     675              : }
     676              : 
     677            2 : HcclResult CcuResBatchAllocator::CcuMissionMgr::PreAlloc(const int32_t devLogicId,
     678              :     const uint32_t blockSize, const std::array<bool, MAX_CCU_IODIE_NUM> dieFlags)
     679              : {
     680            2 :     dieEnableFlags = dieFlags;
     681              :     std::array<uint32_t, MAX_CCU_IODIE_NUM> missionNums;
     682              :     std::array<uint32_t, MAX_CCU_IODIE_NUM> missionStartIds;
     683              : 
     684            2 :     auto ret = PreAllocMissionRes(devLogicId, dieEnableFlags,
     685              :         missionNums, missionStartIds);
     686            2 :     if (ret != HcclResult::HCCL_SUCCESS) {
     687            0 :         return ret;
     688              :     }
     689              : 
     690            2 :     uint32_t missionNum = 0;
     691            2 :     if (dieEnableFlags[0]) {
     692            2 :         missionNum = missionNums[0];
     693            0 :     } else if (dieEnableFlags[1]) {
     694            0 :         missionNum = missionNums[1];
     695              :     }
     696              : 
     697            2 :     if (dieEnableFlags[0] && dieEnableFlags[1]) {
     698            2 :         missionNum = std::min(missionNums[0], missionNums[1]);
     699            6 :         HCCL_WARNING("[CcuMissionMgr][%s] devLogicId[%d] die 0 has %u missions, "
     700              :             "die 1 has %u missions, the allocated size based on the less one.",
     701              :             __func__, devLogicId, missionNums[0], missionNums[1]);
     702              :         
     703              :         // 当前 FUSION_MULTIPLE_DIE 要求多Die ID一致
     704            2 :         if (missionStartIds[0] != missionStartIds[1]) {
     705            0 :             HCCL_WARNING("[CcuMissionMgr][%s] devLogicId[%d] die 0 allocated missions "
     706              :                 "start with id %u, die 1 allocated missions start with id %u, the start "
     707              :                 "id should be same.", __func__, devLogicId, missionStartIds[0],
     708              :                 missionStartIds[1]);
     709            0 :             return HcclResult::HCCL_E_INTERNAL;
     710              :         }
     711              :     }
     712              : 
     713            2 :     stragtegy         = blockSize;
     714            2 :     uint32_t blockNum = missionNum / stragtegy;
     715           18 :     for (uint32_t i = 0; i < blockNum; i++) {
     716           16 :         BlockInfo blockInfo;
     717           16 :         blockInfo.id        = i;
     718           16 :         blockInfo.startId   = missionStartIds[0] + i * stragtegy;
     719           16 :         blockInfo.num       = stragtegy;
     720           16 :         blockInfo.allocated = false;
     721           16 :         blockInfo.handle    = 0;
     722           16 :         blocks.emplace_back(blockInfo);
     723              :     }
     724              : 
     725            2 :     return HcclResult::HCCL_SUCCESS;
     726              : }
     727              : 
     728            7 : static uint32_t Check2DieMissionReqNum(const MissionReq &missionReq,
     729              :     const std::array<bool, MAX_CCU_IODIE_NUM> &dieEnableFlags)
     730              : {
     731            7 :     uint32_t die0ReqNum = missionReq.req[0];
     732            7 :     uint32_t die1ReqNum = missionReq.req[1];
     733              : 
     734            7 :     if (dieEnableFlags[0] && dieEnableFlags[1]) {
     735            7 :         if (die0ReqNum != die1ReqNum) {
     736           18 :             HCCL_WARNING("[CcuMissionMgr][Alloc] die 0 request %u, die 1 request %u, "
     737              :                          "will choose the larger one.", die0ReqNum, die1ReqNum);
     738            6 :             return std::max(die0ReqNum, die1ReqNum);
     739              :         }
     740              : 
     741            1 :         return die0ReqNum;
     742              :     }
     743              : 
     744            0 :     if (dieEnableFlags[0]) {
     745            0 :         return die0ReqNum;
     746              :     }
     747              : 
     748            0 :     if (dieEnableFlags[1]) {
     749            0 :         return die1ReqNum;
     750              :     }
     751              : 
     752            0 :     return 0;
     753              : }
     754              : 
     755            7 : HcclResult CcuResBatchAllocator::CcuMissionMgr::Alloc(const uintptr_t handleKey,
     756              :     const MissionReq &missionReq, MissionResInfo &missionInfos)
     757              : {
     758            7 :     MissionReqType reqType = missionReq.reqType;
     759            7 :     constexpr MissionReqType defaultReqType = MissionReqType::FUSION_MULTIPLE_DIE;
     760            7 :     if (missionReq.reqType != MissionReqType::FUSION_MULTIPLE_DIE) {
     761            0 :         HCCL_WARNING("[CcuMissionMgr][%s] mission reqType[%d], mission resources "
     762              :             "now only support %d.", __func__, reqType, defaultReqType);
     763            0 :         reqType = MissionReqType::FUSION_MULTIPLE_DIE;
     764              :     }
     765              : 
     766            7 :     uint32_t reqNum = Check2DieMissionReqNum(missionReq, dieEnableFlags);
     767            7 :     if (reqNum == 0) {
     768            3 :         HCCL_INFO("[CcuMissionMgr][%s] passed, request mission num is 0, "
     769              :             "will not allocate mission resource.", __func__);
     770            1 :         return HcclResult::HCCL_SUCCESS;
     771              :     }
     772              : 
     773            6 :     vector<ResInfo> resInfos;
     774            6 :     auto ret = HandleBlockRes(handleKey, reqNum, stragtegy, blocks, resInfos);
     775            6 :     if (ret != HcclResult::HCCL_SUCCESS) {
     776            6 :         HCCL_WARNING("[CcuMissionMgr][%s] failed, mission block resources are unavaiable, "
     777              :             "reqNum[%u], stragtegy[%u], reqType[%d].", __func__, reqNum, stragtegy,
     778              :             reqType);
     779            2 :         DumpBlockResInfo(ResType::MISSION, blocks);
     780            2 :         return ret;
     781              :     }
     782            4 :     missionInfos.reqType = reqType;
     783              : 
     784           12 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     785            8 :         if (dieEnableFlags[i]) {
     786            8 :             missionInfos.mission[i] = resInfos;
     787              :         }
     788              :     }
     789              : 
     790            4 :     return HcclResult::HCCL_SUCCESS;
     791            6 : }
     792              : 
     793            8 : void CcuResBatchAllocator::CcuMissionMgr::Release(MissionResInfo &missionInfos)
     794              : {
     795              :     // 目前支持 FUSION_MULTIPLE_DIE 类型,故多die同步释放
     796           16 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     797           12 :         if (dieEnableFlags[i] && missionInfos.mission[i].size() != 0) {
     798            4 :             ReleaseBlockRes(stragtegy, blocks, missionInfos.mission[i]);
     799            4 :             break;
     800              :         }
     801              :     }
     802              : 
     803           24 :     for (uint8_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
     804           16 :         missionInfos.mission[i].clear();
     805              :     }
     806            8 : }
     807              : 
     808            2 : void CcuResBatchAllocator::CcuMissionMgr::Reset()
     809              : {
     810            2 :     blocks.clear();
     811            2 : }
     812              : 
     813              : }; // namespace Hccl
        

Generated by: LCOV version 2.0-1