LCOV - code coverage report
Current view: top level - base_comm/resources/ccu/ccu_device - ccu_res_batch_allocator.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.8 % 444 350
Test Date: 2026-07-28 12:11:00 Functions: 96.4 % 28 27

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

Generated by: LCOV version 2.0-1