Line data Source code
1 : /**
2 : * Copyright (c) 2026 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_launch.h"
12 : #include "adapter_rts_common.h"
13 : #include "ccu_res.h"
14 :
15 : #include <vector>
16 :
17 : #include "ccu_device_res.h"
18 :
19 : #include "ccu_log.h"
20 : #include "ccu_types.h"
21 :
22 : #include "hcom_common.h"
23 :
24 : #include "ccu_kernel_mgr.h"
25 : #include "ccu_instance_mgr.h"
26 :
27 : #include "thread.h"
28 :
29 : #include "env_config/env_config.h" // 暂时引用orion的环境变量处理模块
30 :
31 :
32 : #include "hcomm_adapter_rts.h"
33 :
34 : #include "task_param.h"
35 :
36 : #include "ccu_assist_v1.h"
37 :
38 : #include "unified_platform/pub_inc/config_plf_log.h"
39 : using Hccl::PLF_TASK;
40 :
41 27 : CcuResult HcommCcuInsCreateLegacy(const void *resDesc, uint32_t descNum, CcuInsHandle *insHandle)
42 : {
43 27 : CCU_CHK_PTR_NULL(resDesc);
44 27 : CCU_CHK_PTR_NULL(insHandle);
45 27 : if (descNum != 1) {
46 0 : HCCL_ERROR("[%s] failed, desc num[%u] is more than expected[1].",
47 : __func__, descNum);
48 0 : return CcuResult::CCU_E_PARA;
49 : }
50 :
51 27 : auto *resDescPtr = static_cast<const CcuResDesc *>(resDesc);
52 27 : if (resDescPtr->dieId != hcomm::CCU_MAX_IODIE_NUM) {
53 0 : HCCL_ERROR("[%s] failed, ccu instance cannot be created with die id now.", __func__);
54 0 : return CcuResult::CCU_E_PARA;
55 : }
56 :
57 27 : const uint32_t devLogicId = HcclGetThreadDeviceId();
58 27 : CCU_CHK_RET(hcomm::CcuInstanceMgr::GetInstance(devLogicId).Create(resDescPtr->insType, *insHandle));
59 :
60 27 : return CcuResult::CCU_SUCCESS;
61 : }
62 :
63 1 : CcuResult HcommCcuInsCreate(const HcommCcuResDescHandle *, uint32_t, CcuInsHandle *)
64 : {
65 1 : return CcuResult::CCU_E_NOT_SUPPORT;
66 : }
67 :
68 1 : CcuResult HcommCcuInsCreateDefault(const uint32_t *, uint32_t, CcuInsHandle *)
69 : {
70 1 : return CcuResult::CCU_E_NOT_SUPPORT;
71 : }
72 :
73 1 : CcuResult HcommCcuInsDestroy(CcuInsHandle)
74 : {
75 1 : return CcuResult::CCU_E_NOT_SUPPORT;
76 : }
77 :
78 1 : CcuResult HcommCcuInsQueryResDesc(CcuInsHandle, HcommCcuResDescHandle)
79 : {
80 1 : return CcuResult::CCU_E_NOT_SUPPORT;
81 : }
82 :
83 : /**
84 : * @brief 关闭CCU特性,解初始化CCU平台层
85 : *
86 : * @param insHandle CCU实例句柄
87 : * @param curDeviceLogicId 当前设备逻辑ID
88 : * @return CcuResult 执行结果状态码,CCU_SUCCESS表示成功,其他值表示失败
89 : */
90 27 : CcuResult HcommCcuInsDestroyLegacy(CcuInsHandle insHandle, int32_t curDeviceLogicId)
91 : {
92 : // 获取当前线程的 DeviceId(线程变量)
93 27 : const int32_t threadDevId = HcclGetThreadDeviceId();
94 27 : HCCL_INFO("[%s] curDeviceLogicId[%d], threadDevId[%d]", __func__, curDeviceLogicId, threadDevId);
95 :
96 : // 先切换为目标 curDeviceLogicId
97 27 : bool isDiffDevId = false;
98 27 : if (curDeviceLogicId != threadDevId) {
99 0 : CCU_CHK_RET(hrtSetDevice(curDeviceLogicId));
100 0 : isDiffDevId = true;
101 : }
102 :
103 : // 销毁 CcuInstance
104 27 : CcuResult ret = hcomm::CcuInstanceMgr::GetInstance(curDeviceLogicId).Destroy(insHandle);
105 27 : if (ret != CCU_SUCCESS) {
106 0 : HCCL_ERROR("[%s] Destroy CcuInstance failed, ret[%d]", __func__, ret);
107 : }
108 :
109 : /// 切换回原来的 DeviceId
110 27 : if (isDiffDevId) {
111 0 : CCU_CHK_RET(hrtSetDevice(threadDevId));
112 : }
113 27 : return ret;
114 : }
115 :
116 26 : CcuResult HcommCcuKernelRegisterStart(CcuInsHandle insHandle)
117 : {
118 26 : const uint32_t devLogicId = HcclGetThreadDeviceId();
119 26 : auto *ccuIns = hcomm::CcuInstanceMgr::GetInstance(devLogicId).Get(insHandle);
120 26 : CCU_CHK_PTR_NULL(ccuIns);
121 :
122 26 : CCU_CHK_RET(ccuIns->BeginRegister());
123 :
124 26 : CcuResult ret = ccuIns->Reset();
125 26 : if (ret != CcuResult::CCU_SUCCESS) {
126 0 : (void)ccuIns->EndRegister();
127 0 : HCCL_ERROR("[%s] failed, Reset failed[%d], rollback register state.", __func__, ret);
128 0 : return ret;
129 : }
130 26 : return CcuResult::CCU_SUCCESS;
131 : }
132 :
133 26 : static CcuResult CcuKernelTryRegister(hcomm::CcuInstance *ccuIns, hcomm::CcuResPack *resPack,
134 : uint32_t devLogicId, const char *kernelFuncName, const void *kernelFunc,
135 : const void **kernelArgs, uint32_t argNum, CcuKernelHandle &newHandle)
136 : {
137 : CCU_EXCEPTION_HANDLE_BEGIN
138 26 : auto &kernelMgr = hcomm::CcuKernelMgr::GetInstance(devLogicId);
139 26 : CCU_CHK_RET(kernelMgr.Register(*resPack, kernelFuncName,
140 : kernelFunc, kernelArgs, argNum, newHandle));
141 19 : CCU_CHK_RET(ccuIns->SaveKernel(newHandle));
142 7 : CCU_EXCEPTION_HANDLE_END
143 19 : return CcuResult::CCU_SUCCESS;
144 : }
145 :
146 26 : CcuResult HcommCcuKernelRegister(CcuInsHandle insHandle, uint32_t dieId,
147 : const char *kernelFuncName, const void *kernelFunc,
148 : const void **kernelArgs, uint32_t argNum,
149 : CcuKernelHandle *kernelHandle)
150 : {
151 26 : HCCL_RUN_INFO("Entry-%s", __func__);
152 26 : HcclUs startut = TIME_NOW();
153 :
154 26 : CCU_CHK_PTR_NULL(kernelFunc);
155 26 : CCU_CHK_PTR_NULL(kernelHandle);
156 :
157 26 : if (argNum != 0) {
158 26 : CCU_CHK_PTR_NULL(kernelArgs);
159 : }
160 :
161 : (void)dieId; // dieId 当前预留不使用
162 :
163 26 : const uint32_t devLogicId = HcclGetThreadDeviceId();
164 26 : auto *ccuIns = hcomm::CcuInstanceMgr::GetInstance(devLogicId).Get(insHandle);
165 26 : CCU_CHK_PTR_NULL(ccuIns);
166 :
167 26 : CCU_CHK_RET(ccuIns->CheckRegistering());
168 :
169 26 : auto *resPack = ccuIns->GetResPack();
170 26 : CCU_CHK_PTR_NULL(resPack);
171 :
172 26 : CcuKernelHandle newHandle{0};
173 26 : CcuResult ret = CcuKernelTryRegister(ccuIns, resPack, devLogicId, kernelFuncName,
174 : kernelFunc, kernelArgs, argNum, newHandle);
175 26 : if (ret != CcuResult::CCU_SUCCESS) {
176 7 : ccuIns->AbortRegister();
177 7 : if (CCU_CHK_RES_UNAVAIL(ret)) {
178 0 : HCCL_WARNING("[%s] register kernel resource unavailable[%d], current register round aborted.",
179 : __func__, ret);
180 0 : return CcuResult::CCU_E_UNAVAIL;
181 : } else {
182 7 : HCCL_ERROR("[%s] failed, register kernel failed[%d], current register round aborted.",
183 : __func__, ret);
184 7 : return ret;
185 : }
186 : }
187 :
188 19 : *kernelHandle = newHandle;
189 19 : HCCL_INFO("[%s] success, take time [%lld]us.",
190 : __func__, DURATION_US(TIME_NOW() - startut));
191 19 : return CcuResult::CCU_SUCCESS;
192 : }
193 :
194 19 : CcuResult HcommCcuKernelRegisterEnd(CcuInsHandle insHandle)
195 : {
196 19 : const uint32_t devLogicId = HcclGetThreadDeviceId();
197 19 : auto *ccuIns = hcomm::CcuInstanceMgr::GetInstance(devLogicId).Get(insHandle);
198 19 : CCU_CHK_PTR_NULL(ccuIns);
199 :
200 19 : CCU_CHK_RET(ccuIns->EndRegister());
201 19 : const auto &newKernels = ccuIns->GetUntranslatedKernels();
202 :
203 19 : auto &kernelMgr = hcomm::CcuKernelMgr::GetInstance(devLogicId);
204 : // 当前翻译内部流程可能抛异常
205 : CCU_EXCEPTION_HANDLE_BEGIN
206 19 : CCU_CHK_RET(kernelMgr.Translate(newKernels));
207 0 : CCU_EXCEPTION_HANDLE_END
208 :
209 19 : return CcuResult::CCU_SUCCESS;
210 : }
211 :
212 3 : static std::shared_ptr<std::vector<Hccl::CcuProfilingInfo>> ConstructCcuDetailInfo(
213 : const std::vector<hcomm::CcuProfilingInfo> &allCcuProfilingInfo, bool isSaveProfilingData)
214 : {
215 3 : if (allCcuProfilingInfo.empty() || !isSaveProfilingData) {
216 0 : return nullptr;
217 : }
218 :
219 3 : std::vector<Hccl::CcuProfilingInfo> converted(allCcuProfilingInfo.size());
220 12 : for (u32 idx = 0; idx < allCcuProfilingInfo.size(); ++idx) {
221 9 : auto &src = allCcuProfilingInfo[idx];
222 9 : auto &dst = converted[idx];
223 9 : dst.name = src.name;
224 9 : dst.type = src.type;
225 9 : dst.dieId = src.dieId;
226 9 : dst.missionId = src.missionId;
227 9 : dst.instrId = src.instrId;
228 9 : dst.reduceOpType = src.reduceOpType;
229 9 : dst.inputDataType = src.inputDataType;
230 9 : dst.outputDataType = src.outputDataType;
231 9 : dst.dataSize = src.dataSize;
232 9 : dst.ckeId = src.ckeId;
233 9 : dst.mask = src.mask;
234 9 : (void)memcpy_s(dst.channelId, sizeof(dst.channelId), src.channelId, sizeof(src.channelId));
235 9 : (void)memcpy_s(dst.channelHandle, sizeof(dst.channelHandle), src.channelHandle, sizeof(src.channelHandle));
236 : }
237 3 : return std::make_shared<std::vector<Hccl::CcuProfilingInfo>>(std::move(converted));
238 3 : }
239 :
240 5 : static Hccl::TaskParam ConstructCcuTaskParam(const hcomm::CcuTaskParam &ccuParam,
241 : const CcuKernelHandle kernelHandle,
242 : const std::shared_ptr<std::vector<Hccl::CcuProfilingInfo>> &ccuDetailInfo,
243 : u64 beginTime, u64 endTime, bool isMaster)
244 : {
245 5 : Hccl::TaskParam taskParam{};
246 5 : taskParam.beginTime = beginTime;
247 5 : taskParam.endTime = endTime;
248 5 : taskParam.taskType = Hccl::TaskParamType::TASK_CCU;
249 5 : taskParam.taskPara.Ccu.dieId = ccuParam.dieId;
250 5 : taskParam.taskPara.Ccu.missionId = ccuParam.missionId;
251 5 : taskParam.taskPara.Ccu.execMissionId = ccuParam.missionId;
252 5 : taskParam.taskPara.Ccu.instrId = ccuParam.instStartId;
253 5 : taskParam.taskPara.Ccu.executeId = kernelHandle;
254 5 : taskParam.taskPara.Ccu.ccuKernelHandle = kernelHandle;
255 5 : taskParam.isMaster = isMaster;
256 5 : taskParam.ccuDetailInfo = ccuDetailInfo;
257 5 : return taskParam;
258 : }
259 :
260 3 : static void LogCcuTaskInfo(const std::vector<hcomm::CcuTaskParam> &ccuParams,
261 : const CcuKernelHandle kernelHandle)
262 : {
263 3 : if (!HcclCheckLogLevel(HCCL_LOG_INFO)) {
264 0 : return;
265 : }
266 3 : const uint32_t execTimeOutSec = Hccl::EnvConfig::GetInstance().GetRtsConfig().GetExecTimeOut();
267 8 : for (u32 idx = 0; idx < ccuParams.size(); idx++) {
268 5 : const auto ¶m = ccuParams[idx];
269 5 : PLF_CONFIG_INFO(PLF_TASK, "[%s] start ccu task, dieId[%u], missionId[%u], execMissionId[%u], instStartId[%u], instCnt[%u], "
270 : "argSize[%u], timeout[%u]s, executeId[0x%llx], ccuKernelHandle[0x%llx]",
271 : __func__, param.dieId, param.missionId, param.missionId,
272 : param.instStartId, param.instCnt, param.argSize, execTimeOutSec,
273 : kernelHandle, kernelHandle);
274 : }
275 : }
276 :
277 3 : static void ConstructProfilingInfoLog(
278 : const std::vector<hcomm::CcuProfilingInfo> &allCcuProfilingInfo)
279 : {
280 3 : if (!HcclCheckLogLevel(HCCL_LOG_INFO)) {
281 0 : return;
282 : }
283 12 : for (const hcomm::CcuProfilingInfo& profInfo : allCcuProfilingInfo) {
284 13 : for (int idx = 0; idx < hcomm::CCU_MAX_CHANNEL_NUM; idx++) {
285 13 : if (profInfo.channelId[idx] == hcomm::INVALID_VALUE_CHANNELID) {
286 9 : break;
287 : }
288 4 : HCCL_INFO("[%s]idx[%u]: channelId[%u], channelHandle[0x%llx]",
289 : __func__, idx, profInfo.channelId[idx], profInfo.channelHandle[idx]);
290 : }
291 : }
292 : }
293 :
294 3 : static CcuResult ConstructProfilingInfo(hcomm::CcuKernel *kernel,
295 : const uint64_t *taskArgs, uint32_t argNum,
296 : std::vector<hcomm::CcuProfilingInfo> &allCcuProfilingInfo, bool isSaveProfilingData)
297 : {
298 3 : if (!isSaveProfilingData) {
299 0 : return CcuResult::CCU_SUCCESS;
300 : }
301 :
302 3 : CCU_CHK_RET(kernel->GetCcuProfilingInfo(taskArgs, argNum, allCcuProfilingInfo));
303 3 : if (allCcuProfilingInfo.empty()) {
304 0 : return CcuResult::CCU_SUCCESS;
305 : }
306 3 : ConstructProfilingInfoLog(allCcuProfilingInfo);
307 3 : return CcuResult::CCU_SUCCESS;
308 : }
309 :
310 5 : static CcuResult ReportCcuTaskDfx(const ThreadHandle threadHandle,
311 : const Hccl::TaskParam &taskParam)
312 : {
313 5 : auto *rtsThread = reinterpret_cast<hccl::Thread *>(threadHandle);
314 5 : CCU_CHK_PTR_NULL(rtsThread);
315 :
316 5 : auto callback = rtsThread->GetCallback();
317 5 : if (!callback) {
318 5 : HCCL_WARNING("[%s] task info callback is not registered on thread, skip ccu profiling report.", __func__);
319 5 : return CcuResult::CCU_SUCCESS;
320 : }
321 0 : u32 streamId = INVALID_UINT;
322 0 : u32 taskId = INVALID_UINT;
323 0 : CCU_CHK_RET(hrtGetTaskIdAndStreamID(taskId, streamId));
324 0 : CCU_CHK_RET(callback(streamId, taskId, taskParam, INVALID_U64));
325 0 : return CcuResult::CCU_SUCCESS;
326 5 : }
327 :
328 5 : static HcclResult LaunchCcuTasks(const hcomm::CcuTaskParam ¶m, const aclrtStream stream)
329 : {
330 5 : const uint32_t execTimeOutSec = Hccl::EnvConfig::GetInstance().GetRtsConfig().GetExecTimeOut();
331 5 : rtCcuTaskInfo_t taskInfo{};
332 5 : taskInfo.dieId = param.dieId;
333 5 : taskInfo.missionId = param.missionId;
334 5 : taskInfo.instStartId = param.instStartId;
335 5 : taskInfo.instCnt = param.instCnt;
336 5 : taskInfo.key = param.key;
337 5 : taskInfo.argSize = param.argSize;
338 5 : taskInfo.timeout = execTimeOutSec;
339 15 : std::copy(std::begin(param.args), std::end(param.args), std::begin(taskInfo.args));
340 :
341 5 : auto ret = rtCCULaunch(&taskInfo, stream);
342 5 : if (ret != RT_ERROR_NONE) {
343 0 : HCCL_ERROR("[%s] failed to launch ccu, ret[%d]", __func__, ret);
344 0 : return HcclResult::HCCL_E_RUNTIME;
345 : }
346 :
347 5 : return HcclResult::HCCL_SUCCESS;
348 : }
349 :
350 3 : CcuResult HcommCcuKernelLaunch(ThreadHandle threadHandle,
351 : CcuKernelHandle kernelHandle, const void *taskArgs, uint32_t argNum)
352 : {
353 3 : const auto &startus = TIME_NOW();
354 :
355 3 : CHK_PRT_RET(threadHandle == 0, HCCL_ERROR("[%s] failed, thread handle is empty.", __func__), CcuResult::CCU_E_PARA);
356 3 : CHK_PRT_RET(kernelHandle == 0, HCCL_ERROR("[%s] failed, kernel handle is empty.", __func__), CcuResult::CCU_E_PARA);
357 3 : CHK_PRT_RET(argNum > 0 && taskArgs == nullptr, HCCL_ERROR("[%s] failed, taskArgs is nullptr while argNum[%u] > 0.", __func__, argNum), CcuResult::CCU_E_PTR);
358 :
359 3 : PLF_CONFIG_INFO(PLF_TASK, "[HcommCcuKernelLaunch] threadHandle[0x%llx] kernelHandle[0x%llx].", threadHandle, kernelHandle);
360 :
361 3 : const auto *rtsThread = reinterpret_cast<hccl::Thread *>(threadHandle);
362 3 : const auto *threadStream = rtsThread->GetStream();
363 3 : CCU_CHK_PTR_NULL(threadStream);
364 3 : auto *streamPtr = threadStream->ptr();
365 3 : CCU_CHK_PTR_NULL(streamPtr);
366 :
367 3 : const uint32_t devLogicId = HcclGetThreadDeviceId();
368 3 : auto &kernelMgr = hcomm::CcuKernelMgr::GetInstance(devLogicId);
369 3 : auto *kernel = kernelMgr.GetKernel(kernelHandle);
370 3 : CCU_CHK_PTR_NULL(kernel);
371 :
372 : CCU_EXCEPTION_HANDLE_BEGIN
373 3 : std::vector<hcomm::CcuTaskParam> taskParams{};
374 3 : auto ret = kernel->GeneTaskParams(static_cast<const uint64_t *>(taskArgs), argNum, taskParams);
375 3 : CHK_PRT_RET(ret != CcuResult::CCU_SUCCESS,
376 : HCCL_ERROR("[%s] failed, threadHandle[0x%llx] kernelHandle[0x%llx].",
377 : __func__, threadHandle, kernelHandle),
378 : ret);
379 :
380 3 : if (taskParams.empty()) {
381 0 : HCCL_INFO("[%s] passed, ccu params are empty.", __func__);
382 0 : return CcuResult::CCU_SUCCESS;
383 : }
384 3 : bool isProfilingEnabledL1 = Hccl::ProfilingHandler::GetInstance().GetHcclL1State();
385 3 : bool isProfilingEnabledL0 = Hccl::ProfilingHandler::GetInstance().GetHcclL0State();
386 3 : bool isOpbase = Hccl::ProfilingHandler::GetInstance().GetIsOpbase();
387 3 : bool isSaveProfilingData = !(!isProfilingEnabledL1 && !isProfilingEnabledL0 && isOpbase);
388 :
389 3 : std::vector<hcomm::CcuProfilingInfo> allCcuProfilingInfo;
390 3 : CCU_CHK_RET(ConstructProfilingInfo(kernel, static_cast<const uint64_t *>(taskArgs), argNum, allCcuProfilingInfo, isSaveProfilingData));
391 3 : LogCcuTaskInfo(taskParams, kernelHandle);
392 3 : auto ccuDetailInfo = ConstructCcuDetailInfo(allCcuProfilingInfo, isSaveProfilingData);
393 8 : for (u32 idx = 0; idx < taskParams.size(); idx++) {
394 5 : u64 beginTime = Hccl::DlProfFunction::GetInstance().dlMsprofSysCycleTime();
395 5 : CCU_CHK_RET(LaunchCcuTasks(taskParams[idx], streamPtr));
396 5 : u64 endTime = Hccl::DlProfFunction::GetInstance().dlMsprofSysCycleTime();
397 5 : Hccl::TaskParam taskParam = ConstructCcuTaskParam(taskParams[idx], kernelHandle, ccuDetailInfo,
398 5 : beginTime, endTime, rtsThread->GetMaster());
399 5 : CCU_CHK_RET(ReportCcuTaskDfx(threadHandle, taskParam));
400 5 : }
401 3 : CCU_EXCEPTION_HANDLE_END
402 3 : HCCL_INFO("[%s] success, take time [%lld]us.",
403 : __func__, DURATION_US(TIME_NOW() - startus));
404 3 : return CcuResult::CCU_SUCCESS;
405 : }
406 :
407 0 : CcuResult HcommCcuGetMemToken(uint64_t srcVa, uint64_t size, uint64_t *tokenInfo)
408 : {
409 0 : CCU_CHK_PTR_NULL(tokenInfo);
410 :
411 0 : if (srcVa == 0 || size == 0) {
412 0 : HCCL_ERROR("[%s] failed, srcVa[%llx] size[%llu] should not be 0.",
413 : __func__, srcVa, size);
414 0 : return CcuResult::CCU_E_PARA;
415 : }
416 : // 注意token信息属于安全信息,均不允许打印
417 0 : hcomm::rtMemUbTokenInfo info{};
418 0 : info.va = srcVa;
419 0 : info.size = size;
420 0 : CCU_CHK_RET(hcomm::RtsUbDevQueryInfo(QUERY_PROCESS_TOKEN, info));
421 0 : *tokenInfo = hcomm::CcuRep::CcuCombineTokenInfo(info.tokenId, info.tokenValue, 1);
422 :
423 0 : return CcuResult::CCU_SUCCESS;
424 : }
|