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.blockGsaReq[i] += GetResTotalNum(tmpResRepository.blockGsa[i]);
265 0 : totalRes.xnReq[i] += GetResTotalNum(tmpResRepository.xn[i]);
266 0 : totalRes.blockXnReq[i] += GetResTotalNum(tmpResRepository.blockXn[i]);
267 0 : totalRes.missionReq.req[i] += GetResTotalNum(tmpResRepository.mission.mission[i]);
268 : }
269 : }
270 :
271 3 : DumpResReqInfo(totalRes);
272 9 : HCCL_INFO("GetResPackTotalResNum:dumpInfos success.");
273 3 : return HcclResult::HCCL_SUCCESS;
274 3 : }
275 :
276 3 : CcuResReq CtxMgrImp::GetCtxGroupResReq(CcuCtxGroup &ctxGroup) const
277 : {
278 3 : CcuResReq totalResReq;
279 :
280 3 : std::unordered_set<uint16_t> usedDieId; // CCUCtxGroup使用到的所有dieId
281 :
282 : // 获取CCUCtxGroup所有ctx资源诉求
283 9 : for (auto &ctx : ctxGroup.ctxs) {
284 6 : auto dieId = ctx->GetDieId();
285 6 : usedDieId.insert(dieId);
286 :
287 6 : CcuResReq tmpResReq = ctx->GetResourceRequest();
288 6 : MergeCcuResReq(totalResReq, tmpResReq);
289 : }
290 :
291 3 : DumpResReqInfo(totalResReq);
292 9 : HCCL_INFO("CtxGroupResReq:dumpInfos success.");
293 :
294 6 : return totalResReq;
295 3 : }
296 :
297 102 : void CtxMgrImp::MergeCcuResReq(CcuResReq &resReqA, const CcuResReq &resReqB) const
298 : {
299 : // 合并获取的所持有的资源信息, 按照类型合并资源总和到totalRes的第0个vector中
300 306 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
301 204 : resReqA.msReq[i] += resReqB.msReq[i];
302 204 : resReqA.blockMsReq[i] += resReqB.blockMsReq[i];
303 204 : resReqA.ckeReq[i] += resReqB.ckeReq[i];
304 204 : resReqA.blockCkeReq[i] += resReqB.blockCkeReq[i];
305 204 : resReqA.loopEngineReq[i] += resReqB.loopEngineReq[i];
306 204 : resReqA.blockLoopEngineReq[i] += resReqB.blockLoopEngineReq[i];
307 204 : resReqA.gsaReq[i] += resReqB.gsaReq[i];
308 204 : resReqA.blockGsaReq[i] += resReqB.blockGsaReq[i];
309 204 : resReqA.xnReq[i] += resReqB.xnReq[i];
310 204 : resReqA.blockXnReq[i] += resReqB.blockXnReq[i];
311 204 : resReqA.missionReq.req[i] += resReqB.missionReq.req[i];
312 :
313 204 : if (resReqB.missionReq.req[i] > 0) {
314 6 : resReqA.missionReq.reqType = resReqB.missionReq.reqType;
315 : }
316 : }
317 102 : return;
318 : }
319 :
320 3 : HcclResult CtxMgrImp::CompareResAndApplyAsNeeded(const CcuResReq &totalRes, const CcuResReq &resReq,
321 : CcuResPack &resPack) const
322 : {
323 : // 比较额外需要的资源
324 3 : bool isNeedAlloc = false;
325 3 : CcuResReq needResReq;
326 :
327 9 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
328 6 : needResReq.msReq[i] = GetReqResNum(resReq.msReq[i], totalRes.msReq[i]);
329 6 : needResReq.blockMsReq[i] = GetReqResNum(resReq.blockMsReq[i], totalRes.blockMsReq[i]);
330 6 : needResReq.ckeReq[i] = GetReqResNum(resReq.ckeReq[i], totalRes.ckeReq[i]);
331 6 : needResReq.blockCkeReq[i] = GetReqResNum(resReq.blockCkeReq[i], totalRes.blockCkeReq[i]);
332 6 : needResReq.loopEngineReq[i] = GetReqResNum(resReq.loopEngineReq[i], totalRes.loopEngineReq[i]);
333 6 : needResReq.blockLoopEngineReq[i] = GetReqResNum(resReq.blockLoopEngineReq[i], totalRes.blockLoopEngineReq[i]);
334 6 : needResReq.gsaReq[i] = GetReqResNum(resReq.gsaReq[i], totalRes.gsaReq[i]);
335 6 : needResReq.blockGsaReq[i] = GetReqResNum(resReq.blockGsaReq[i], totalRes.blockGsaReq[i]);
336 6 : needResReq.xnReq[i] = GetReqResNum(resReq.xnReq[i], totalRes.xnReq[i]);
337 6 : needResReq.blockXnReq[i] = GetReqResNum(resReq.blockXnReq[i], totalRes.blockXnReq[i]);
338 6 : needResReq.missionReq.req[i]
339 6 : = GetReqResNum(resReq.missionReq.req[i], totalRes.missionReq.req[i]);
340 :
341 6 : if (needResReq.missionReq.req[i] > 0) {
342 4 : needResReq.missionReq.reqType = resReq.missionReq.reqType;
343 : }
344 :
345 12 : if (needResReq.msReq[i] != 0 || needResReq.blockMsReq[i] != 0 || needResReq.ckeReq[i] != 0 || needResReq.blockCkeReq[i] != 0
346 3 : || needResReq.loopEngineReq[i] != 0 || needResReq.blockLoopEngineReq[i] != 0 || needResReq.gsaReq[i] != 0
347 3 : || needResReq.blockGsaReq[i] != 0 || needResReq.xnReq[i] != 0 || needResReq.blockXnReq[i] != 0
348 12 : || needResReq.missionReq.req[i] != 0) {
349 4 : isNeedAlloc = true;
350 : }
351 : }
352 :
353 3 : if (isNeedAlloc) {
354 : // 申请额外资源
355 : CcuResHandle handle;
356 3 : DumpResReqInfo(needResReq);
357 :
358 3 : CHK_RET_UNAVAIL(CcuDeviceManager::AllocResHandle(deviceLogicId_, needResReq, handle));
359 : // 将申请的资源保存到resPack中
360 3 : resPack.handles.push_back(handle);
361 :
362 9 : HCCL_INFO("ApplyAsNeeded:dumpInfos success deviceLogicId[%d] handle[%p].", deviceLogicId_, handle);
363 : }
364 :
365 3 : return HcclResult::HCCL_SUCCESS;
366 : }
367 :
368 3 : void CtxMgrImp::SaveResPackToCtx(CcuCtxGroup &ctxGroup, CcuResPack &resPack) const
369 : {
370 9 : for (auto &ctx : ctxGroup.ctxs) {
371 6 : ctx->SetResPack(resPack);
372 : }
373 3 : return;
374 : }
375 :
376 4 : HcclResult CtxMgrImp::InstantiationTranslator(uint16_t dieId)
377 : {
378 4 : if (translators.find(dieId) != translators.end()) {
379 1 : return HcclResult::HCCL_SUCCESS;
380 : }
381 :
382 3 : std::array<uint16_t, MAX_CCU_IODIE_NUM> tmpChannelId{};
383 3 : uint32_t chaneelId = 0;
384 : // 获取innerDieChannelId
385 3 : auto ret = CcuDeviceManager::GetLoopChannelId(deviceLogicId_, dieId, dieId, chaneelId);
386 3 : if (ret != HcclResult::HCCL_SUCCESS) {
387 0 : THROW<CcuApiException>("Failed to get inner die channel id. deviceLogicId = %d, dieId = %u, ret = %d",
388 : deviceLogicId_, dieId, ret);
389 : }
390 3 : tmpChannelId[0] = chaneelId;
391 : // 获取interDieChannelId
392 3 : uint8_t dstDieId = ((dieId == 0) ? 1 : 0);
393 3 : ret = CcuDeviceManager::GetLoopChannelId(deviceLogicId_, dieId, dstDieId, chaneelId);
394 3 : if (ret != HcclResult::HCCL_SUCCESS) {
395 : // 当前验证环境为单die环境,获取die间ChannelId会失败,打印WARNING日志。
396 0 : HCCL_WARNING("Failed to get inter die channel id. deviceLogicId = %d, srcDieId = %u, dstDieId = %u, ret = %d",
397 : deviceLogicId_, dieId, dstDieId, ret);
398 : }
399 3 : tmpChannelId[1] = chaneelId;
400 : // 获取ccu token信息
401 3 : uint64_t tokenId = 0;
402 3 : uint64_t tokenValue = 0;
403 3 : ret = CcuDeviceManager::GetCcuResourceSpaceTokenInfoForLocal(deviceLogicId_, dieId, tokenId, tokenValue);
404 3 : if (ret != HcclResult::HCCL_SUCCESS) {
405 0 : THROW<CcuApiException>("Failed to get ccu resource space token info. deviceLogicId = %d, dieId = %u, ret = %d",
406 : deviceLogicId_, dieId, ret);
407 : }
408 3 : std::pair<uint64_t, uint64_t> ccuTokenInfo(tokenId, tokenValue);
409 3 : CcuResReq totalResReq;
410 :
411 : // 先获取hbm token,避免创建mission时循环获取
412 3 : DevBuffer tmpDevMem{1};
413 3 : auto hbmTokenInfo = GetTokenInfo(tmpDevMem.GetAddr(), 1);
414 :
415 : // 实例化CcuRepReferenceManager和CcuRepTranslator,并为CcuRepReferenceManager绑定物理资源
416 51 : for (uint32_t i = 0; i < 16; i++) { // mgr有16个
417 48 : referenceMgrs[dieId][i] = std::make_shared<CcuRepReferenceManager>(dieId);
418 96 : translators[dieId][i] = std::make_shared<CcuRepTranslator>(deviceLogicId_, dieId, referenceMgrs[dieId][i],
419 48 : tmpChannelId, ccuTokenInfo, hbmTokenInfo);
420 :
421 : // 统计&合并refManager和translaotr所有资源REQ
422 48 : auto refMangerResReq = CcuRep::CcuRepReferenceManager::GetResReq(dieId);
423 48 : auto transLatorResReq = CcuRep::CcuRepTranslator::GetResReq(dieId);
424 48 : MergeCcuResReq(totalResReq, refMangerResReq);
425 48 : MergeCcuResReq(totalResReq, transLatorResReq);
426 : }
427 :
428 3 : DumpResReqInfo(totalResReq);
429 :
430 : // 为refManager和translaotr申请物理资源
431 : CcuResHandle handle;
432 3 : CHK_RET_UNAVAIL(CcuDeviceManager::AllocResHandle(deviceLogicId_, totalResReq, handle));
433 3 : translatorResPack.handles.push_back(handle);
434 :
435 3 : CcuRepResource translatorRepRes;
436 51 : for (uint32_t i = 0; i < 16; i++) { // mgr有16个
437 48 : referenceMgrs[dieId][i]->GetRes(translatorRepRes);
438 48 : translators[dieId][i]->GetRes(translatorRepRes);
439 : }
440 :
441 3 : CcuResRepository totalResRepository;
442 3 : CHK_RET(GetResPackTotalResRepository(translatorResPack, totalResRepository));
443 : // 将ctx中的rep虚拟资源按类型进行和CCU物理资源映射
444 3 : ResetRepResourceToResRepository(translatorRepRes, totalResRepository);
445 3 : return HcclResult::HCCL_SUCCESS;
446 3 : }
447 :
448 3 : HcclResult CtxMgrImp::TransRepResToPhyRes(CcuCtxGroup &ctxGroup) const
449 : {
450 : // 获取ctxGroup中CCU物理资源句柄
451 3 : CcuResPack *resPack = ctxGroup.ctxs[0]->GetResPack();
452 3 : CHK_PTR_NULL(resPack);
453 :
454 : // 获取通信域当前所持有的资源
455 3 : CcuResRepository totalResRepository;
456 3 : CHK_RET(GetResPackTotalResRepository(*resPack, totalResRepository));
457 :
458 : // 遍历ctxGroup, 将每个ctx的虚拟资源进行合并
459 3 : CcuRepResource totalRepRes = GetTotalCcuRepResource(ctxGroup);
460 :
461 : // 将ctx中的rep虚拟资源按类型进行和CCU物理资源映射
462 3 : ResetRepResourceToResRepository(totalRepRes, totalResRepository);
463 :
464 : // 针对跨ctx的资源进行特殊映射处理
465 3 : ProcessInterCtxRes(ctxGroup);
466 :
467 : // missionId、mission key赋值给ctx
468 3 : CHK_RET(SaveCtxMissionInfo(ctxGroup, totalResRepository.mission.mission));
469 3 : return HcclResult::HCCL_SUCCESS;
470 3 : }
471 :
472 6 : HcclResult CtxMgrImp::GetResPackTotalResRepository(const CcuResPack &resPack, CcuResRepository &totalRes) const
473 : {
474 6 : CcuResRepository tmpResRepository;
475 :
476 : // 获取通信域当前所持有的资源
477 13 : for (CcuResHandle resHandle : resPack.handles) {
478 7 : CHK_RET(CcuDeviceManager::GetResource(deviceLogicId_, resHandle, tmpResRepository));
479 :
480 : // 合并获取的所持有的资源信息, 按照类型合并资源总和到totalRes中
481 21 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
482 14 : ExpandResInfo(totalRes.ms[i], tmpResRepository.ms[i]);
483 14 : ExpandResInfo(totalRes.blockMs[i], tmpResRepository.blockMs[i]);
484 14 : ExpandResInfo(totalRes.loopEngine[i], tmpResRepository.loopEngine[i]);
485 14 : ExpandResInfo(totalRes.blockLoopEngine[i], tmpResRepository.blockLoopEngine[i]);
486 14 : ExpandResInfo(totalRes.cke[i], tmpResRepository.cke[i]);
487 14 : ExpandResInfo(totalRes.blockCke[i], tmpResRepository.blockCke[i]);
488 14 : ExpandResInfo(totalRes.gsa[i], tmpResRepository.gsa[i]);
489 14 : ExpandResInfo(totalRes.blockGsa[i], tmpResRepository.blockGsa[i]);
490 14 : ExpandResInfo(totalRes.xn[i], tmpResRepository.xn[i]);
491 14 : ExpandResInfo(totalRes.blockXn[i], tmpResRepository.blockXn[i]);
492 14 : ExpandResInfo(totalRes.mission.mission[i], tmpResRepository.mission.mission[i]);
493 : }
494 7 : DumpResRepositoryInfo(totalRes);
495 21 : HCCL_INFO("GetResPackTotalResRepository:dumpInfos success deviceLogicId[%d] resHandle[%p].", deviceLogicId_,
496 : resHandle);
497 : }
498 6 : return HcclResult::HCCL_SUCCESS;
499 6 : }
500 :
501 3 : CcuRepResource CtxMgrImp::GetTotalCcuRepResource(CcuCtxGroup &ctxGroup) const
502 : {
503 3 : CcuRepResource totalRepRes;
504 :
505 : // 遍历ctxGroup, 将每个ctx的虚拟资源进行合并
506 9 : for (auto &ctx : ctxGroup.ctxs) {
507 : // 获取ctx的虚拟资源
508 6 : CcuRepResource tmpRepRes = ctx->GetResource();
509 6 : MergeCtxRepResource(totalRepRes, tmpRepRes);
510 6 : }
511 :
512 3 : return totalRepRes;
513 0 : }
514 :
515 6 : void CtxMgrImp::MergeCtxRepResource(CcuRepResource &repResourceA, CcuRepResource &repResourceB) const
516 : {
517 18 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
518 : // 合并repRes
519 24 : repResourceA.ccubuffers[i].insert(repResourceA.ccubuffers[i].end(), repResourceB.ccubuffers[i].begin(),
520 12 : repResourceB.ccubuffers[i].end());
521 :
522 36 : repResourceA.blockCcubuffers[i].insert(repResourceA.blockCcubuffers[i].end(),
523 12 : repResourceB.blockCcubuffers[i].begin(),
524 12 : repResourceB.blockCcubuffers[i].end());
525 :
526 24 : repResourceA.executor[i].insert(repResourceA.executor[i].end(), repResourceB.executor[i].begin(),
527 12 : repResourceB.executor[i].end());
528 :
529 24 : repResourceA.blockExecutor[i].insert(repResourceA.blockExecutor[i].end(), repResourceB.blockExecutor[i].begin(),
530 12 : repResourceB.blockExecutor[i].end());
531 :
532 24 : repResourceA.maskSignal[i].insert(repResourceA.maskSignal[i].end(), repResourceB.maskSignal[i].begin(),
533 12 : repResourceB.maskSignal[i].end());
534 :
535 36 : repResourceA.blockMaskSignal[i].insert(repResourceA.blockMaskSignal[i].end(),
536 12 : repResourceB.blockMaskSignal[i].begin(),
537 12 : repResourceB.blockMaskSignal[i].end());
538 :
539 24 : repResourceA.address[i].insert(repResourceA.address[i].end(), repResourceB.address[i].begin(),
540 12 : repResourceB.address[i].end());
541 :
542 24 : repResourceA.blockAddress[i].insert(repResourceA.blockAddress[i].end(), repResourceB.blockAddress[i].begin(),
543 12 : repResourceB.blockAddress[i].end());
544 :
545 24 : repResourceA.variable[i].insert(repResourceA.variable[i].end(), repResourceB.variable[i].begin(),
546 12 : repResourceB.variable[i].end());
547 :
548 36 : repResourceA.continuousVariable[i].insert(repResourceA.continuousVariable[i].end(),
549 12 : repResourceB.continuousVariable[i].begin(),
550 12 : repResourceB.continuousVariable[i].end());
551 : }
552 6 : return;
553 : }
554 :
555 : template <typename T1, typename T2>
556 120 : void CtxMgrImp::ResetRepResourceTemplate(std::vector<T1> &resource, const std::vector<T2> &repository) const
557 : {
558 120 : if (resource.size() > repository.size()) {
559 0 : THROW<CcuApiException>("[CtxMgrImp][ResetRepResourceTemplate]resource size[%u] bigger repository size[%u] typeid[%s]",
560 : resource.size(), repository.size(), typeid(T1).name());
561 : return;
562 : }
563 :
564 3956 : for (uint32_t j = 0; j < resource.size(); j++) {
565 3836 : resource[j].Reset(repository[j].startId);
566 : }
567 : }
568 :
569 6 : void CtxMgrImp::ResetRepResourceToResRepository(CcuRepResource &totalRepRes, const CcuResRepository &totalResRepository) const
570 : {
571 : // 遍历translatorRepRes, 将每个rep的虚拟资源翻译到实际物理资源上
572 18 : for (u32 i = 0; i < MAX_CCU_IODIE_NUM; i++) {
573 12 : ResetRepResourceTemplate(totalRepRes.ccubuffers[i], totalResRepository.ms[i]);
574 12 : ResetRepResourceTemplate(totalRepRes.blockCcubuffers[i], totalResRepository.blockMs[i]);
575 12 : ResetRepResourceTemplate(totalRepRes.executor[i], totalResRepository.loopEngine[i]);
576 12 : ResetRepResourceTemplate(totalRepRes.blockExecutor[i], totalResRepository.blockLoopEngine[i]);
577 12 : ResetRepResourceTemplate(totalRepRes.maskSignal[i], totalResRepository.cke[i]);
578 12 : ResetRepResourceTemplate(totalRepRes.blockMaskSignal[i], totalResRepository.blockCke[i]);
579 12 : ResetRepResourceTemplate(totalRepRes.address[i], totalResRepository.gsa[i]);
580 12 : ResetRepResourceTemplate(totalRepRes.blockAddress[i], totalResRepository.blockGsa[i]);
581 12 : ResetRepResourceTemplate(totalRepRes.variable[i], totalResRepository.xn[i]);
582 12 : ResetRepResourceTemplate(totalRepRes.continuousVariable[i], totalResRepository.blockXn[i]);
583 : }
584 6 : }
585 :
586 : template <typename T>
587 12 : void CtxMgrImp::ProcessSharedResources(std::unordered_map<std::string, T> &resources,
588 : std::vector<std::unordered_map<std::string, T>> &exportedResources, uint32_t i) const
589 : {
590 18 : for (auto &res : resources) {
591 : uint32_t j;
592 13 : for (j = 0; j < exportedResources.size(); j++) {
593 13 : if (i != j) {
594 8 : auto exportedRes = exportedResources[j].find(res.first);
595 8 : if (exportedRes != exportedResources[j].end()) {
596 6 : res.second.Reset(exportedRes->second.Id(), exportedRes->second.DieId());
597 6 : break;
598 : }
599 : }
600 : }
601 :
602 6 : if (j >= exportedResources.size()) {
603 0 : THROW<CcuApiException>("ProcessSharedResources failed tag[%s]", res.first.c_str());
604 : }
605 : }
606 12 : }
607 :
608 3 : void CtxMgrImp::ProcessInterCtxRes(CcuCtxGroup &ctxGroup) const
609 : {
610 : // 针对跨ctx的资源进行特殊映射处理
611 9 : for (uint32_t i = 0; i < ctxGroup.ctxs.size(); i++) {
612 : // 获取当前ctx中导入的ccuShrRes
613 6 : CcuSharedResource importRes = ctxGroup.ctxs[i]->GetImportRes();
614 :
615 : // 提前计算所有ctx的exportRes,以减少不必要的重复计算
616 12 : std::vector<std::unordered_map<std::string, CcuRep::Variable>> exportVarResList(ctxGroup.ctxs.size());
617 6 : std::vector<std::unordered_map<std::string, CcuRep::MaskSignal>> exportSigResList(ctxGroup.ctxs.size());
618 :
619 20 : for (uint32_t j = 0; j < ctxGroup.ctxs.size(); j++) {
620 14 : if (i != j) {
621 8 : auto exportRes = ctxGroup.ctxs[j]->GetExportRes();
622 8 : exportVarResList[j] = exportRes.sharedVar;
623 8 : exportSigResList[j] = exportRes.sharedSig;
624 8 : }
625 : }
626 :
627 : // 处理sharedVar和sharedSig
628 6 : ProcessSharedResources(importRes.sharedVar, exportVarResList, i);
629 6 : ProcessSharedResources(importRes.sharedSig, exportSigResList, i);
630 6 : }
631 3 : }
632 :
633 3 : HcclResult CtxMgrImp::SaveCtxMissionInfo(CcuCtxGroup &ctxGroup, array<vector<ResInfo>, MAX_CCU_IODIE_NUM> &missionId) const
634 : {
635 9 : for (auto &ctx : ctxGroup.ctxs) {
636 6 : auto dieId = ctx->GetDieId();
637 : uint32_t missionKey;
638 6 : CHK_RET(CcuDeviceManager::GetMissionKey(deviceLogicId_, dieId, missionKey));
639 :
640 18 : HCCL_INFO("[SaveCtxMissionInfo]GetMissionKey:deviceLogicId[%d] dieId[%u]", deviceLogicId_, dieId);
641 :
642 6 : ctx->SetMissionKey(missionKey);
643 : // 从missionId中获取一个元素并从missionId中删除
644 6 : ctx->SetMissionId(missionId[dieId].back().startId);
645 6 : missionId[dieId].pop_back();
646 : }
647 :
648 3 : return HcclResult::HCCL_SUCCESS;
649 : }
650 :
651 3 : void CtxMgrImp::TransRepSequenceToMicrocode(CcuCtxGroup &ctxGroup, bool isFuncBlock)
652 : {
653 9 : for (auto &ctx : ctxGroup.ctxs) {
654 6 : auto dieId = ctx->GetDieId();
655 6 : auto missionId = ctx->GetMissionId();
656 : // 翻译本ctx的REP序列
657 6 : auto instrInfo = translators[dieId][missionId]->Translate(ctx->GetRepSequence(), ctx->GetInstrId(), isFuncBlock);
658 :
659 : #ifdef HCCL_ALG_ANALYZER_DAVID
660 : // 建立CCU指令和微码的映射关系
661 : extern std::map<const Hccl::Instruction*, std::vector<Hccl::CcuRep::CcuInstrInfo>> g_ccuIns2MicroCode;
662 : extern Hccl::Instruction* g_ccuIns;
663 : g_ccuIns2MicroCode[g_ccuIns].push_back(instrInfo);
664 : #endif
665 :
666 : // 保存翻译后的指令信息
667 6 : ctx->SetCcuInstrInfo(instrInfo);
668 :
669 : // 加载指令到CCU指令空间
670 6 : LoadInstruction(instrInfo, dieId);
671 6 : }
672 3 : return;
673 : }
674 :
675 6 : void CtxMgrImp::LoadInstruction(CcuRep::CcuInstrInfo &instrInfo, uint32_t dieId)
676 : {
677 6 : uint64_t instrInfoSize = instrInfo.instrVec.size() * sizeof(CcuInstr);
678 :
679 6 : if (!instructionLoadDevMem_) {
680 6 : uint32_t instrNum = 0;
681 6 : if (CcuDeviceManager::GetInstructionNum(deviceLogicId_, 0, instrNum) != HcclResult::HCCL_SUCCESS) {
682 0 : THROW<CcuApiException>("CtxMgrImp::Init failed");
683 : }
684 18 : HCCL_INFO("[CtxMgrImp]LoadInstruction: deviceLogicId[%d], instrNum[%u]", deviceLogicId_, instrNum);
685 : // rt接口申请device内存
686 6 : instructionLoadDevMem_ = HrtMalloc(instrNum * sizeof(CcuInstr),
687 : static_cast<int>(ACL_MEM_TYPE_HIGH_BAND_WIDTH));
688 : }
689 :
690 : // rt接口memcpySync
691 6 : HrtMemcpy(instructionLoadDevMem_, instrInfoSize, instrInfo.instrVec.data(), instrInfoSize,
692 : RT_MEMCPY_HOST_TO_DEVICE);
693 :
694 6 : auto tlvHandle = HccpTlvHdcManager::GetInstance().GetTlvHandle(deviceLogicId_);
695 6 : CHECK_NULLPTR(tlvHandle, StringFormat("[CtxMgrImp][%s] tlvHandle is nullptr, deviceLogicId[%d]", __func__, deviceLogicId_));
696 :
697 6 : struct CustomChannelInfoIn inBuff;
698 6 : struct CustomChannelInfoOut outBuff;
699 :
700 : CcuDataTypeUnion tmp;
701 6 : tmp.insinfo.resourceAddr = reinterpret_cast<uint64_t>(instructionLoadDevMem_);
702 :
703 : // 设置操作码和通道数据
704 6 : inBuff.op = CcuOpcodeType::CCU_U_OP_SET_INSTRUCTION;
705 6 : inBuff.offsetStartIdx = instrInfo.startInstrId;
706 6 : inBuff.data.dataInfo.udieIdx = dieId;
707 6 : inBuff.data.dataInfo.dataArraySize = 1;
708 6 : inBuff.data.dataInfo.dataLen = instrInfoSize;
709 :
710 : // 复制通道数据
711 6 : (void)memcpy_s(inBuff.data.dataInfo.dataArray, sizeof(CcuDataTypeUnion), &tmp, sizeof(CcuDataTypeUnion));
712 :
713 6 : HrtRaTlvRequestForCustomChannel(tlvHandle, MSG_TYPE_CCU_DISPATCH_CMD, static_cast<void *>(&inBuff), static_cast<void *>(&outBuff));
714 :
715 18 : HCCL_RUN_INFO("Entry-LoadInstruction: load instruction success startInstrId[%u] instrCount[%u]",
716 : instrInfo.startInstrId, instrInfo.instrCount);
717 :
718 12 : return;
719 : }
720 :
721 12 : void CtxMgrImp::DumpResReqInfo(const CcuResReq &totalRes) const
722 : {
723 36 : for (uint32_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
724 48 : if (totalRes.msReq[i] != 0 || totalRes.blockMsReq[i] != 0 || totalRes.ckeReq[i] != 0 || totalRes.blockCkeReq[i] != 0
725 15 : || totalRes.loopEngineReq[i] != 0 || totalRes.blockLoopEngineReq[i] != 0 || totalRes.gsaReq[i] != 0
726 15 : || totalRes.blockGsaReq[i] != 0 || totalRes.xnReq[i] != 0 || totalRes.blockXnReq[i] != 0
727 48 : ||totalRes.missionReq.req[i] != 0) {
728 33 : HCCL_INFO("DumpResReqInfo: dieId[%u], msReq[%u], blockMsReq[%u], ckeReq[%u], blockCkeReq[%u], "
729 : "loopEngineReq[%u], blockLoopEngineReq[%u], gsaReq[%u], blockGsaReq[%u], "
730 : "xnReq[%u], blockXnReq[%u], missionReq[%u]",
731 : i, totalRes.msReq[i], totalRes.blockMsReq[i], totalRes.ckeReq[i], totalRes.blockCkeReq[i],
732 : totalRes.loopEngineReq[i], totalRes.blockLoopEngineReq[i], totalRes.gsaReq[i], totalRes.blockGsaReq[i],
733 : totalRes.xnReq[i], totalRes.blockXnReq[i], totalRes.missionReq.req[i]);
734 : }
735 : }
736 12 : }
737 :
738 7 : void CtxMgrImp::DumpResRepositoryInfo(const CcuResRepository &resRepo) const
739 : {
740 21 : for (uint32_t i = 0; i < MAX_CCU_IODIE_NUM; i++) {
741 28 : if (resRepo.ms[i].size() != 0 || resRepo.blockMs[i].size() != 0 || resRepo.cke[i].size() != 0 || resRepo.blockCke[i].size() != 0
742 3 : || resRepo.loopEngine[i].size() != 0 || resRepo.blockLoopEngine[i].size() != 0 || resRepo.gsa[i].size() != 0
743 3 : || resRepo.blockGsa[i].size() != 0 || resRepo.xn[i].size() != 0 || resRepo.blockXn[i].size() != 0
744 28 : || resRepo.mission.mission[i].size() != 0) {
745 33 : HCCL_INFO("DumpResRepository: dieId[%u], ms size[%u], blockMs size[%u], cke size[%u], blockCke size[%u], "
746 : "loopEngine size[%u], blockLoopEngine size[%u], gsa size[%u], blockGsa size[%u], xn size[%u], "
747 : "block xn size[%u], mission size[%u]",
748 : i, resRepo.ms[i].size(), resRepo.blockMs[i].size(), resRepo.cke[i].size(),
749 : resRepo.blockCke[i].size(), resRepo.loopEngine[i].size(), resRepo.blockLoopEngine[i].size(),
750 : resRepo.gsa[i].size(), resRepo.blockGsa[i].size(), resRepo.xn[i].size(), resRepo.blockXn[i].size(),
751 : resRepo.mission.mission[i].size());
752 : }
753 : }
754 7 : }
755 :
756 0 : std::vector<std::vector<CcuProfilingInfo>> CtxMgrImp::GetProfilingInfo(CcuTaskArg &ccuTaskArg, const uint64_t entityId)
757 : {
758 : // 根据entityId获取ctxGroup
759 0 : std::unique_lock<std::mutex> lock(contextMapMutex_);
760 :
761 : // 校验ctxGroupMap_中是否存在entityId对应的ctxGroup
762 0 : CHK_PRT_RET(ctxGroupMap_.find(entityId) == ctxGroupMap_.end(),
763 : HCCL_ERROR("[CtxMgrImp][GetProfilingInfo]entityId [%llu] is not exist", entityId),
764 : std::vector<std::vector<CcuProfilingInfo>>());
765 :
766 : // 获取每个ctx的profiling信息
767 0 : std::vector<std::vector<CcuProfilingInfo>> ccuProfilingInfo;
768 0 : for (auto &ctx : ctxGroupMap_[entityId].ctxs) {
769 0 : std::vector<CcuProfilingInfo> tmp;
770 0 : auto ret = ctx->GetCcuProfilingInfo(ccuTaskArg, tmp);
771 0 : if (ret != HcclResult::HCCL_SUCCESS) {
772 0 : THROW<CcuApiException>("GetCcuProfilingInfo is failed. ret[%d]", ret);
773 : }
774 0 : ccuProfilingInfo.push_back(tmp);
775 0 : }
776 :
777 0 : return ccuProfilingInfo;
778 0 : }
779 :
780 2 : CcuContext* CtxMgrImp::GetCtx(uint64_t executorId, uint32_t dieId, uint32_t missionId)
781 : {
782 2 : std::unique_lock<std::mutex> lock(contextMapMutex_);
783 :
784 2 : if (ctxGroupMap_.find(executorId) == ctxGroupMap_.end()) {
785 3 : HCCL_ERROR("[CtxMgrImp][GetCtx] executorId [%llu] is not exist", executorId);
786 1 : return nullptr;
787 : }
788 :
789 1 : for (auto& ctx : ctxGroupMap_[executorId].ctxs) {
790 0 : if (ctx->GetDieId() == dieId && ctx->GetMissionId() == missionId) {
791 0 : return ctx.get();
792 : }
793 : }
794 :
795 3 : HCCL_ERROR("[CtxMgrImp][GetCtx] CcuContext is not exist, dieId[%u], missionId[%u]", dieId, missionId);
796 1 : return nullptr;
797 2 : }
798 : }; // namespace Hccl
|