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