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