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