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_context_mgr_imp.h"
12 :
13 : #include <unordered_set>
14 :
15 : #include "ccu_ctx_mgr.h"
16 : #include "ccu_res_pack.h"
17 :
18 : #include "hccl_common_v2.h"
19 : #include "orion_adapter_rts.h"
20 : #include "exception_util.h"
21 : #include "ccu_api_exception.h"
22 : #include "orion_adapter_hccp.h"
23 : #include "ccu_assist.h"
24 : #include "dev_buffer.h"
25 : #include "hccp_tlv_hdc_manager.h"
26 :
27 : #ifdef HCCL_ALG_ANALYZER_DAVID
28 : #include "instruction.h"
29 : #endif
30 :
31 :
32 : namespace Hccl {
33 66 : CtxMgrImp::CtxMgrImp()
34 : {
35 66 : }
36 :
37 66 : CtxMgrImp::~CtxMgrImp()
38 : {
39 66 : if (initializedFlag_) {
40 0 : HCCL_INFO("[CtxMgrImp]~CtxMgrImp: deviceLogicId[%d], free addr[%p]", deviceLogicId_, instructionLoadDevMem_);
41 0 : if (instructionLoadDevMem_ != nullptr) {
42 0 : DECTOR_TRY_CATCH("CtxMgrImp", HrtFree(instructionLoadDevMem_));
43 0 : instructionLoadDevMem_ = nullptr;
44 : }
45 0 : ctxGroupMap_.clear();
46 0 : initializedFlag_ = false;
47 : }
48 66 : }
49 :
50 51 : CtxMgrImp &CtxMgrImp::GetInstance(s32 deviceLogicId)
51 : {
52 117 : static CtxMgrImp contextManager[MAX_MODULE_DEVICE_NUM + 1];
53 :
54 51 : if (deviceLogicId < 0 || static_cast<u32>(deviceLogicId) > MAX_MODULE_DEVICE_NUM) {
55 0 : THROW<CcuApiException>("ProcessSharedResources failed deviceLogicId[%d]", deviceLogicId);
56 : }
57 :
58 51 : contextManager[deviceLogicId].deviceLogicId_ = deviceLogicId;
59 51 : return contextManager[deviceLogicId];
60 : }
61 :
62 0 : void CtxMgrImp::Init()
63 : {
64 0 : std::unique_lock<std::mutex> lock(contextMapMutex_);
65 0 : if (initializedFlag_) {
66 0 : return;
67 : }
68 :
69 0 : initializedFlag_ = true;
70 0 : ctxGroupMap_.clear();
71 0 : }
72 :
73 2 : void CtxMgrImp::Deinit()
74 : {
75 2 : std::unique_lock<std::mutex> lock(contextMapMutex_);
76 2 : translatorResPack.handles.clear();
77 2 : translatorResPack.count = 0;
78 2 : initializedFlag_ = false;
79 2 : ctxGroupMap_.clear();
80 2 : translators.clear();
81 2 : referenceMgrs.clear();
82 2 : }
83 :
84 3 : HcclResult CtxMgrImp::AllocRes(CcuCtxGroup &ctxGroup, CcuResPack &resPack)
85 : {
86 3 : std::unique_lock<std::mutex> lock(contextMapMutex_);
87 : // 初始化ctx
88 3 : CtxInit(ctxGroup);
89 :
90 : // 获取ctxGroup使用到的所有dieId
91 3 : std::unordered_set<uint16_t> usedDieId;
92 9 : for (const auto &ctx : ctxGroup.ctxs) {
93 6 : usedDieId.insert(ctx->GetDieId());
94 : }
95 7 : for (auto dieId : usedDieId) {
96 : // 实例化translator,并且为RefManager和translator申请&绑定资源
97 4 : CHK_RET_UNAVAIL(InstantiationTranslator(dieId));
98 : }
99 :
100 : // 获取通信域当前所持有的资源
101 3 : CcuResReq totalRes;
102 3 : CHK_RET(GetResPackTotalResNum(resPack, totalRes));
103 :
104 : // 计算本次编排逻辑所需的资源
105 3 : CcuResReq resReq = GetCtxGroupResReq(ctxGroup);
106 :
107 : // 比较额外需要的资源
108 3 : CHK_RET_UNAVAIL(CompareResAndApplyAsNeeded(totalRes, resReq, resPack));
109 :
110 : // 申请指令空间资源
111 3 : CHK_RET_UNAVAIL(AllocInstrRes(ctxGroup));
112 :
113 : // 保存本次编排的资源信息到Ctx中
114 3 : resPack.count++;
115 3 : SaveResPackToCtx(ctxGroup, resPack);
116 9 : HCCL_INFO("[CtxMgrImp:%s]cur resPack count[%u], resHandle[%u], handle size[%u]", __func__, resPack.count, resPack.GetId(), resPack.handles.size());
117 3 : return HcclResult::HCCL_SUCCESS;
118 3 : }
119 :
120 : // 在外侧调用的UnRegister函数中已加锁,所以当前函数不需要加锁
121 2 : HcclResult CtxMgrImp::ReleaseRes(CcuCtxGroup &ctxGroup) const
122 : {
123 : // 获取本次编排Ctx多对应的资源信息
124 2 : CcuResPack *resPack = ctxGroup.ctxs[0]->GetResPack();
125 2 : CHK_PTR_NULL(resPack);
126 6 : HCCL_INFO("[CtxMgrImp:%s]cur resPack count[%u], resHandle[%u], handle size[%u]", __func__, resPack->count, resPack->GetId(), resPack->handles.size());
127 2 : if(resPack->count > 0) {
128 2 : resPack->count--;
129 : }
130 :
131 : // 释放资源
132 2 : if (resPack->count == 0) {
133 4 : for (CcuResHandle resHandle : resPack->handles) {
134 6 : HCCL_INFO("[CtxMgrImp]ReleaseRes: deviceLogicId[%d], resHandle[%p]", deviceLogicId_, resHandle);
135 2 : CHK_RET(CcuDeviceManager::ReleaseResHandle(deviceLogicId_, resHandle));
136 : }
137 : }
138 :
139 2 : return HcclResult::HCCL_SUCCESS;
140 : }
141 :
142 3 : uint64_t CtxMgrImp::Register(CcuCtxGroup &ctxGroup, bool isFuncBlock)
143 : {
144 : // 多通信域场景需要加锁
145 3 : std::unique_lock<std::mutex> lock(contextMapMutex_);
146 :
147 : // REP编排虚拟资源和实际物理资源映射关联
148 3 : TransRepResToPhyRes(ctxGroup);
149 :
150 : // 构造翻译器,翻译本次编排的ctxGroup
151 3 : TransRepSequenceToMicrocode(ctxGroup, isFuncBlock);
152 :
153 : // 保存本次编排的ctxGroup和exeutorId关联关系
154 3 : executorId_++; // executorId_ = executorId_ > UINT64_MAX ? 0 : executorId_++;
155 3 : ctxGroupMap_[executorId_] = std::move(ctxGroup);
156 : // 清除referenceMgr中保存的引用关系
157 7 : for (auto &referenceMgrMap : referenceMgrs) {
158 68 : for (auto &referenceMgr : referenceMgrMap.second) {
159 64 : referenceMgr.second->ClearRepReference();
160 : }
161 : }
162 3 : return executorId_;
163 3 : }
164 :
165 9 : HcclResult CtxMgrImp::UnRegister(const uint64_t executorId)
166 : {
167 9 : std::unique_lock<std::mutex> lock(contextMapMutex_);
168 :
169 : // 校验ctxGroupMap_中是否存在executorId对应的ctxGroup
170 30 : CHK_PRT_RET(ctxGroupMap_.find(executorId) == ctxGroupMap_.end(),
171 : HCCL_ERROR("[CtxMgrImp][UnRegister]executorId [%llu] is not exist", executorId),
172 : HcclResult::HCCL_E_NOT_FOUND);
173 :
174 : // 释放指令空间
175 2 : ReleaseInstrRes(ctxGroupMap_[executorId]);
176 :
177 : // 尝试释放掉ctx对应的handle
178 2 : CHK_RET(ReleaseRes(ctxGroupMap_[executorId]));
179 :
180 2 : ctxGroupMap_.erase(executorId);
181 :
182 2 : return HcclResult::HCCL_SUCCESS;
183 9 : }
184 :
185 8 : std::vector<std::vector<CcuTaskParam>> CtxMgrImp::GetTaskParam(CcuTaskArg &ccuTaskArg, const uint64_t executorId)
186 : {
187 : // 根据executorId获取ctxGroup
188 8 : std::unique_lock<std::mutex> lock(contextMapMutex_);
189 :
190 : // 校验ctxGroupMap_中是否存在executorId对应的ctxGroup
191 8 : CHK_PRT_RET(ctxGroupMap_.find(executorId) == ctxGroupMap_.end(),
192 : HCCL_ERROR("[CtxMgrImp][GetTaskParam]executorId [%llu] is not exist", executorId),
193 : std::vector<std::vector<CcuTaskParam>>());
194 :
195 : // 获取每个ctx的taskParam信息
196 8 : std::vector<std::vector<CcuTaskParam>> taskParam;
197 12 : for (auto &ctx : ctxGroupMap_[executorId].ctxs) {
198 10 : std::vector<CcuTaskParam> tmp;
199 10 : auto ret = ctx->GeneTaskParam(ccuTaskArg, tmp);
200 4 : if (ret != HcclResult::HCCL_SUCCESS) {
201 0 : THROW<CcuApiException>("GeneTaskParam is failed. ret[%d]", ret);
202 : }
203 4 : taskParam.push_back(tmp);
204 10 : }
205 :
206 2 : return taskParam;
207 14 : }
208 :
209 : // ctx初始化
210 3 : void CtxMgrImp::CtxInit(CcuCtxGroup &ctxGroup) const
211 : {
212 9 : for (auto &ctx : ctxGroup.ctxs) {
213 : // 初始化ctx
214 6 : CHK_PRT_RET_NULL(ctx->Init(), HCCL_ERROR("Init failed"));
215 : }
216 3 : return;
217 : }
218 :
219 : // 申请指令空间资源
220 3 : HcclResult CtxMgrImp::AllocInstrRes(CcuCtxGroup &ctxGroup) const
221 : {
222 9 : for (auto &ctx : ctxGroup.ctxs) {
223 6 : ResInfo insInfo(0, 0);
224 6 : uint32_t instrCount = ctx->GetInstrCount() + CcuRepTranslator::GetInstrNum();
225 6 : CHK_RET_UNAVAIL(CcuDeviceManager::AllocIns(deviceLogicId_, ctx->GetDieId(), instrCount, insInfo));
226 18 : HCCL_INFO("[CtxMgrImp]AllocInstrRes: deviceLogicId[%d], dieId[%u], startId[%u], count[%u]", deviceLogicId_,
227 : ctx->GetDieId(), insInfo.startId, insInfo.num);
228 6 : ctx->SetInstrId(insInfo.startId);
229 : }
230 :
231 3 : return HcclResult::HCCL_SUCCESS;
232 : }
233 :
234 : // 释放指令空间资源
235 2 : HcclResult CtxMgrImp::ReleaseInstrRes(CcuCtxGroup &ctxGroup) const
236 : {
237 6 : for (auto &ctx : ctxGroup.ctxs) {
238 4 : ResInfo insInfo(ctx->GetInstrId(), (ctx->GetInstrCount() + CcuRepTranslator::GetInstrNum()));
239 12 : HCCL_INFO("[CtxMgrImp]ReleaseInstrRes: deviceLogicId[%d], dieId[%u], startId[%u], count[%u]", deviceLogicId_,
240 : ctx->GetDieId(), insInfo.startId, insInfo.num);
241 4 : CHK_RET(CcuDeviceManager::ReleaseIns(deviceLogicId_, ctx->GetDieId(), insInfo));
242 : }
243 :
244 2 : return HcclResult::HCCL_SUCCESS;
245 : }
246 :
247 3 : HcclResult CtxMgrImp::GetResPackTotalResNum(const CcuResPack &resPack, CcuResReq &totalRes) const
248 : {
249 3 : CcuResRepository tmpResRepository;
250 :
251 : // 获取通信域当前所持有的资源
252 3 : for (CcuResHandle resHandle : resPack.handles) {
253 0 : CHK_RET(CcuDeviceManager::GetResource(deviceLogicId_, resHandle, tmpResRepository));
254 :
255 : // 合并获取的所持有的资源信息, 按照类型合并资源总和到totalRes的第0个vector中
256 0 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
257 0 : totalRes.msReq[i] += GetResTotalNum(tmpResRepository.ms[i]);
258 0 : totalRes.blockMsReq[i] += GetResTotalNum(tmpResRepository.blockMs[i]);
259 0 : totalRes.ckeReq[i] += GetResTotalNum(tmpResRepository.cke[i]);
260 0 : totalRes.blockCkeReq[i] += GetResTotalNum(tmpResRepository.blockCke[i]);
261 0 : totalRes.loopEngineReq[i] += GetResTotalNum(tmpResRepository.loopEngine[i]);
262 0 : totalRes.blockLoopEngineReq[i] += GetResTotalNum(tmpResRepository.blockLoopEngine[i]);
263 0 : totalRes.gsaReq[i] += GetResTotalNum(tmpResRepository.gsa[i]);
264 0 : totalRes.xnReq[i] += GetResTotalNum(tmpResRepository.xn[i]);
265 0 : totalRes.continuousXnReq[i] += GetResTotalNum(tmpResRepository.continuousXn[i]);
266 0 : totalRes.missionReq.req[i] += GetResTotalNum(tmpResRepository.mission.mission[i]);
267 : }
268 : }
269 :
270 3 : DumpResReqInfo(totalRes);
271 9 : HCCL_INFO("GetResPackTotalResNum:dumpInfos success.");
272 3 : return HcclResult::HCCL_SUCCESS;
273 3 : }
274 :
275 3 : CcuResReq CtxMgrImp::GetCtxGroupResReq(CcuCtxGroup &ctxGroup) const
276 : {
277 3 : CcuResReq totalResReq;
278 :
279 3 : std::unordered_set<uint16_t> usedDieId; // CCUCtxGroup使用到的所有dieId
280 :
281 : // 获取CCUCtxGroup所有ctx资源诉求
282 9 : for (auto &ctx : ctxGroup.ctxs) {
283 6 : auto dieId = ctx->GetDieId();
284 6 : usedDieId.insert(dieId);
285 :
286 6 : CcuResReq tmpResReq = ctx->GetResourceRequest();
287 6 : MergeCcuResReq(totalResReq, tmpResReq);
288 : }
289 :
290 3 : DumpResReqInfo(totalResReq);
291 9 : HCCL_INFO("CtxGroupResReq:dumpInfos success.");
292 :
293 6 : return totalResReq;
294 3 : }
295 :
296 102 : void CtxMgrImp::MergeCcuResReq(CcuResReq &resReqA, const CcuResReq &resReqB) const
297 : {
298 : // 合并获取的所持有的资源信息, 按照类型合并资源总和到totalRes的第0个vector中
299 306 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
300 204 : resReqA.msReq[i] += resReqB.msReq[i];
301 204 : resReqA.blockMsReq[i] += resReqB.blockMsReq[i];
302 204 : resReqA.ckeReq[i] += resReqB.ckeReq[i];
303 204 : resReqA.blockCkeReq[i] += resReqB.blockCkeReq[i];
304 204 : resReqA.loopEngineReq[i] += resReqB.loopEngineReq[i];
305 204 : resReqA.blockLoopEngineReq[i] += resReqB.blockLoopEngineReq[i];
306 204 : resReqA.gsaReq[i] += resReqB.gsaReq[i];
307 204 : resReqA.xnReq[i] += resReqB.xnReq[i];
308 204 : resReqA.continuousXnReq[i] += resReqB.continuousXnReq[i];
309 204 : resReqA.missionReq.req[i] += resReqB.missionReq.req[i];
310 :
311 204 : if (resReqB.missionReq.req[i] > 0) {
312 6 : resReqA.missionReq.reqType = resReqB.missionReq.reqType;
313 : }
314 : }
315 102 : return;
316 : }
317 :
318 3 : HcclResult CtxMgrImp::CompareResAndApplyAsNeeded(const CcuResReq &totalRes, const CcuResReq &resReq,
319 : CcuResPack &resPack) const
320 : {
321 : // 比较额外需要的资源
322 3 : bool isNeedAlloc = false;
323 3 : CcuResReq needResReq;
324 :
325 9 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
326 6 : needResReq.msReq[i] = GetReqResNum(resReq.msReq[i], totalRes.msReq[i]);
327 6 : needResReq.blockMsReq[i] = GetReqResNum(resReq.blockMsReq[i], totalRes.blockMsReq[i]);
328 6 : needResReq.ckeReq[i] = GetReqResNum(resReq.ckeReq[i], totalRes.ckeReq[i]);
329 6 : needResReq.blockCkeReq[i] = GetReqResNum(resReq.blockCkeReq[i], totalRes.blockCkeReq[i]);
330 6 : needResReq.loopEngineReq[i] = GetReqResNum(resReq.loopEngineReq[i], totalRes.loopEngineReq[i]);
331 6 : needResReq.blockLoopEngineReq[i] = GetReqResNum(resReq.blockLoopEngineReq[i], totalRes.blockLoopEngineReq[i]);
332 6 : needResReq.gsaReq[i] = GetReqResNum(resReq.gsaReq[i], totalRes.gsaReq[i]);
333 6 : needResReq.xnReq[i] = GetReqResNum(resReq.xnReq[i], totalRes.xnReq[i]);
334 6 : needResReq.continuousXnReq[i] = GetReqResNum(resReq.continuousXnReq[i], totalRes.continuousXnReq[i]);
335 6 : needResReq.missionReq.req[i]
336 6 : = GetReqResNum(resReq.missionReq.req[i], totalRes.missionReq.req[i]);
337 :
338 6 : if (needResReq.missionReq.req[i] > 0) {
339 4 : needResReq.missionReq.reqType = resReq.missionReq.reqType;
340 : }
341 :
342 12 : if (needResReq.msReq[i] != 0 || needResReq.blockMsReq[i] != 0 || needResReq.ckeReq[i] != 0 || needResReq.blockCkeReq[i] != 0
343 3 : || needResReq.loopEngineReq[i] != 0 || needResReq.blockLoopEngineReq[i] != 0 || needResReq.gsaReq[i] != 0
344 3 : || needResReq.xnReq[i] != 0 || needResReq.continuousXnReq[i] != 0
345 12 : || needResReq.missionReq.req[i] != 0) {
346 4 : isNeedAlloc = true;
347 : }
348 : }
349 :
350 3 : if (isNeedAlloc) {
351 : // 申请额外资源
352 : CcuResHandle handle;
353 3 : DumpResReqInfo(needResReq);
354 :
355 3 : CHK_RET_UNAVAIL(CcuDeviceManager::AllocResHandle(deviceLogicId_, needResReq, handle));
356 : // 将申请的资源保存到resPack中
357 3 : resPack.handles.push_back(handle);
358 :
359 9 : HCCL_INFO("ApplyAsNeeded:dumpInfos success deviceLogicId[%d] handle[%p].", deviceLogicId_, handle);
360 : }
361 :
362 3 : return HcclResult::HCCL_SUCCESS;
363 : }
364 :
365 3 : void CtxMgrImp::SaveResPackToCtx(CcuCtxGroup &ctxGroup, CcuResPack &resPack) const
366 : {
367 9 : for (auto &ctx : ctxGroup.ctxs) {
368 6 : ctx->SetResPack(resPack);
369 : }
370 3 : return;
371 : }
372 :
373 4 : HcclResult CtxMgrImp::InstantiationTranslator(uint16_t dieId)
374 : {
375 4 : if (translators.find(dieId) != translators.end()) {
376 1 : return HcclResult::HCCL_SUCCESS;
377 : }
378 :
379 3 : std::array<uint16_t, MAX_CCU_IODIE_NUM> tmpChannelId{};
380 3 : uint32_t chaneelId = 0;
381 : // 获取innerDieChannelId
382 3 : auto ret = CcuDeviceManager::GetLoopChannelId(deviceLogicId_, dieId, dieId, chaneelId);
383 3 : if (ret != HcclResult::HCCL_SUCCESS) {
384 0 : THROW<CcuApiException>("Failed to get inner die channel id. deviceLogicId = %d, dieId = %u, ret = %d",
385 : deviceLogicId_, dieId, ret);
386 : }
387 3 : tmpChannelId[0] = chaneelId;
388 : // 获取interDieChannelId
389 3 : uint8_t dstDieId = ((dieId == 0) ? 1 : 0);
390 3 : ret = CcuDeviceManager::GetLoopChannelId(deviceLogicId_, dieId, dstDieId, chaneelId);
391 3 : if (ret != HcclResult::HCCL_SUCCESS) {
392 : // 当前验证环境为单die环境,获取die间ChannelId会失败,打印WARNING日志。
393 0 : HCCL_WARNING("Failed to get inter die channel id. deviceLogicId = %d, srcDieId = %u, dstDieId = %u, ret = %d",
394 : deviceLogicId_, dieId, dstDieId, ret);
395 : }
396 3 : tmpChannelId[1] = chaneelId;
397 : // 获取ccu token信息
398 3 : uint64_t tokenId = 0;
399 3 : uint64_t tokenValue = 0;
400 3 : ret = CcuDeviceManager::GetCcuResourceSpaceTokenInfoForLocal(deviceLogicId_, dieId, tokenId, tokenValue);
401 3 : if (ret != HcclResult::HCCL_SUCCESS) {
402 0 : THROW<CcuApiException>("Failed to get ccu resource space token info. deviceLogicId = %d, dieId = %u, ret = %d",
403 : deviceLogicId_, dieId, ret);
404 : }
405 3 : std::pair<uint64_t, uint64_t> ccuTokenInfo(tokenId, tokenValue);
406 3 : CcuResReq totalResReq;
407 :
408 : // 先获取hbm token,避免创建mission时循环获取
409 3 : DevBuffer tmpDevMem{1};
410 3 : auto hbmTokenInfo = GetTokenInfo(tmpDevMem.GetAddr(), 1);
411 :
412 : // 实例化CcuRepReferenceManager和CcuRepTranslator,并为CcuRepReferenceManager绑定物理资源
413 51 : for (uint32_t i = 0; i < 16; i++) { // mgr有16个
414 48 : referenceMgrs[dieId][i] = std::make_shared<CcuRepReferenceManager>(dieId);
415 96 : translators[dieId][i] = std::make_shared<CcuRepTranslator>(deviceLogicId_, dieId, referenceMgrs[dieId][i],
416 48 : tmpChannelId, ccuTokenInfo, hbmTokenInfo);
417 :
418 : // 统计&合并refManager和translaotr所有资源REQ
419 48 : auto refMangerResReq = CcuRep::CcuRepReferenceManager::GetResReq(dieId);
420 48 : auto transLatorResReq = CcuRep::CcuRepTranslator::GetResReq(dieId);
421 48 : MergeCcuResReq(totalResReq, refMangerResReq);
422 48 : MergeCcuResReq(totalResReq, transLatorResReq);
423 : }
424 :
425 3 : DumpResReqInfo(totalResReq);
426 :
427 : // 为refManager和translaotr申请物理资源
428 : CcuResHandle handle;
429 3 : CHK_RET_UNAVAIL(CcuDeviceManager::AllocResHandle(deviceLogicId_, totalResReq, handle));
430 3 : translatorResPack.handles.push_back(handle);
431 :
432 3 : CcuRepResource translatorRepRes;
433 51 : for (uint32_t i = 0; i < 16; i++) { // mgr有16个
434 48 : referenceMgrs[dieId][i]->GetRes(translatorRepRes);
435 48 : translators[dieId][i]->GetRes(translatorRepRes);
436 : }
437 :
438 3 : CcuResRepository totalResRepository;
439 3 : CHK_RET(GetResPackTotalResRepository(translatorResPack, totalResRepository));
440 : // 将ctx中的rep虚拟资源按类型进行和CCU物理资源映射
441 3 : ResetRepResourceToResRepository(translatorRepRes, totalResRepository);
442 3 : return HcclResult::HCCL_SUCCESS;
443 3 : }
444 :
445 3 : HcclResult CtxMgrImp::TransRepResToPhyRes(CcuCtxGroup &ctxGroup) const
446 : {
447 : // 获取ctxGroup中CCU物理资源句柄
448 3 : CcuResPack *resPack = ctxGroup.ctxs[0]->GetResPack();
449 3 : CHK_PTR_NULL(resPack);
450 :
451 : // 获取通信域当前所持有的资源
452 3 : CcuResRepository totalResRepository;
453 3 : CHK_RET(GetResPackTotalResRepository(*resPack, totalResRepository));
454 :
455 : // 遍历ctxGroup, 将每个ctx的虚拟资源进行合并
456 3 : CcuRepResource totalRepRes = GetTotalCcuRepResource(ctxGroup);
457 :
458 : // 将ctx中的rep虚拟资源按类型进行和CCU物理资源映射
459 3 : ResetRepResourceToResRepository(totalRepRes, totalResRepository);
460 :
461 : // 针对跨ctx的资源进行特殊映射处理
462 3 : ProcessInterCtxRes(ctxGroup);
463 :
464 : // missionId、mission key赋值给ctx
465 3 : CHK_RET(SaveCtxMissionInfo(ctxGroup, totalResRepository.mission.mission));
466 3 : return HcclResult::HCCL_SUCCESS;
467 3 : }
468 :
469 6 : HcclResult CtxMgrImp::GetResPackTotalResRepository(const CcuResPack &resPack, CcuResRepository &totalRes) const
470 : {
471 6 : CcuResRepository tmpResRepository;
472 :
473 : // 获取通信域当前所持有的资源
474 13 : for (CcuResHandle resHandle : resPack.handles) {
475 7 : CHK_RET(CcuDeviceManager::GetResource(deviceLogicId_, resHandle, tmpResRepository));
476 :
477 : // 合并获取的所持有的资源信息, 按照类型合并资源总和到totalRes中
478 21 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
479 14 : ExpandResInfo(totalRes.ms[i], tmpResRepository.ms[i]);
480 14 : ExpandResInfo(totalRes.blockMs[i], tmpResRepository.blockMs[i]);
481 14 : ExpandResInfo(totalRes.loopEngine[i], tmpResRepository.loopEngine[i]);
482 14 : ExpandResInfo(totalRes.blockLoopEngine[i], tmpResRepository.blockLoopEngine[i]);
483 14 : ExpandResInfo(totalRes.cke[i], tmpResRepository.cke[i]);
484 14 : ExpandResInfo(totalRes.blockCke[i], tmpResRepository.blockCke[i]);
485 14 : ExpandResInfo(totalRes.gsa[i], tmpResRepository.gsa[i]);
486 14 : ExpandResInfo(totalRes.xn[i], tmpResRepository.xn[i]);
487 14 : ExpandResInfo(totalRes.continuousXn[i], tmpResRepository.continuousXn[i]);
488 14 : ExpandResInfo(totalRes.mission.mission[i], tmpResRepository.mission.mission[i]);
489 : }
490 7 : DumpResRepositoryInfo(totalRes);
491 21 : HCCL_INFO("GetResPackTotalResRepository:dumpInfos success deviceLogicId[%d] resHandle[%p].", deviceLogicId_,
492 : resHandle);
493 : }
494 6 : return HcclResult::HCCL_SUCCESS;
495 6 : }
496 :
497 3 : CcuRepResource CtxMgrImp::GetTotalCcuRepResource(CcuCtxGroup &ctxGroup) const
498 : {
499 3 : CcuRepResource totalRepRes;
500 :
501 : // 遍历ctxGroup, 将每个ctx的虚拟资源进行合并
502 9 : for (auto &ctx : ctxGroup.ctxs) {
503 : // 获取ctx的虚拟资源
504 6 : CcuRepResource tmpRepRes = ctx->GetResource();
505 6 : MergeCtxRepResource(totalRepRes, tmpRepRes);
506 6 : }
507 :
508 3 : return totalRepRes;
509 0 : }
510 :
511 6 : void CtxMgrImp::MergeCtxRepResource(CcuRepResource &repResourceA, CcuRepResource &repResourceB) const
512 : {
513 18 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
514 : // 合并repRes
515 24 : repResourceA.ccubuffers[i].insert(repResourceA.ccubuffers[i].end(), repResourceB.ccubuffers[i].begin(),
516 12 : repResourceB.ccubuffers[i].end());
517 :
518 36 : repResourceA.blockCcubuffers[i].insert(repResourceA.blockCcubuffers[i].end(),
519 12 : repResourceB.blockCcubuffers[i].begin(),
520 12 : repResourceB.blockCcubuffers[i].end());
521 :
522 24 : repResourceA.executor[i].insert(repResourceA.executor[i].end(), repResourceB.executor[i].begin(),
523 12 : repResourceB.executor[i].end());
524 :
525 24 : repResourceA.blockExecutor[i].insert(repResourceA.blockExecutor[i].end(), repResourceB.blockExecutor[i].begin(),
526 12 : repResourceB.blockExecutor[i].end());
527 :
528 24 : repResourceA.maskSignal[i].insert(repResourceA.maskSignal[i].end(), repResourceB.maskSignal[i].begin(),
529 12 : repResourceB.maskSignal[i].end());
530 :
531 36 : repResourceA.blockMaskSignal[i].insert(repResourceA.blockMaskSignal[i].end(),
532 12 : repResourceB.blockMaskSignal[i].begin(),
533 12 : repResourceB.blockMaskSignal[i].end());
534 :
535 24 : repResourceA.address[i].insert(repResourceA.address[i].end(), repResourceB.address[i].begin(),
536 12 : repResourceB.address[i].end());
537 :
538 24 : repResourceA.variable[i].insert(repResourceA.variable[i].end(), repResourceB.variable[i].begin(),
539 12 : repResourceB.variable[i].end());
540 :
541 36 : repResourceA.continuousVariable[i].insert(repResourceA.continuousVariable[i].end(),
542 12 : repResourceB.continuousVariable[i].begin(),
543 12 : repResourceB.continuousVariable[i].end());
544 : }
545 6 : return;
546 : }
547 :
548 : template <typename T1, typename T2>
549 108 : void CtxMgrImp::ResetRepResourceTemplate(std::vector<T1> &resource, const std::vector<T2> &repository) const
550 : {
551 108 : if (resource.size() > repository.size()) {
552 0 : THROW<CcuApiException>("[CtxMgrImp][ResetRepResourceTemplate]resource size[%u] bigger repository size[%u] typeid[%s]",
553 : resource.size(), repository.size(), typeid(T1).name());
554 : return;
555 : }
556 :
557 5768 : for (uint32_t j = 0; j < resource.size(); j++) {
558 5660 : resource[j].Reset(repository[j].startId);
559 : }
560 : }
561 :
562 6 : void CtxMgrImp::ResetRepResourceToResRepository(CcuRepResource &totalRepRes, const CcuResRepository &totalResRepository) const
563 : {
564 : // 遍历translatorRepRes, 将每个rep的虚拟资源翻译到实际物理资源上
565 18 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
566 12 : ResetRepResourceTemplate(totalRepRes.ccubuffers[i], totalResRepository.ms[i]);
567 12 : ResetRepResourceTemplate(totalRepRes.blockCcubuffers[i], totalResRepository.blockMs[i]);
568 12 : ResetRepResourceTemplate(totalRepRes.executor[i], totalResRepository.loopEngine[i]);
569 12 : ResetRepResourceTemplate(totalRepRes.blockExecutor[i], totalResRepository.blockLoopEngine[i]);
570 12 : ResetRepResourceTemplate(totalRepRes.maskSignal[i], totalResRepository.cke[i]);
571 12 : ResetRepResourceTemplate(totalRepRes.blockMaskSignal[i], totalResRepository.blockCke[i]);
572 12 : ResetRepResourceTemplate(totalRepRes.address[i], totalResRepository.gsa[i]);
573 12 : ResetRepResourceTemplate(totalRepRes.variable[i], totalResRepository.xn[i]);
574 12 : ResetRepResourceTemplate(totalRepRes.continuousVariable[i], totalResRepository.continuousXn[i]);
575 : }
576 6 : }
577 :
578 : template <typename T>
579 12 : void CtxMgrImp::ProcessSharedResources(std::unordered_map<std::string, T> &resources,
580 : std::vector<std::unordered_map<std::string, T>> &exportedResources, uint32_t i) const
581 : {
582 18 : for (auto &res : resources) {
583 : uint32_t j;
584 13 : for (j = 0; j < exportedResources.size(); j++) {
585 13 : if (i != j) {
586 8 : auto exportedRes = exportedResources[j].find(res.first);
587 8 : if (exportedRes != exportedResources[j].end()) {
588 6 : res.second.Reset(exportedRes->second.Id(), exportedRes->second.DieId());
589 6 : break;
590 : }
591 : }
592 : }
593 :
594 6 : if (j >= exportedResources.size()) {
595 0 : THROW<CcuApiException>("ProcessSharedResources failed tag[%s]", res.first.c_str());
596 : }
597 : }
598 12 : }
599 :
600 3 : void CtxMgrImp::ProcessInterCtxRes(CcuCtxGroup &ctxGroup) const
601 : {
602 : // 针对跨ctx的资源进行特殊映射处理
603 9 : for (uint32_t i = 0; i < ctxGroup.ctxs.size(); i++) {
604 : // 获取当前ctx中导入的ccuShrRes
605 6 : CcuSharedResource importRes = ctxGroup.ctxs[i]->GetImportRes();
606 :
607 : // 提前计算所有ctx的exportRes,以减少不必要的重复计算
608 12 : std::vector<std::unordered_map<std::string, CcuRep::Variable>> exportVarResList(ctxGroup.ctxs.size());
609 6 : std::vector<std::unordered_map<std::string, CcuRep::MaskSignal>> exportSigResList(ctxGroup.ctxs.size());
610 :
611 20 : for (uint32_t j = 0; j < ctxGroup.ctxs.size(); j++) {
612 14 : if (i != j) {
613 8 : auto exportRes = ctxGroup.ctxs[j]->GetExportRes();
614 8 : exportVarResList[j] = exportRes.sharedVar;
615 8 : exportSigResList[j] = exportRes.sharedSig;
616 8 : }
617 : }
618 :
619 : // 处理sharedVar和sharedSig
620 6 : ProcessSharedResources(importRes.sharedVar, exportVarResList, i);
621 6 : ProcessSharedResources(importRes.sharedSig, exportSigResList, i);
622 6 : }
623 3 : }
624 :
625 3 : HcclResult CtxMgrImp::SaveCtxMissionInfo(CcuCtxGroup &ctxGroup, array<vector<ResInfo>, MAX_CCU_IODIE_NUM> &missionId) const
626 : {
627 9 : for (auto &ctx : ctxGroup.ctxs) {
628 6 : auto dieId = ctx->GetDieId();
629 : uint32_t missionKey;
630 6 : CHK_RET(CcuDeviceManager::GetMissionKey(deviceLogicId_, dieId, missionKey));
631 :
632 18 : HCCL_INFO("[SaveCtxMissionInfo]GetMissionKey:deviceLogicId[%d] dieId[%u]", deviceLogicId_, dieId);
633 :
634 6 : ctx->SetMissionKey(missionKey);
635 : // 从missionId中获取一个元素并从missionId中删除
636 6 : ctx->SetMissionId(missionId[dieId].back().startId);
637 6 : missionId[dieId].pop_back();
638 : }
639 :
640 3 : return HcclResult::HCCL_SUCCESS;
641 : }
642 :
643 3 : void CtxMgrImp::TransRepSequenceToMicrocode(CcuCtxGroup &ctxGroup, bool isFuncBlock)
644 : {
645 9 : for (auto &ctx : ctxGroup.ctxs) {
646 6 : auto dieId = ctx->GetDieId();
647 6 : auto missionId = ctx->GetMissionId();
648 : // 翻译本ctx的REP序列
649 6 : auto instrInfo = translators[dieId][missionId]->Translate(ctx->GetRepSequence(), ctx->GetInstrId(), isFuncBlock);
650 :
651 : #ifdef HCCL_ALG_ANALYZER_DAVID
652 : // 建立CCU指令和微码的映射关系
653 : extern std::map<const Hccl::Instruction*, std::vector<Hccl::CcuRep::CcuInstrInfo>> g_ccuIns2MicroCode;
654 : extern Hccl::Instruction* g_ccuIns;
655 : g_ccuIns2MicroCode[g_ccuIns].push_back(instrInfo);
656 : #endif
657 :
658 : // 保存翻译后的指令信息
659 6 : ctx->SetCcuInstrInfo(instrInfo);
660 :
661 : // 加载指令到CCU指令空间
662 6 : LoadInstruction(instrInfo, dieId);
663 6 : }
664 3 : return;
665 : }
666 :
667 6 : void CtxMgrImp::LoadInstruction(CcuRep::CcuInstrInfo &instrInfo, uint32_t dieId)
668 : {
669 6 : uint64_t instrInfoSize = instrInfo.instrVec.size() * sizeof(CcuInstr);
670 :
671 6 : if (!instructionLoadDevMem_) {
672 6 : uint32_t instrNum = 0;
673 6 : if (CcuDeviceManager::GetInstructionNum(deviceLogicId_, 0, instrNum) != HcclResult::HCCL_SUCCESS) {
674 0 : THROW<CcuApiException>("CtxMgrImp::Init failed");
675 : }
676 18 : HCCL_INFO("[CtxMgrImp]LoadInstruction: deviceLogicId[%d], instrNum[%u]", deviceLogicId_, instrNum);
677 : // rt接口申请device内存
678 6 : instructionLoadDevMem_ = HrtMalloc(instrNum * sizeof(CcuInstr),
679 : static_cast<int>(ACL_MEM_TYPE_HIGH_BAND_WIDTH));
680 : }
681 :
682 : // rt接口memcpySync
683 6 : HrtMemcpy(instructionLoadDevMem_, instrInfoSize, instrInfo.instrVec.data(), instrInfoSize,
684 : RT_MEMCPY_HOST_TO_DEVICE);
685 :
686 6 : auto tlvHandle = HccpTlvHdcManager::GetInstance().GetTlvHandle(deviceLogicId_);
687 6 : CHECK_NULLPTR(tlvHandle, StringFormat("[CtxMgrImp][%s] tlvHandle is nullptr, deviceLogicId[%d]", __func__, deviceLogicId_));
688 :
689 6 : struct CustomChannelInfoIn inBuff;
690 6 : struct CustomChannelInfoOut outBuff;
691 :
692 : CcuDataTypeUnion tmp;
693 6 : tmp.insinfo.resourceAddr = reinterpret_cast<uint64_t>(instructionLoadDevMem_);
694 :
695 : // 设置操作码和通道数据
696 6 : inBuff.op = CcuOpcodeType::CCU_U_OP_SET_INSTRUCTION;
697 6 : inBuff.offsetStartIdx = instrInfo.startInstrId;
698 6 : inBuff.data.dataInfo.udieIdx = dieId;
699 6 : inBuff.data.dataInfo.dataArraySize = 1;
700 6 : inBuff.data.dataInfo.dataLen = instrInfoSize;
701 :
702 : // 复制通道数据
703 6 : (void)memcpy_s(inBuff.data.dataInfo.dataArray, sizeof(CcuDataTypeUnion), &tmp, sizeof(CcuDataTypeUnion));
704 :
705 6 : HrtRaTlvRequestForCustomChannel(tlvHandle, MSG_TYPE_CCU_DISPATCH_CMD, static_cast<void *>(&inBuff), static_cast<void *>(&outBuff));
706 :
707 18 : HCCL_RUN_INFO("Entry-LoadInstruction: load instruction success startInstrId[%u] instrCount[%u]",
708 : instrInfo.startInstrId, instrInfo.instrCount);
709 :
710 12 : return;
711 : }
712 :
713 12 : void CtxMgrImp::DumpResReqInfo(const CcuResReq &totalRes) const
714 : {
715 36 : for (uint32_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
716 48 : if (totalRes.msReq[i] != 0 || totalRes.blockMsReq[i] != 0 || totalRes.ckeReq[i] != 0 || totalRes.blockCkeReq[i] != 0
717 15 : || totalRes.loopEngineReq[i] != 0 || totalRes.blockLoopEngineReq[i] != 0 || totalRes.gsaReq[i] != 0
718 15 : || totalRes.xnReq[i] != 0 || totalRes.continuousXnReq[i] != 0
719 48 : ||totalRes.missionReq.req[i] != 0) {
720 33 : HCCL_INFO("DumpResReqInfo: dieId[%u], msReq[%u], blockMsReq[%u], ckeReq[%u], blockCkeReq[%u], "
721 : "loopEngineReq[%u], blockLoopEngineReq[%u], gsaReq[%u], xnReq[%u], continuousXnReq[%u], "
722 : "missionReq[%u]",
723 : i, totalRes.msReq[i], totalRes.blockMsReq[i], totalRes.ckeReq[i], totalRes.blockCkeReq[i],
724 : totalRes.loopEngineReq[i], totalRes.blockLoopEngineReq[i], totalRes.gsaReq[i],
725 : totalRes.xnReq[i], totalRes.continuousXnReq[i], totalRes.missionReq.req[i]);
726 : }
727 : }
728 12 : }
729 :
730 7 : void CtxMgrImp::DumpResRepositoryInfo(const CcuResRepository &resRepo) const
731 : {
732 21 : for (uint32_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
733 28 : if (resRepo.ms[i].size() != 0 || resRepo.blockMs[i].size() != 0 || resRepo.cke[i].size() != 0 || resRepo.blockCke[i].size() != 0
734 3 : || resRepo.loopEngine[i].size() != 0 || resRepo.blockLoopEngine[i].size() != 0 || resRepo.gsa[i].size() != 0
735 3 : || resRepo.xn[i].size() != 0 || resRepo.continuousXn[i].size() != 0
736 28 : || resRepo.mission.mission[i].size() != 0) {
737 33 : HCCL_INFO("DumpResRepository: dieId[%u], ms size[%u], blockMs size[%u], cke size[%u], blockCke size[%u], "
738 : "loopEngine size[%u], blockLoopEngine size[%u], gsa size[%u], xn size[%u], "
739 : "continuous xn size[%u], mission size[%u]",
740 : i, resRepo.ms[i].size(), resRepo.blockMs[i].size(), resRepo.cke[i].size(),
741 : resRepo.blockCke[i].size(), resRepo.loopEngine[i].size(), resRepo.blockLoopEngine[i].size(),
742 : resRepo.gsa[i].size(), resRepo.xn[i].size(), resRepo.continuousXn[i].size(),
743 : resRepo.mission.mission[i].size());
744 : }
745 : }
746 7 : }
747 :
748 0 : std::vector<std::vector<CcuProfilingInfo>> CtxMgrImp::GetProfilingInfo(CcuTaskArg &ccuTaskArg, const uint64_t entityId)
749 : {
750 : // 根据entityId获取ctxGroup
751 0 : std::unique_lock<std::mutex> lock(contextMapMutex_);
752 :
753 : // 校验ctxGroupMap_中是否存在entityId对应的ctxGroup
754 0 : CHK_PRT_RET(ctxGroupMap_.find(entityId) == ctxGroupMap_.end(),
755 : HCCL_ERROR("[CtxMgrImp][GetProfilingInfo]entityId [%llu] is not exist", entityId),
756 : std::vector<std::vector<CcuProfilingInfo>>());
757 :
758 : // 获取每个ctx的profiling信息
759 0 : std::vector<std::vector<CcuProfilingInfo>> ccuProfilingInfo;
760 0 : for (auto &ctx : ctxGroupMap_[entityId].ctxs) {
761 0 : std::vector<CcuProfilingInfo> tmp;
762 0 : auto ret = ctx->GetCcuProfilingInfo(ccuTaskArg, tmp);
763 0 : if (ret != HcclResult::HCCL_SUCCESS) {
764 0 : THROW<CcuApiException>("GetCcuProfilingInfo is failed. ret[%d]", ret);
765 : }
766 0 : ccuProfilingInfo.push_back(tmp);
767 0 : }
768 :
769 0 : return ccuProfilingInfo;
770 0 : }
771 :
772 2 : CcuContext* CtxMgrImp::GetCtx(uint64_t executorId, uint32_t dieId, uint32_t missionId)
773 : {
774 2 : std::unique_lock<std::mutex> lock(contextMapMutex_);
775 :
776 2 : if (ctxGroupMap_.find(executorId) == ctxGroupMap_.end()) {
777 3 : HCCL_ERROR("[CtxMgrImp][GetCtx] executorId [%llu] is not exist", executorId);
778 1 : return nullptr;
779 : }
780 :
781 1 : for (auto& ctx : ctxGroupMap_[executorId].ctxs) {
782 0 : if (ctx->GetDieId() == dieId && ctx->GetMissionId() == missionId) {
783 0 : return ctx.get();
784 : }
785 : }
786 :
787 3 : HCCL_ERROR("[CtxMgrImp][GetCtx] CcuContext is not exist, dieId[%u], missionId[%u]", dieId, missionId);
788 1 : return nullptr;
789 2 : }
790 : }; // namespace Hccl
|