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 "aicpu_ts_channel_helper.h"
12 : #include "channel_process.h"
13 : #include "channel.h"
14 : #include "launch_aicpu.h"
15 : #include "launch_device.h"
16 : #include "comm_engine_utils.h"
17 : #include "adapter_rts_common.h"
18 :
19 : using namespace hcomm;
20 :
21 : aclrtBinHandle AicpuTsChannelHelper::g_BinHandle = nullptr;
22 : std::mutex AicpuTsChannelHelper::g_BinHandleMtx;
23 :
24 0 : HcclResult AicpuTsChannelHelper::TryFillCtxList(
25 : ChannelHandle* hostChannelHandles, uint32_t listNum, const hccl::DeviceMem& deviceChannelList, void*& outCtxList,
26 : bool& isCtxMode)
27 : {
28 0 : auto* firstCh = reinterpret_cast<Channel*>(hostChannelHandles[0]);
29 0 : CHK_PTR_NULL(firstCh);
30 0 : auto* firstHelper = firstCh->GetAicpuTsHelper();
31 0 : CHK_PTR_NULL(firstHelper);
32 0 : isCtxMode = (firstHelper->GetCtxPtr() != nullptr);
33 0 : HCCL_INFO("[%s] isCtxMode[%d].", __func__, isCtxMode);
34 0 : if (!isCtxMode) {
35 0 : return HCCL_SUCCESS;
36 : }
37 0 : std::vector<void*> ctxVec(listNum);
38 0 : for (uint32_t i = 0; i < listNum; i++) {
39 0 : auto* ch = reinterpret_cast<Channel*>(hostChannelHandles[i]);
40 0 : CHK_PTR_NULL(ch);
41 0 : auto* helper = ch->GetAicpuTsHelper();
42 0 : ctxVec[i] = helper ? helper->GetCtxPtr() : nullptr;
43 : }
44 0 : HcclResult ret = hrtMemSyncCopy(
45 0 : deviceChannelList.ptr(), listNum * sizeof(void*), ctxVec.data(), listNum * sizeof(void*),
46 : HcclRtMemcpyKind::HCCL_RT_MEMCPY_KIND_HOST_TO_DEVICE);
47 0 : if (ret != HCCL_SUCCESS) {
48 0 : HCCL_ERROR("[TryFillCtxList] hrtMemSyncCopy failed, ret[%d]", ret);
49 0 : return ret;
50 : }
51 0 : outCtxList = deviceChannelList.ptr();
52 0 : return HCCL_SUCCESS;
53 0 : }
54 :
55 18 : HcclResult AicpuTsChannelHelper::EnsureKernelBinLoaded(CommEngine engine)
56 : {
57 18 : if (engine != COMM_ENGINE_AICPU && engine != COMM_ENGINE_AICPU_TS) {
58 15 : HCCL_INFO(
59 : "[%s] engine[%s] kernel loading not required", __func__,
60 : GetEnumToString(GetCommEngineStatusStrMap(), engine).c_str());
61 15 : return HCCL_SUCCESS;
62 : }
63 3 : std::lock_guard<std::mutex> lock(g_BinHandleMtx);
64 3 : if (g_BinHandle != nullptr) {
65 0 : return HCCL_SUCCESS;
66 : }
67 3 : std::string jsonPath;
68 3 : CHK_RET(hccl::GetKernelFilePath(jsonPath));
69 3 : jsonPath += "ccl_kernel.json";
70 :
71 3 : HcclResult ret = hccl::LoadBinaryFromFile(jsonPath.c_str(), ACL_RT_BINARY_LOAD_OPT_CPU_KERNEL_MODE, 0, g_BinHandle);
72 3 : CHK_PRT_RET(
73 : ret != HCCL_SUCCESS, HCCL_ERROR("[%s] load aicpu file fail, path[%s]", __func__, jsonPath.c_str()), ret);
74 3 : return HCCL_SUCCESS;
75 3 : }
76 :
77 3 : HcclResult AicpuTsChannelHelper::LaunchKernel(
78 : const ChannelHandle* channelList, uint32_t listNum, [[maybe_unused]] CommEngine engine,
79 : const HcommChannelDesc* channelDescs, aclrtBinHandle binHandle)
80 : {
81 3 : CHK_PTR_NULL(channelList);
82 3 : CHK_PRT_RET((listNum == 0), HCCL_ERROR("[%s]Invalid listNum, listNum[%u]", __func__, listNum), HCCL_E_PARA);
83 :
84 : // 过滤出未就绪的子集,避免重复下 kernel 导致 device 侧 channel 对象泄漏
85 3 : std::vector<ChannelHandle> subHostHandles;
86 3 : std::vector<HcommChannelDesc> subDescs;
87 3 : std::vector<Channel*> subChannels;
88 3 : subHostHandles.reserve(listNum);
89 3 : subDescs.reserve(listNum);
90 3 : subChannels.reserve(listNum);
91 6 : for (uint32_t i = 0; i < listNum; i++) {
92 3 : void* ch = nullptr;
93 3 : CHK_RET(ChannelProcess::ChannelGet(channelList[i], &ch));
94 3 : CHK_PTR_NULL(ch);
95 3 : auto* channel = static_cast<Channel*>(ch);
96 3 : if (channel->IsDeviceEntityReady()) {
97 3 : continue;
98 : }
99 0 : subHostHandles.push_back(reinterpret_cast<ChannelHandle>(ch));
100 0 : subDescs.push_back(channelDescs[i]);
101 0 : subChannels.push_back(channel);
102 : }
103 3 : if (subHostHandles.empty()) {
104 3 : HCCL_INFO("[%s] all channels already ready, skip kernel launch.", __func__);
105 3 : return HCCL_SUCCESS;
106 : }
107 : // 序列化 + kernel launch
108 0 : std::vector<ChannelHandle> devHandles(subHostHandles.size());
109 0 : CHK_RET(ChannelProcess::LaunchChannelKernel(
110 : devHandles.data(), subHostHandles.data(), subDescs.data(), subHostHandles.size(), binHandle));
111 0 : for (auto* channel : subChannels) {
112 0 : channel->SetDeviceEntityReady();
113 : }
114 0 : HCCL_INFO("[%s] aicpu kernel launch success, launched[%zu]/total[%u].", __func__, subHostHandles.size(), listNum);
115 0 : return HCCL_SUCCESS;
116 3 : }
117 :
118 7 : HcclResult AicpuTsChannelHelper::HandleStatus(
119 : const ChannelHandle* channelList, uint32_t listNum, CommEngine engine, const HcommChannelDesc* channelDescs,
120 : const std::vector<int32_t>& linkStatusList, int32_t* statusList)
121 : {
122 7 : bool allReady = true;
123 11 : for (uint32_t i = 0; i < listNum; i++) {
124 8 : if (linkStatusList[i] != HCOMM_CHANNEL_STATUS_READY) {
125 4 : allReady = false;
126 4 : break;
127 : }
128 : }
129 7 : if (!allReady) {
130 9 : for (uint32_t i = 0; i < listNum; i++) {
131 5 : if (linkStatusList[i] == HCOMM_CHANNEL_STATUS_FAILED) {
132 2 : statusList[i] = HCOMM_CHANNEL_STATUS_FAILED;
133 3 : } else if (linkStatusList[i] == HCOMM_CHANNEL_STATUS_TIMEOUT) {
134 1 : statusList[i] = HCOMM_CHANNEL_STATUS_TIMEOUT;
135 : } else {
136 2 : statusList[i] = HCOMM_CHANNEL_STATUS_CONNECTING;
137 : }
138 : }
139 4 : return HCCL_SUCCESS;
140 : }
141 3 : CHK_RET(EnsureKernelBinLoaded(engine));
142 3 : HcclResult kernelRet = LaunchKernel(channelList, listNum, engine, channelDescs, g_BinHandle);
143 3 : if (kernelRet != HCCL_SUCCESS) {
144 0 : HCCL_ERROR("[%s] LaunchKernel failed, ret[%d]", __func__, kernelRet);
145 0 : return HCCL_E_INTERNAL;
146 : }
147 6 : for (uint32_t i = 0; i < listNum; i++) {
148 3 : statusList[i] = linkStatusList[i];
149 : }
150 3 : return HCCL_SUCCESS;
151 : }
152 :
153 3 : HcclResult AicpuTsChannelHelper::PreAllocChannels(
154 : ChannelHandle* targetChannels, ChannelHandle* userChannels, [[maybe_unused]] HcommChannelDesc* channelDescs,
155 : uint32_t channelNum)
156 : {
157 3 : CHK_PTR_NULL(targetChannels);
158 3 : CHK_PTR_NULL(userChannels);
159 3 : CHK_PRT_RET(
160 : (channelNum == 0), HCCL_ERROR("[%s]Invalid channelNum, channelNum[%u]", __func__, channelNum), HCCL_E_PARA);
161 :
162 5 : for (uint32_t i = 0; i < channelNum; i++) {
163 3 : auto* channel = reinterpret_cast<Channel*>(targetChannels[i]);
164 3 : CHK_PTR_NULL(channel);
165 2 : auto* helper = channel->GetAicpuTsHelper();
166 2 : CHK_PTR_NULL(helper);
167 2 : CHK_RET(helper->PreAllocCtx(userChannels[i]));
168 : // 清零 ctx device 内存,防止脏数据 magic 误匹配
169 2 : CHK_RET(hrtMemSet(helper->GetCtxPtr(), sizeof(HcommAicpuChannelCtx), sizeof(HcommAicpuChannelCtx)));
170 : }
171 :
172 2 : CHK_RET(ChannelProcess::FillChannelD2HMap(userChannels, targetChannels, channelNum));
173 2 : return HCCL_SUCCESS;
174 : }
|