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_kernel_mgr.h"
12 :
13 : #include <acl/acl.h>
14 :
15 : #include "hccl_common.h"
16 : #include "exception_handler.h"
17 : #include "adapter_rts.h"
18 : #include "ccu_assist_v1.h"
19 : #include "dev_buffer.h"
20 : #include "ccu_ins_generator_v1.h"
21 : #include "ccu_ins_generator_v2.h"
22 : #include "ccu_dev_mgr_imp.h"
23 :
24 : #include "ccu_rep_base_v1.h"
25 : #include "ccu_rep_block_v1.h"
26 : #include "ccu_rep_type_v1.h"
27 :
28 : #include "hcomm_adapter_hccp.h"
29 :
30 : #include "ccu_log.h"
31 : #include "ccu_kernel_func.h"
32 :
33 : namespace hcomm {
34 :
35 0 : HcclResult GetHcclVersionForCcuKernelMgr(int& hcclVersion)
36 : {
37 0 : char hcclPkgName[] = "hccl";
38 0 : aclError aclRet = aclsysGetVersionNum(hcclPkgName, &hcclVersion);
39 0 : CHK_PRT_RET(
40 : aclRet != ACL_SUCCESS,
41 : HCCL_ERROR("[GetHcclVersionForCcuKernelMgr] aclsysGetVersionNum failed, aclRet[%d].", aclRet), HCCL_E_INTERNAL);
42 0 : HCCL_RUN_INFO("[GetHcclVersionForCcuKernelMgr] hccl version is %d.", hcclVersion);
43 0 : return HCCL_SUCCESS;
44 : }
45 :
46 : constexpr int MAX_HCCL_VERSION_USING_CCU_RES_STATIC_ALLOC = 90100000;
47 :
48 : static uint32_t ComputeKernelInstrRegionSize(CcuKernel* kernel, const int32_t devLogicId);
49 :
50 198 : CcuKernelMgr::~CcuKernelMgr()
51 : {
52 198 : if (!initializedFlag_) {
53 198 : return;
54 : }
55 :
56 0 : if (instructionLoadDevMem_) {
57 0 : HCCL_RUN_INFO(
58 : "[CcuKernelMgr][~CcuKernelMgr]: deviceLogicId[%d], free addr[%p]", devLogicId_, instructionLoadDevMem_);
59 0 : (void)hrtFree(instructionLoadDevMem_);
60 0 : instructionLoadDevMem_ = nullptr;
61 : }
62 :
63 0 : (void)Deinit();
64 1188 : }
65 :
66 2889 : CcuKernelMgr& CcuKernelMgr::GetInstance(const int32_t deviceLogicId)
67 : {
68 3087 : static CcuKernelMgr kernelManager[MAX_MODULE_DEVICE_NUM + 1];
69 :
70 2889 : int32_t devLogicId = deviceLogicId;
71 2889 : if (devLogicId < 0 || static_cast<uint32_t>(devLogicId) >= MAX_MODULE_DEVICE_NUM) {
72 0 : HCCL_WARNING(
73 : "[CcuKernelMgr][%s] use the backup device, devLogicId[%d] should be "
74 : "less than %u.",
75 : __func__, devLogicId, MAX_MODULE_DEVICE_NUM);
76 0 : devLogicId = MAX_MODULE_DEVICE_NUM; // 使用备份设备
77 : }
78 :
79 2889 : kernelManager[devLogicId].devLogicId_ = devLogicId;
80 2889 : return kernelManager[devLogicId];
81 : }
82 :
83 94 : HcclResult CcuKernelMgr::Init()
84 : {
85 94 : std::unique_lock<std::mutex> lock(kernelMapMutex_);
86 94 : if (initializedFlag_) {
87 0 : return HcclResult::HCCL_SUCCESS;
88 : }
89 :
90 282 : for (uint8_t dieId = 0; dieId < CCU_MAX_IODIE_NUM; dieId++) {
91 188 : bool enableFlag = false;
92 188 : CHK_RET(static_cast<HcclResult>(CcuGetDieEnableInfo(devLogicId_, dieId, enableFlag)));
93 188 : if (!enableFlag) {
94 0 : continue;
95 : }
96 :
97 188 : CHK_RET(InstantiationTranslator(dieId));
98 : }
99 :
100 94 : initializedFlag_ = true;
101 94 : kernelMap_.clear();
102 :
103 94 : CHK_RET(CcuDevMgrImp::GetCcuVersion(devLogicId_, ccuVersion_));
104 94 : HCCL_INFO("[CcuKernelMgr] Get CcuVersion[%d](0: CcuV1, 1: CcuV2, 2: Invalid)", ccuVersion_);
105 94 : if (ccuVersion_ == CcuVersion::INVALID) {
106 0 : HCCL_ERROR("[CcuKernelMgr][%s] Invalid chip type, abort Init.", __func__);
107 0 : return HcclResult::HCCL_E_INTERNAL;
108 : }
109 :
110 94 : if (ccuVersion_ == CcuVersion::CCU_V2) {
111 17 : HCCL_INFO("[CcuKernelMgr] Init CcuInsGeneratorV2");
112 17 : insGenePtr = std::make_shared<CcuRep::CcuInsGeneratorV2>();
113 17 : return HcclResult::HCCL_SUCCESS;
114 : }
115 :
116 77 : HCCL_INFO("[CcuKernelMgr] Init CcuInsGeneratorV1");
117 77 : insGenePtr = std::make_shared<CcuRep::CcuInsGeneratorV1>();
118 77 : return HcclResult::HCCL_SUCCESS;
119 94 : }
120 :
121 175 : HcclResult CcuKernelMgr::Deinit()
122 : {
123 : // 不需要主动释放CCU指令空间等资源,因为设备管理与kernelMgr都为静态,生命周期一致
124 175 : std::unique_lock<std::mutex> lock(kernelMapMutex_);
125 175 : translatorResPack.handles.clear();
126 175 : initializedFlag_ = false;
127 175 : kernelMap_.clear();
128 175 : translators.clear();
129 175 : referenceMgrs.clear();
130 175 : return HcclResult::HCCL_SUCCESS;
131 175 : }
132 :
133 57 : CcuResult CcuKernelMgr::Register(
134 : CcuResPack& resPack, const uint32_t dieId, const char* kernelFuncName, const void* kernelFunc,
135 : const void** kernelArgs, const uint32_t argNum, CcuInstance* ccuIns, CcuKernelHandle& kernelHandle)
136 : {
137 : // 允许kernelFuncName为空,此时传递默认名称
138 57 : CCU_CHK_PTR_NULL(kernelFunc);
139 :
140 : // 当前argNum仅允许 0 或 1
141 57 : if (argNum > 1) {
142 0 : HCCL_ERROR("[%s] failed, argNum[%u] now only support 0 or 1.", __func__, argNum);
143 0 : return CcuResult::CCU_E_PARA;
144 : }
145 :
146 : // 注意处理时序,需要先重置后处理rep
147 57 : std::unique_lock<std::mutex> lock(kernelMapMutex_);
148 57 : CCU_CHK_RET(BuildKernel(dieId, kernelFuncName, kernelFunc, kernelArgs, argNum, ccuIns));
149 :
150 46 : CcuResult ret = AllocRes(resPack);
151 46 : if (ret != CcuResult::CCU_SUCCESS) {
152 0 : HCCL_WARNING("[%s] AllocRes failed, maybe resource not enough, please check ret[%d]", __func__, ret);
153 0 : return ret;
154 : }
155 :
156 46 : kernelId_++;
157 46 : kernelMap_[kernelId_] = std::move(currKernel_);
158 :
159 46 : kernelHandle = kernelId_;
160 46 : return CcuResult::CCU_SUCCESS;
161 57 : }
162 :
163 72 : CcuResult CcuKernelMgr::BuildKernel(
164 : const uint32_t dieId, const char* kernelFuncName, const void* kernelFunc, const void** kernelArgs,
165 : const uint32_t argNum, CcuInstance* ccuIns)
166 : {
167 72 : currKernel_ = std::make_unique<CcuKernel>(); // 重置待构建kernel
168 : // 执行算法流程时将资源占用临时记录在 die 0,后续确定实际 die 并迁移资源
169 72 : currKernel_->SetDieId(0);
170 72 : CCU_CHK_RET(currKernel_->SetupProfilingInfo(kernelFuncName));
171 :
172 : // 初始化翻译器(需在执行kernel func前设置,因为func执行时会创建rep对象)
173 72 : currKernel_->SetInsGenerater(insGenePtr.get());
174 72 : currKernel_->SetCcuVersion(ccuVersion_);
175 :
176 72 : if (argNum == 0) {
177 8 : auto ccuKernelFunc = reinterpret_cast<CcuKernelFuncNoArg>(kernelFunc);
178 8 : CCU_CHK_RET(ccuKernelFunc()); // 执行算法流程,生成rep和计算资源占用
179 : } else {
180 64 : CCU_CHK_PTR_NULL(kernelArgs);
181 64 : const void* kernelArg = kernelArgs[0];
182 64 : CCU_CHK_PTR_NULL(kernelArg);
183 64 : const auto ccuKernelArg = const_cast<CcuKernelArg>(kernelArg);
184 64 : auto ccuKernelFunc = reinterpret_cast<CcuKernelFuncOneArg>(kernelFunc);
185 64 : CCU_CHK_RET(ccuKernelFunc(ccuKernelArg)); // 执行算法流程,生成rep和计算资源占用
186 : }
187 :
188 59 : currKernel_->FlushClosablePendingIfs(); // 处理未闭合的if
189 59 : if (ccuIns != nullptr && ccuIns->IsFixedResNum()) {
190 : // 按固定资源数量创建的 ccu instance,外部 dieId 始终为 0,从 channel 获取实际 dieId
191 1 : CCU_CHK_RET(currKernel_->ApplyDieFromChannels());
192 : } else {
193 : // 按需创建的 ccu instance,校验所有 channel 使用相同的 die,然后将资源占用从 die 0 迁移到指定 die
194 58 : CCU_CHK_RET(currKernel_->ValidateAndApplyDie(dieId));
195 : }
196 56 : CCU_CHK_RET(PrepareConstValueResources()); // 记录翻译过程所需常量并申请对应资源
197 56 : return CcuResult::CCU_SUCCESS;
198 : }
199 :
200 15 : CcuResult CcuKernelMgr::GetKernelResourceRequest(
201 : const uint32_t dieId, const char* kernelFuncName, const void* kernelFunc, const void** kernelArgs,
202 : const uint32_t argNum, CcuResReq& resReq, uint32_t& instrCount)
203 : {
204 15 : CCU_CHK_PTR_NULL(kernelFunc);
205 15 : if (argNum > 1) {
206 0 : HCCL_ERROR("[%s] failed, argNum[%u] now only support 0 or 1.", __func__, argNum);
207 0 : return CcuResult::CCU_E_PARA;
208 : }
209 15 : if (argNum == 1) {
210 7 : CCU_CHK_PTR_NULL(kernelArgs);
211 7 : CCU_CHK_PTR_NULL(kernelArgs[0]);
212 : }
213 :
214 15 : std::unique_lock<std::mutex> lock(kernelMapMutex_);
215 15 : currKernel_.reset();
216 : struct CurrentKernelGuard {
217 15 : explicit CurrentKernelGuard(std::unique_ptr<CcuKernel>& kernel) : kernel_(kernel) {}
218 15 : ~CurrentKernelGuard() { kernel_.reset(); }
219 : std::unique_ptr<CcuKernel>& kernel_;
220 15 : } guard(currKernel_);
221 :
222 15 : CCU_CHK_RET(BuildKernel(dieId, kernelFuncName, kernelFunc, kernelArgs, argNum, nullptr));
223 10 : resReq = currKernel_->GetResourceRequest();
224 10 : const uint32_t kernelInstrCount = currKernel_->GetInstrCount();
225 10 : const uint32_t translatorInstrCount = CcuRepTranslator::GetInstrNum(devLogicId_);
226 10 : const uint32_t constInstrCount = currKernel_->GetConstValue2VarMap().size();
227 10 : const uint32_t ckeReserveInstrCount = currKernel_->GetRepNeedToAddLatency() * CcuRep::CCU_CKE_RAW_LATENCY;
228 : // 总数统一走 ComputeKernelInstrRegionSize, 与申请/释放口径保持结构一致; 分项仅用于日志观测
229 10 : instrCount = ComputeKernelInstrRegionSize(currKernel_.get(), devLogicId_);
230 10 : HCCL_INFO(
231 : "[HcommCcuKernelQueryResReq][%s] resource request instruction count, kernelInstrCount[%u], "
232 : "translatorInstrCount[%u], constInstrCount[%u], ckeReserveInstrCount[%u], totalInstrCount[%u].",
233 : __func__, kernelInstrCount, translatorInstrCount, constInstrCount, ckeReserveInstrCount, instrCount);
234 10 : return CcuResult::CCU_SUCCESS;
235 16 : }
236 :
237 280 : static void DumpResReqInfo(const CcuResReq& totalRes)
238 : {
239 840 : for (uint32_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
240 1120 : if (totalRes.msReq[i] != 0 || totalRes.blockMsReq[i] != 0 || totalRes.ckeReq[i] != 0
241 274 : || totalRes.blockCkeReq[i] != 0 || totalRes.loopEngineReq[i] != 0 || totalRes.blockLoopEngineReq[i] != 0
242 261 : || totalRes.gsaReq[i] != 0 || totalRes.blockGsaReq[i] != 0 || totalRes.xnReq[i] != 0
243 1120 : || totalRes.blockXnReq[i] != 0 || totalRes.missionReq.req[i] != 0) {
244 326 : HCCL_INFO(
245 : "DumpResReqInfo: dieId[%u], msReq[%u], blockMsReq[%u], ckeReq[%u], blockCkeReq[%u], "
246 : "loopEngineReq[%u], blockLoopEngineReq[%u], gsaReq[%u], blockGsaReq[%u], xnReq[%u], blockXnReq[%u], "
247 : "missionReq[%u]",
248 : i, totalRes.msReq[i], totalRes.blockMsReq[i], totalRes.ckeReq[i], totalRes.blockCkeReq[i],
249 : totalRes.loopEngineReq[i], totalRes.blockLoopEngineReq[i], totalRes.gsaReq[i], totalRes.blockGsaReq[i],
250 : totalRes.xnReq[i], totalRes.blockXnReq[i], totalRes.missionReq.req[i]);
251 : }
252 : }
253 280 : }
254 :
255 1012 : inline int32_t GetResTotalNum(const std::vector<ResInfo>& resInfos)
256 : {
257 1012 : int32_t resNum = 0;
258 1530 : for (ResInfo resInfo : resInfos) {
259 518 : resNum += static_cast<int32_t>(resInfo.num);
260 : }
261 1012 : return resNum;
262 : }
263 :
264 46 : static void GetResNumFromResPack(CcuResPack& resPack, CcuResReq& totalRes)
265 : {
266 : // 获取通信域当前所持有的资源
267 46 : const auto& tmpResRepository = resPack.GetCcuResRepo();
268 :
269 : // 合并获取的所持有的资源信息, 按照类型合并资源总和到totalRes的第0个vector中
270 138 : for (u32 i = 0; i < CCU_MAX_IODIE_NUM; i++) {
271 92 : totalRes.msReq[i] += GetResTotalNum(tmpResRepository.ms[i]);
272 92 : totalRes.blockMsReq[i] += GetResTotalNum(tmpResRepository.blockMs[i]);
273 92 : totalRes.ckeReq[i] += GetResTotalNum(tmpResRepository.cke[i]);
274 92 : totalRes.blockCkeReq[i] += GetResTotalNum(tmpResRepository.blockCke[i]);
275 92 : totalRes.loopEngineReq[i] += GetResTotalNum(tmpResRepository.loopEngine[i]);
276 92 : totalRes.blockLoopEngineReq[i] += GetResTotalNum(tmpResRepository.blockLoopEngine[i]);
277 92 : totalRes.gsaReq[i] += GetResTotalNum(tmpResRepository.gsa[i]);
278 92 : totalRes.blockGsaReq[i] += GetResTotalNum(tmpResRepository.blockGsa[i]);
279 92 : totalRes.xnReq[i] += GetResTotalNum(tmpResRepository.xn[i]);
280 92 : totalRes.blockXnReq[i] += GetResTotalNum(tmpResRepository.blockXn[i]);
281 92 : totalRes.missionReq.req[i] += GetResTotalNum(tmpResRepository.mission.mission[i]);
282 : }
283 :
284 46 : DumpResReqInfo(totalRes);
285 46 : HCCL_INFO("GetResPackTotalResNum:dumpInfos success.");
286 46 : }
287 :
288 1012 : inline uint32_t GetReqResNum(const uint32_t reqRes, const uint32_t totalRes)
289 : {
290 1012 : return ((reqRes > totalRes) ? (reqRes - totalRes) : 0);
291 : }
292 :
293 46 : static bool CheckResIfAvailable(const CcuResReq& totalRes, const CcuResReq& resReq)
294 : {
295 46 : DumpResReqInfo(resReq);
296 :
297 46 : CcuResReq needResReq{};
298 : // todo: 优化为遍历数组
299 138 : for (u32 i = 0; i < CCU_MAX_IODIE_NUM; i++) {
300 92 : needResReq.msReq[i] = GetReqResNum(resReq.msReq[i], totalRes.msReq[i]);
301 92 : needResReq.blockMsReq[i] = GetReqResNum(resReq.blockMsReq[i], totalRes.blockMsReq[i]);
302 92 : needResReq.ckeReq[i] = GetReqResNum(resReq.ckeReq[i], totalRes.ckeReq[i]);
303 92 : needResReq.blockCkeReq[i] = GetReqResNum(resReq.blockCkeReq[i], totalRes.blockCkeReq[i]);
304 92 : needResReq.loopEngineReq[i] = GetReqResNum(resReq.loopEngineReq[i], totalRes.loopEngineReq[i]);
305 92 : needResReq.blockLoopEngineReq[i] = GetReqResNum(resReq.blockLoopEngineReq[i], totalRes.blockLoopEngineReq[i]);
306 92 : needResReq.gsaReq[i] = GetReqResNum(resReq.gsaReq[i], totalRes.gsaReq[i]);
307 92 : needResReq.blockGsaReq[i] = GetReqResNum(resReq.blockGsaReq[i], totalRes.blockGsaReq[i]);
308 92 : needResReq.xnReq[i] = GetReqResNum(resReq.xnReq[i], totalRes.xnReq[i]);
309 92 : needResReq.blockXnReq[i] = GetReqResNum(resReq.blockXnReq[i], totalRes.blockXnReq[i]);
310 92 : needResReq.missionReq.req[i] = GetReqResNum(resReq.missionReq.req[i], totalRes.missionReq.req[i]);
311 :
312 92 : if (needResReq.missionReq.req[i] > 0) {
313 0 : needResReq.missionReq.reqType = resReq.missionReq.reqType;
314 : }
315 :
316 184 : if (needResReq.msReq[i] != 0 || needResReq.blockMsReq[i] != 0 || needResReq.ckeReq[i] != 0
317 92 : || needResReq.blockCkeReq[i] != 0 || needResReq.loopEngineReq[i] != 0
318 92 : || needResReq.blockLoopEngineReq[i] != 0 || needResReq.gsaReq[i] != 0 || needResReq.blockGsaReq[i] != 0
319 184 : || needResReq.xnReq[i] != 0 || needResReq.blockXnReq[i] != 0 || needResReq.missionReq.req[i] != 0) {
320 0 : HCCL_WARNING(
321 : "[CcuKernelMgr][%s] dieId[%u] not enough, msReq[%u] blockMsReq[%u] ckeReq[%u]"
322 : "blockCkeReq[%u] loopEngineReq[%u] blockLoopEngineReq[%u] gsaReq[%u] blockGsaReq[%u] xnReq[%u]"
323 : "blockXnReq[%u] missionReq[%u].",
324 : __func__, i, needResReq.msReq[i], needResReq.blockMsReq[i], needResReq.ckeReq[i],
325 : needResReq.blockCkeReq[i], needResReq.loopEngineReq[i], needResReq.blockLoopEngineReq[i],
326 : needResReq.gsaReq[i], needResReq.blockGsaReq[i], needResReq.xnReq[i], needResReq.blockXnReq[i],
327 : needResReq.missionReq.req[i]);
328 0 : return false;
329 : }
330 : }
331 :
332 46 : return true;
333 : }
334 :
335 1012 : static void MoveResInfo(std::vector<ResInfo>& dest, std::vector<ResInfo>& source, const uint32_t resNum)
336 : {
337 : // Register 前序流程已检查资源不足场景
338 1012 : if (resNum == 0) {
339 888 : return;
340 : }
341 :
342 124 : dest.clear();
343 124 : auto iter = source.begin();
344 124 : uint32_t remain = resNum;
345 248 : while (remain > 0 && iter != source.end()) {
346 124 : auto& srcBlock = *iter;
347 124 : const uint32_t take = std::min(remain, srcBlock.num);
348 124 : dest.emplace_back(srcBlock.startId, take);
349 :
350 124 : if (take == srcBlock.num) {
351 : // 完全用掉这个资源,source中移除
352 0 : iter = source.erase(iter);
353 : } else {
354 : // 只用了部分,更新source中的资源
355 124 : srcBlock.startId += take;
356 124 : srcBlock.num -= take;
357 : }
358 :
359 124 : remain -= take; // 更新剩余需要的资源数量
360 : }
361 : }
362 :
363 46 : static void LoadRes(std::unique_ptr<CcuKernel>& kernel, CcuResPack& resPack)
364 : {
365 46 : const CcuResReq& resReq = kernel->GetResourceRequest();
366 46 : CcuResRepository& totalResRepo = resPack.GetCcuResRepo();
367 1058 : CcuResRepository kernelResRepo{};
368 :
369 138 : for (uint8_t i = 0; i < CCU_MAX_IODIE_NUM; i++) { // todo: 建议改成dieId
370 92 : MoveResInfo(kernelResRepo.loopEngine[i], totalResRepo.loopEngine[i], resReq.loopEngineReq[i]);
371 92 : MoveResInfo(kernelResRepo.blockLoopEngine[i], totalResRepo.blockLoopEngine[i], resReq.blockLoopEngineReq[i]);
372 92 : MoveResInfo(kernelResRepo.ms[i], totalResRepo.ms[i], resReq.msReq[i]);
373 92 : MoveResInfo(kernelResRepo.blockMs[i], totalResRepo.blockMs[i], resReq.blockMsReq[i]);
374 92 : MoveResInfo(kernelResRepo.cke[i], totalResRepo.cke[i], resReq.ckeReq[i]);
375 92 : MoveResInfo(kernelResRepo.blockCke[i], totalResRepo.blockCke[i], resReq.blockCkeReq[i]);
376 92 : MoveResInfo(kernelResRepo.blockXn[i], totalResRepo.blockXn[i], resReq.blockXnReq[i]);
377 92 : MoveResInfo(kernelResRepo.xn[i], totalResRepo.xn[i], resReq.xnReq[i]);
378 92 : MoveResInfo(kernelResRepo.gsa[i], totalResRepo.gsa[i], resReq.gsaReq[i]);
379 92 : MoveResInfo(kernelResRepo.blockGsa[i], totalResRepo.blockGsa[i], resReq.blockGsaReq[i]);
380 92 : MoveResInfo(kernelResRepo.mission.mission[i], totalResRepo.mission.mission[i], resReq.missionReq.req[i]);
381 : }
382 :
383 46 : kernel->SetResRepository(kernelResRepo);
384 46 : }
385 :
386 : // 指令空间区域大小的唯一计算入口:
387 : // 裸指令数 (rep InstrCount 累加) + 翻译器结构指令 (GetInstrNum) + 常量赋值指令
388 : // + 每个会翻译出 waitcke/clearcke 的 wait 类 rep 预留 CCU_CKE_RAW_LATENCY 条 NOP 空间.
389 : // 后端优化 cke-only 档只会为 CKE 写后读补 NOP, 每个 wait 类 rep 最多补 (latency-1) 条,
390 : // 故此预留可从构造上保证优化后指令数不超过申请区. 申请 / 查询 / 释放三处必须走本函数,
391 : // 保证口径一致 (尤其申请与释放必须完全相等).
392 147 : static uint32_t ComputeKernelInstrRegionSize(CcuKernel* kernel, const int32_t devLogicId)
393 : {
394 147 : return kernel->GetInstrCount() + CcuRep::CcuRepTranslator::GetInstrNum(devLogicId)
395 147 : + static_cast<uint32_t>(kernel->GetConstValue2VarMap().size())
396 147 : + kernel->GetRepNeedToAddLatency() * CcuRep::CCU_CKE_RAW_LATENCY;
397 : }
398 :
399 46 : static CcuResult AllocInstrRes(std::unique_ptr<CcuKernel>& kernel, const int32_t devLogicId)
400 : {
401 46 : const uint32_t instrCount = ComputeKernelInstrRegionSize(kernel.get(), devLogicId);
402 46 : const uint32_t dieId = kernel->GetDieId();
403 46 : ResInfo insInfo(0, 0);
404 46 : CCU_CHK_RET(CcuDevMgrImp::AllocIns(devLogicId, dieId, instrCount, insInfo));
405 46 : HCCL_INFO(
406 : "[CcuKernelMgr][%s]: devLogicId[%d], dieId[%u], startId[%u], count[%u]", __func__, devLogicId, dieId,
407 : insInfo.startId, insInfo.num);
408 46 : kernel->SetInstrId(insInfo.startId);
409 :
410 46 : return CcuResult::CCU_SUCCESS;
411 : }
412 :
413 56 : CcuResult CcuKernelMgr::PrepareConstValueResources()
414 : {
415 : // insGenerator统计rep中常量,并填写当前kernel的常量表,当前只有A6有对应处理,A5没有常量处理需求
416 56 : CCU_CHK_PTR_NULL(currKernel_);
417 56 : const auto& repVec = currKernel_->GetRepSequence();
418 :
419 56 : const auto& translator = translators[currKernel_->GetDieId()][0];
420 56 : CCU_CHK_PTR_NULL(translator);
421 56 : const auto& transDep = translator->GetTransDep(); // 此时未分配missionid,取0对应的transDep读取常量
422 56 : CCU_CHK_PTR_NULL(insGenePtr);
423 1166 : for (uint32_t index = 0; index < repVec.size(); index++) {
424 1110 : const auto& curRepType = repVec[index]->Type();
425 1110 : CcuRep::CcuRepBase* curRepPtr = repVec[index].get();
426 1110 : CCU_CHK_PTR_NULL(curRepPtr);
427 1110 : HCCL_DEBUG("Current rep[%d] ptr[%p] repType[%d]", index, curRepPtr, curRepType);
428 :
429 : // 遍历每个rep,包括repBlock中的每个rep,将常量资源需求记录在currkernel中
430 1110 : CCU_CHK_RET(insGenePtr->PrepareConstValue(curRepPtr, transDep, currKernel_.get()));
431 1110 : if (curRepType == CcuRep::CcuRepType::BLOCK || curRepType == CcuRep::CcuRepType::FUNC_BLOCK
432 1106 : || curRepType == CcuRep::CcuRepType::LOOP_BLOCK) {
433 47 : CcuRep::CcuRepBlock* curRepBlockPtr = static_cast<CcuRep::CcuRepBlock*>(curRepPtr);
434 47 : CCU_CHK_PTR_NULL(curRepBlockPtr);
435 125 : for (const auto& repInBlock : curRepBlockPtr->GetReps()) {
436 78 : CCU_CHK_RET(insGenePtr->PrepareConstValue(repInBlock.get(), transDep, currKernel_.get()));
437 : }
438 : }
439 : }
440 56 : return CcuResult::CCU_SUCCESS;
441 : }
442 :
443 46 : CcuResult CcuKernelMgr::AllocRes(CcuResPack& resPack)
444 : {
445 46 : CcuResReq leftRes{};
446 46 : GetResNumFromResPack(resPack, leftRes);
447 :
448 46 : const CcuResReq& resReq = currKernel_->GetResourceRequest();
449 : // todo: 需要整改,传递资源不足的信息
450 46 : if (!CheckResIfAvailable(leftRes, resReq)) {
451 0 : HCCL_WARNING("[CcuKernelMgr][%s] resource is not enough.", __func__);
452 0 : return CcuResult::CCU_E_UNAVAIL;
453 : }
454 :
455 : // 申请指令空间资源
456 46 : CCU_CHK_RET(AllocInstrRes(currKernel_, devLogicId_));
457 :
458 : // 资源从respack转移至kernel
459 46 : LoadRes(currKernel_, resPack);
460 :
461 46 : return CcuResult::CCU_SUCCESS;
462 : }
463 :
464 : template <typename T1, typename T2>
465 : HcclResult
466 5148 : ResetRepResourceTemplate(std::vector<T1>& resource, const std::vector<T2>& repository, const uint32_t startIndex = 0)
467 : {
468 5148 : if (resource.size() > repository.size() - startIndex) {
469 0 : HCCL_ERROR(
470 : "[CcuKernelMgr][ResetRepResourceTemplate]resource size[%u] bigger "
471 : "repository size[%u] typeid[%s]",
472 : resource.size(), repository.size(), typeid(T1).name());
473 0 : return HcclResult::HCCL_E_INTERNAL;
474 : }
475 :
476 47059 : for (uint32_t j = 0; j < resource.size(); j++) {
477 41911 : resource[j].Reset(repository[j + startIndex].startId);
478 : }
479 :
480 5148 : return HcclResult::HCCL_SUCCESS;
481 : }
482 :
483 : static HcclResult
484 234 : ResetRepResourceToResRepository(CcuRepResource& totalRepRes, const CcuResRepository& totalResRepository)
485 : {
486 : // 遍历translatorRepRes, 将每个rep的虚拟资源翻译到实际物理资源上
487 702 : for (u32 i = 0; i < CCU_MAX_IODIE_NUM; i++) {
488 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.ccubufs[i], totalResRepository.ms[i]));
489 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.blockCcubufs[i], totalResRepository.blockMs[i]));
490 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.executor[i], totalResRepository.loopEngine[i]));
491 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.blockExecutor[i], totalResRepository.blockLoopEngine[i]));
492 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.completedEvent[i], totalResRepository.cke[i]));
493 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.blockCompletedEvent[i], totalResRepository.blockCke[i]));
494 468 : CHK_RET(ResetRepResourceTemplate(
495 : totalRepRes.localNotify[i], totalResRepository.blockCke[i],
496 : totalRepRes.blockCompletedEvent[i].size())); // 两类资源都使用cke,需要调整起始分配位置
497 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.address[i], totalResRepository.gsa[i]));
498 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.blockAddress[i], totalResRepository.blockGsa[i]));
499 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.variable[i], totalResRepository.xn[i]));
500 468 : CHK_RET(ResetRepResourceTemplate(totalRepRes.continuousVariable[i], totalResRepository.blockXn[i]));
501 : }
502 234 : return HcclResult::HCCL_SUCCESS;
503 : }
504 :
505 : using DieResInfos = std::array<std::vector<ResInfo>, CCU_MAX_IODIE_NUM>;
506 46 : static HcclResult SaveKernelMissionInfo(CcuKernel* kernel, const DieResInfos& missionId, const int32_t devLogicId)
507 : {
508 46 : const uint32_t dieId = kernel->GetDieId();
509 46 : uint32_t missionKey{0};
510 46 : CHK_RET(CcuDevMgrImp::GetMissionKey(devLogicId, dieId, missionKey));
511 :
512 46 : HCCL_INFO("[CcuKernelMgr][%s] deviceLogicId[%d] dieId[%u]", __func__, devLogicId, dieId);
513 :
514 46 : kernel->SetMissionKey(missionKey);
515 : // 从missionId中获取一个元素并从missionId中删除,当前应只有一个元素,且无需删除
516 46 : if (missionId[dieId].empty()) {
517 0 : HCCL_ERROR("[%s] failed, devLogicId[%d] dieId[%u] do not have missions.", __func__, devLogicId, dieId);
518 0 : return HcclResult::HCCL_E_INTERNAL;
519 : }
520 :
521 46 : kernel->SetMissionId(missionId[dieId].back().startId);
522 46 : return HcclResult::HCCL_SUCCESS;
523 : }
524 :
525 328 : static void DumpResRepositoryInfo(const CcuResRepository& resRepo)
526 : {
527 984 : for (uint32_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
528 1312 : if (resRepo.ms[i].size() != 0 || resRepo.blockMs[i].size() != 0 || resRepo.cke[i].size() != 0
529 274 : || resRepo.blockCke[i].size() != 0 || resRepo.loopEngine[i].size() != 0
530 271 : || resRepo.blockLoopEngine[i].size() != 0 || resRepo.gsa[i].size() != 0 || resRepo.blockGsa[i].size() != 0
531 1312 : || resRepo.xn[i].size() != 0 || resRepo.blockXn[i].size() != 0 || resRepo.mission.mission[i].size() != 0) {
532 422 : HCCL_INFO(
533 : "DumpResRepository: dieId[%u], ms size[%u], blockMs size[%u], cke size[%u], blockCke size[%u], "
534 : "loopEngine size[%u], blockLoopEngine size[%u], gsa size[%u], blockGsa size[%u], xn size[%u], "
535 : "block xn size[%u], mission size[%u]",
536 : i, resRepo.ms[i].size(), resRepo.blockMs[i].size(), resRepo.cke[i].size(), resRepo.blockCke[i].size(),
537 : resRepo.loopEngine[i].size(), resRepo.blockLoopEngine[i].size(), resRepo.gsa[i].size(),
538 : resRepo.blockGsa[i].size(), resRepo.xn[i].size(), resRepo.blockXn[i].size(),
539 : resRepo.mission.mission[i].size());
540 : }
541 : }
542 328 : }
543 :
544 7216 : inline void ExpandResInfo(std::vector<ResInfo>& expendResInfos, const std::vector<ResInfo>& resInfos)
545 : {
546 : // 将resInfo中的资源信息还原为单个资源粒度
547 8135 : for (auto& resInfo : resInfos) {
548 63116 : for (uint32_t id = 0; id < resInfo.num; id++) {
549 62197 : expendResInfos.push_back({(resInfo.startId + id), {1}});
550 : }
551 : }
552 7216 : }
553 :
554 328 : static CcuResult ExpandResRepo(CcuResRepository& totalRes, const CcuResRepository& tmpResRepository)
555 : {
556 : // 合并获取的所持有的资源信息, 按照类型合并资源总和到totalRes中
557 984 : for (u32 i = 0; i < CCU_MAX_IODIE_NUM; i++) {
558 656 : ExpandResInfo(totalRes.ms[i], tmpResRepository.ms[i]);
559 656 : ExpandResInfo(totalRes.blockMs[i], tmpResRepository.blockMs[i]);
560 656 : ExpandResInfo(totalRes.loopEngine[i], tmpResRepository.loopEngine[i]);
561 656 : ExpandResInfo(totalRes.blockLoopEngine[i], tmpResRepository.blockLoopEngine[i]);
562 656 : ExpandResInfo(totalRes.cke[i], tmpResRepository.cke[i]);
563 656 : ExpandResInfo(totalRes.blockCke[i], tmpResRepository.blockCke[i]);
564 656 : ExpandResInfo(totalRes.gsa[i], tmpResRepository.gsa[i]);
565 656 : ExpandResInfo(totalRes.blockGsa[i], tmpResRepository.blockGsa[i]);
566 656 : ExpandResInfo(totalRes.xn[i], tmpResRepository.xn[i]);
567 656 : ExpandResInfo(totalRes.blockXn[i], tmpResRepository.blockXn[i]);
568 656 : ExpandResInfo(totalRes.mission.mission[i], tmpResRepository.mission.mission[i]);
569 : }
570 328 : DumpResRepositoryInfo(totalRes);
571 328 : return CcuResult::CCU_SUCCESS;
572 : }
573 :
574 : template <typename T>
575 46 : static HcclResult MergeExportedResources(
576 : const std::unordered_map<std::string, T>& inputRes, std::unordered_map<std::string, T>& outputRes)
577 : {
578 46 : for (const auto& item : inputRes) {
579 0 : const auto& resTag = item.first;
580 0 : if (outputRes.find(resTag) != outputRes.end()) {
581 0 : HCCL_ERROR(
582 : "[CcuKernelMgr][%s] failed, exported resource tag[%s] is already existed, "
583 : "please check.",
584 : __func__, resTag);
585 0 : return HcclResult::HCCL_E_PARA;
586 : }
587 :
588 0 : outputRes.insert(item);
589 : }
590 :
591 46 : return HcclResult::HCCL_SUCCESS;
592 : }
593 :
594 : template <typename T>
595 46 : static HcclResult ResetImportedResources(
596 : std::unordered_map<std::string, T>& importedRes, const std::unordered_map<std::string, T>& exportedRes)
597 : {
598 46 : for (auto& item : importedRes) {
599 0 : const auto& resTag = item.first;
600 0 : const auto& iter = exportedRes.find(resTag);
601 0 : if (iter == exportedRes.end()) {
602 0 : HCCL_ERROR("[CcuKernelMgr][%s] failed to find exported resources by tag[%s].", __func__, resTag.c_str());
603 0 : return HcclResult::HCCL_E_NOT_FOUND;
604 : }
605 :
606 0 : item.second.Reset(iter->second.Id(), iter->second.DieId());
607 : }
608 :
609 46 : return HcclResult::HCCL_SUCCESS;
610 : }
611 :
612 46 : static HcclResult ProcessInterCtxRes(const std::vector<CcuKernel*>& kernels)
613 : {
614 46 : std::unordered_map<std::string, CcuRep::LocalNotify> totalExportedNotifies;
615 :
616 92 : for (const auto kernel : kernels) {
617 46 : const auto& exportedRes = kernel->GetExportedRes();
618 46 : CHK_RET(MergeExportedResources(exportedRes.sharedNotifies, totalExportedNotifies));
619 : }
620 :
621 92 : for (auto kernel : kernels) {
622 46 : auto& importedRes = kernel->GetImportedRes();
623 46 : CHK_RET(ResetImportedResources(importedRes.sharedNotifies, totalExportedNotifies));
624 : }
625 :
626 46 : return HcclResult::HCCL_SUCCESS;
627 46 : }
628 :
629 46 : static HcclResult TransRepResToPhyRes(const std::vector<CcuKernel*>& kernels, const int32_t devLogicId)
630 : {
631 92 : for (auto kernel : kernels) {
632 46 : const auto& totalResRepository = kernel->GetResRepository();
633 46 : auto& totalRepRes = kernel->GetResource();
634 :
635 : // 将ccu kernel持有的物理资源赋给资源对象
636 1058 : CcuResRepository expandedResRepo{};
637 46 : ExpandResRepo(expandedResRepo, totalResRepository);
638 46 : CHK_RET(ResetRepResourceToResRepository(totalRepRes, expandedResRepo));
639 :
640 46 : CHK_RET(SaveKernelMissionInfo(kernel, totalResRepository.mission.mission, devLogicId));
641 46 : }
642 :
643 46 : CHK_RET(ProcessInterCtxRes(kernels));
644 :
645 46 : return HcclResult::HCCL_SUCCESS;
646 : }
647 :
648 47 : CcuResult CcuKernelMgr::Translate(const std::vector<CcuKernelHandle>& kernelHandles)
649 : {
650 47 : if (kernelHandles.empty()) {
651 1 : HCCL_INFO("[CcuKernelMgr][%s] passed, kernelHandles are empty.", __func__);
652 1 : return CcuResult::CCU_SUCCESS;
653 : }
654 :
655 46 : std::vector<CcuKernel*> kernels{};
656 46 : std::unique_lock<std::mutex> mapLock(kernelMapMutex_);
657 92 : for (const auto kernelHandle : kernelHandles) {
658 46 : const auto& iter = kernelMap_.find(kernelHandle);
659 46 : if (iter == kernelMap_.end()) {
660 0 : HCCL_ERROR(
661 : "[CcuKernelMgr][%s] failed to find kernel by ccu kernel handle[0x%llx].", __func__, kernelHandle);
662 0 : return CcuResult::CCU_E_NOT_FOUND;
663 : }
664 :
665 46 : kernels.push_back(iter->second.get());
666 : }
667 46 : mapLock.unlock();
668 :
669 46 : constexpr bool isFuncBlock = false; // 当前不支持MC2
670 :
671 46 : std::unique_lock<std::mutex> translateLock(translateMutex_);
672 46 : CCU_CHK_RET(TransRepResToPhyRes(kernels, devLogicId_));
673 46 : CCU_CHK_RET(TransRepSequenceToMicrocode(kernels, isFuncBlock));
674 :
675 135 : for (auto& referenceMgrMap : referenceMgrs) {
676 1530 : for (auto& referenceMgr : referenceMgrMap.second) {
677 1440 : referenceMgr.second->ClearRepReference();
678 : }
679 : }
680 45 : return CcuResult::CCU_SUCCESS;
681 46 : }
682 :
683 46 : static HcclResult ReleaseInstrRes(CcuKernel* kernel, const int32_t devLogicId)
684 : {
685 46 : const uint32_t instrCount = ComputeKernelInstrRegionSize(kernel, devLogicId);
686 46 : const ResInfo insInfo{kernel->GetInstrId(), instrCount};
687 46 : const uint8_t dieId = static_cast<uint8_t>(kernel->GetDieId());
688 46 : HCCL_INFO(
689 : "[CcuKernelMgr][%s] devLogicId[%d], dieId[%u], startId[%u], count[%u]", __func__, devLogicId, dieId,
690 : insInfo.startId, insInfo.num);
691 46 : CHK_RET(CcuDevMgrImp::ReleaseIns(devLogicId, dieId, insInfo));
692 :
693 46 : return HcclResult::HCCL_SUCCESS;
694 : }
695 :
696 46 : CcuResult CcuKernelMgr::UnRegister(const CcuKernelHandle kernelHandle)
697 : {
698 46 : std::unique_lock<std::mutex> lock(kernelMapMutex_);
699 :
700 : // 校验kernelMap_中是否存在executorId对应的kernel
701 46 : auto it = kernelMap_.find(kernelHandle);
702 46 : CHK_PRT_RET(
703 : it == kernelMap_.end(),
704 : HCCL_ERROR("[CcuKernelMgr][%s] kernelHandle [%llu] does not exist", __func__, kernelHandle),
705 : CcuResult::CCU_E_NOT_FOUND);
706 :
707 46 : auto kernel = it->second.get();
708 46 : CCU_CHK_RET(ReleaseInstrRes(kernel, devLogicId_));
709 46 : kernelMap_.erase(kernelHandle);
710 46 : return CcuResult::CCU_SUCCESS;
711 46 : }
712 :
713 188 : HcclResult CcuKernelMgr::GetResPackTotalResRepository(
714 : const CcuKernelMgr::CcuTranslatResPack& resPack, CcuResRepository& totalRes) const
715 : {
716 4324 : CcuResRepository tmpResRepository{};
717 : // 获取通信域当前所持有的资源
718 470 : for (CcuResHandle resHandle : resPack.handles) {
719 282 : CHK_RET(CcuDevMgrImp::GetResource(devLogicId_, resHandle, tmpResRepository));
720 282 : ExpandResRepo(totalRes, tmpResRepository);
721 282 : HCCL_INFO("[%s] succeed, deviceLogicId[%d] resHandle[%p].", __func__, devLogicId_, resHandle);
722 : }
723 188 : return HcclResult::HCCL_SUCCESS;
724 188 : }
725 :
726 6016 : static void MergeCcuResReq(CcuResReq& resReqA, const CcuResReq& resReqB)
727 : {
728 : // 合并获取的所持有的资源信息, 按照类型合并资源总和到totalRes的第0个vector中
729 18048 : for (uint32_t i = 0; i < CCU_MAX_IODIE_NUM; i++) {
730 12032 : resReqA.msReq[i] += resReqB.msReq[i];
731 12032 : resReqA.blockMsReq[i] += resReqB.blockMsReq[i];
732 12032 : resReqA.ckeReq[i] += resReqB.ckeReq[i];
733 12032 : resReqA.blockCkeReq[i] += resReqB.blockCkeReq[i];
734 12032 : resReqA.loopEngineReq[i] += resReqB.loopEngineReq[i];
735 12032 : resReqA.blockLoopEngineReq[i] += resReqB.blockLoopEngineReq[i];
736 12032 : resReqA.gsaReq[i] += resReqB.gsaReq[i];
737 12032 : resReqA.blockGsaReq[i] += resReqB.blockGsaReq[i];
738 12032 : resReqA.xnReq[i] += resReqB.xnReq[i];
739 12032 : resReqA.blockXnReq[i] += resReqB.blockXnReq[i];
740 12032 : resReqA.missionReq.req[i] += resReqB.missionReq.req[i];
741 :
742 12032 : if (resReqB.missionReq.req[i] > 0) {
743 0 : resReqA.missionReq.reqType = resReqB.missionReq.reqType;
744 : }
745 : }
746 6016 : }
747 :
748 188 : HcclResult CcuKernelMgr::InstantiationTranslator(const uint16_t dieId)
749 : {
750 188 : if (translators.find(dieId) != translators.end()) {
751 0 : return HcclResult::HCCL_SUCCESS;
752 : }
753 :
754 188 : std::array<uint16_t, CCU_MAX_IODIE_NUM> tmpChannelId{};
755 188 : uint32_t channelId = 0;
756 : // 获取innerDieChannelId
757 188 : auto ret = CcuDevMgrImp::GetLoopChannelId(devLogicId_, dieId, dieId, channelId);
758 188 : CHK_RET(ret);
759 :
760 188 : tmpChannelId[0] = channelId;
761 : // 获取interDieChannelId
762 188 : uint8_t dstDieId = ((dieId == 0) ? 1 : 0);
763 188 : ret = CcuDevMgrImp::GetLoopChannelId(devLogicId_, dieId, dstDieId, channelId);
764 188 : CHK_RET(ret);
765 188 : tmpChannelId[1] = channelId;
766 :
767 188 : uint64_t tokenId = 0;
768 188 : uint64_t tokenValue = 0;
769 188 : ret = CcuDevMgrImp::GetCcuResourceSpaceTokenInfo(devLogicId_, dieId, tokenId, tokenValue);
770 188 : CHK_RET(ret);
771 :
772 188 : std::pair<uint64_t, uint64_t> ccuTokenInfo(tokenId, tokenValue);
773 188 : Hccl::DevBuffer tmpDevMem{1}; // 临时申请device hbm内存用于查询token信息
774 188 : auto hbmTokenInfo = hcomm::CcuRep::GetTokenInfo(tmpDevMem.GetAddr(), 1);
775 :
776 188 : CcuResReq totalResReq{};
777 : // 实例化CcuRepReferenceManager和CcuRepTranslator,并为CcuRepReferenceManager绑定物理资源
778 3196 : for (uint32_t i = 0; i < 16; i++) { // mgr有16个
779 3008 : referenceMgrs[dieId][i] = std::make_shared<hcomm::CcuRep::CcuRepReferenceManager>(dieId);
780 6016 : translators[dieId][i] = std::make_shared<hcomm::CcuRep::CcuRepTranslator>(
781 6016 : devLogicId_, dieId, referenceMgrs[dieId][i], tmpChannelId, ccuTokenInfo, hbmTokenInfo);
782 :
783 : // 统计&合并refManager和translator所有资源REQ
784 3008 : auto refMangerResReq = CcuRep::CcuRepReferenceManager::GetResReq(dieId);
785 3008 : auto transLatorResReq = CcuRep::CcuRepTranslator::GetResReq(devLogicId_, dieId);
786 3008 : MergeCcuResReq(totalResReq, refMangerResReq);
787 3008 : MergeCcuResReq(totalResReq, transLatorResReq);
788 : }
789 188 : DumpResReqInfo(totalResReq);
790 :
791 : // 为refManager和translator申请物理资源
792 : CcuResHandle handle;
793 188 : CHK_RET(CcuDevMgrImp::AllocResHandle(devLogicId_, totalResReq, handle));
794 188 : translatorResPack.handles.push_back(handle);
795 :
796 188 : CcuRepResource translatorRepRes;
797 3196 : for (uint32_t i = 0; i < 16; i++) { // mgr有16个
798 3008 : referenceMgrs[dieId][i]->GetRes(translatorRepRes);
799 3008 : translators[dieId][i]->GetRes(translatorRepRes);
800 : }
801 :
802 188 : CcuResRepository totalResRepository;
803 188 : CHK_RET(GetResPackTotalResRepository(translatorResPack, totalResRepository));
804 : // 将kernel中的rep虚拟资源按类型进行和CCU物理资源映射
805 188 : CHK_RET(ResetRepResourceToResRepository(translatorRepRes, totalResRepository));
806 188 : return HcclResult::HCCL_SUCCESS;
807 188 : }
808 :
809 45 : HcclResult CcuKernelMgr::LoadInstruction(const CcuRep::CcuInstrInfo& instrInfo, const uint32_t dieId)
810 : {
811 45 : const uint64_t instrInfoSize = instrInfo.instrVec.size() * sizeof(hcomm::CcuRep::CcuInstr);
812 :
813 45 : if (!instructionLoadDevMem_) {
814 20 : uint32_t instrNum = 0;
815 20 : CHK_RET(CcuDevMgrImp::GetResSpecsInstructionNum(devLogicId_, 0, instrNum));
816 20 : HCCL_INFO("[CcuKernelMgr]LoadInstruction: deviceLogicId[%d], instrNum[%u]", devLogicId_, instrNum);
817 20 : CHK_RET(hrtMalloc(&instructionLoadDevMem_, instrNum * sizeof(hcomm::CcuRep::CcuInstr)));
818 : }
819 :
820 45 : CHK_RET(hrtMemcpy(
821 : instructionLoadDevMem_, instrInfoSize, instrInfo.instrVec.data(), instrInfoSize,
822 : HcclRtMemcpyKind::HCCL_RT_MEMCPY_KIND_HOST_TO_DEVICE));
823 :
824 45 : uint32_t devPhyId = 0;
825 45 : CHK_RET(hrtGetDevicePhyIdByIndex(static_cast<uint32_t>(devLogicId_), devPhyId));
826 :
827 45 : CustomChannelInfoIn inBuff{};
828 45 : CustomChannelInfoOut outBuff{};
829 :
830 : // 设置操作码和通道数据
831 45 : inBuff.op = CcuOpcodeType::CCU_U_OP_SET_INSTRUCTION;
832 45 : inBuff.offsetStartIdx = instrInfo.startInstrId;
833 45 : inBuff.data.dataInfo.udieIdx = dieId;
834 45 : inBuff.data.dataInfo.dataArraySize = 1;
835 45 : inBuff.data.dataInfo.dataLen = instrInfoSize;
836 :
837 45 : CcuDataTypeUnion tmp{};
838 45 : tmp.insinfo.resourceAddr = reinterpret_cast<uint64_t>(instructionLoadDevMem_);
839 45 : (void)memcpy_s(inBuff.data.dataInfo.dataArray, sizeof(CcuDataTypeUnion), &tmp, sizeof(CcuDataTypeUnion));
840 :
841 45 : auto ret = HccpRaTlvCcuCustomChannel(devLogicId_, static_cast<void*>(&inBuff), static_cast<void*>(&outBuff));
842 45 : if (ret != HCCL_SUCCESS) {
843 0 : HCCL_ERROR(
844 : "[CcuResSpecifications][%s] failed to call ccu driver, "
845 : "devLogicId[%d] devPhyId[%u] dieId[%d] op[%s] ret[%d].",
846 : __func__, devLogicId_, devPhyId, dieId, "SET_INSTRUCTION", ret);
847 0 : return ret;
848 : }
849 :
850 45 : return HcclResult::HCCL_SUCCESS;
851 : }
852 :
853 46 : HcclResult CcuKernelMgr::TransRepSequenceToMicrocode(const std::vector<CcuKernel*>& kernels, bool isFuncBlock)
854 : {
855 91 : for (auto kernel : kernels) {
856 46 : const uint32_t dieId = kernel->GetDieId();
857 46 : const uint32_t missionId = kernel->GetMissionId();
858 :
859 : EXCEPTION_HANDLE_BEGIN
860 47 : const auto& instrInfo = translators[dieId][missionId]->Translate(
861 46 : kernel, kernel->GetRepSequence(), kernel->GetInstrId(), isFuncBlock);
862 :
863 : // 后端优化会插 NOP 改变指令数; 按与申请同一口径校验不越界, 把静默越界变成快速失败.
864 45 : const uint32_t regionSize = ComputeKernelInstrRegionSize(kernel, devLogicId_);
865 45 : CHK_PRT_RET(
866 : instrInfo.instrVec.size() > regionSize,
867 : HCCL_ERROR(
868 : "[CcuKernelMgr][%s] optimized instr count[%zu] exceeds reserved region size[%u], "
869 : "dieId[%u] startId[%u]. Check cke reservation / backend optimizer NOP insertion.",
870 : __func__, instrInfo.instrVec.size(), regionSize, dieId, kernel->GetInstrId()),
871 : HcclResult::HCCL_E_INTERNAL);
872 :
873 45 : CHK_RET(LoadInstruction(instrInfo, dieId));
874 :
875 45 : kernel->SetCcuInstrInfo(instrInfo); // 指令下发成功后可以对kernel进行launch
876 46 : EXCEPTION_HANDLE_END
877 : }
878 :
879 45 : return HcclResult::HCCL_SUCCESS;
880 : }
881 :
882 20 : CcuKernel* CcuKernelMgr::GetKernel(const CcuKernelHandle kernelHandle)
883 : {
884 20 : std::unique_lock<std::mutex> lock(kernelMapMutex_);
885 20 : auto it = kernelMap_.find(kernelHandle);
886 20 : if (it == kernelMap_.end()) {
887 4 : HCCL_ERROR("[CcuKernelMgr][%s] handle[%llx] is not existed.", __func__, kernelHandle);
888 4 : return nullptr;
889 : }
890 :
891 16 : return it->second.get();
892 20 : }
893 :
894 4 : CcuResult CcuKernelMgr::GetCcuKernelInfo(const CcuKernelHandle kernelHandle, CcuKernelInfo& info)
895 : {
896 4 : std::unique_lock<std::mutex> lock(kernelMapMutex_);
897 4 : auto it = kernelMap_.find(kernelHandle);
898 4 : if (it == kernelMap_.end()) {
899 1 : HCCL_ERROR("[CcuKernelMgr][%s] handle[%llx] is not existed.", __func__, kernelHandle);
900 1 : return CcuResult::CCU_E_NOT_FOUND;
901 : }
902 : // 在锁内填充 info,避免裸指针逃逸锁后 kernel 被 UnRegister 导致 use-after-free
903 3 : CCU_CHK_RET(it->second->GetCcuKernelInfo(info));
904 3 : return CcuResult::CCU_SUCCESS;
905 4 : }
906 :
907 2422 : CcuKernel* CcuKernelMgr::GetCurrentKernel() { return currKernel_.get(); }
908 :
909 : } // namespace hcomm
|