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