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 "flush_handle.h"
12 : #include <stdlib.h>
13 : #include "hccp.h"
14 : #include "orion_adapter_rts.h"
15 :
16 : namespace Hccl {
17 :
18 7 : FlushHandle::FlushHandle() : flushIsInitialized(false) {}
19 :
20 7 : FlushHandle::~FlushHandle() { Destroy(); }
21 :
22 5 : HcclResult FlushHandle::Init(IpAddress ip, u32 devPhyId)
23 : {
24 5 : int lbMax = 0;
25 : // 获取 RDMA handle
26 5 : CHK_RET(GetRdmaHandle(ip, devPhyId, &rdmaHandle));
27 :
28 : // 获取 LbMax
29 5 : CHK_RET(GetLbMax(&lbMax));
30 :
31 5 : if (lbMax > 0) {
32 2 : SetFlushOpcodeSupport();
33 : }
34 :
35 : // 分配 Local Memory
36 5 : CHK_RET(AllocateLocalMemory());
37 :
38 : // 分配 Device Memory
39 8 : CHK_RET(AllocateDeviceMemory());
40 :
41 : // 创建环回 QP
42 7 : CHK_RET(CreateLoopbackQp());
43 :
44 : // 注册 Local MR
45 6 : CHK_RET(RegisterLocalMr());
46 :
47 : // 注册 Remote MR
48 2 : CHK_RET(RegisterRemoteMr());
49 :
50 2 : flushIsInitialized = true;
51 2 : return HCCL_SUCCESS;
52 : }
53 :
54 5 : HcclResult FlushHandle::GetLbMax(int* lbMax) const
55 : {
56 5 : int ret = RaGetLbMax(rdmaHandle, lbMax);
57 5 : if (ret != 0) {
58 0 : HCCL_ERROR("[GetLbMax]Failed to get load balance max value. error_code=%d.", ret);
59 0 : return HCCL_E_ROCE_CONNECT;
60 : }
61 15 : HCCL_INFO("[GetLbMax]Get load balance max value successfully, lbMax = %d", *lbMax);
62 5 : return HCCL_SUCCESS;
63 : }
64 :
65 13 : HcclResult FlushHandle::Destroy()
66 : {
67 13 : HcclResult finalResult = HCCL_SUCCESS;
68 13 : if (remoteMrHandle != nullptr) {
69 4 : finalResult = std::max(finalResult, DeregisterMr(remoteMrHandle, "Remote"));
70 : }
71 13 : if (localMrHandle != nullptr) {
72 6 : finalResult = std::max(finalResult, DeregisterMr(localMrHandle, "Local"));
73 : }
74 13 : finalResult = std::max(finalResult, DestroyLoopbackQp());
75 13 : finalResult = std::max(finalResult, FreeLocalMemory());
76 13 : finalResult = std::max(finalResult, FreeDeviceMemory());
77 13 : return finalResult;
78 : }
79 :
80 5 : HcclResult FlushHandle::GetRdmaHandle(IpAddress ip, u32 devPhyId, void** rdmaHandle) const
81 : {
82 : *rdmaHandle
83 5 : = RdmaHandleManager::GetInstance().GetByAddr(devPhyId, LinkProtoType::RDMA, ip, PortDeploymentType::HOST_NET);
84 5 : CHK_PTR_NULL(*rdmaHandle);
85 :
86 15 : HCCL_DEBUG("[GetRdmaHandle]RDMA handle initialized. ");
87 :
88 5 : return HCCL_SUCCESS;
89 : }
90 :
91 5 : HcclResult FlushHandle::AllocateLocalMemory()
92 : {
93 5 : u64 bufferSize = FLUSH_BUFFER_SIZE;
94 5 : if (flushOpcodeSupport_) {
95 : // 1825 主动排空要求使用device 内存
96 2 : localMem = HrtMalloc(bufferSize, static_cast<int>(ACL_MEM_TYPE_HIGH_BAND_WIDTH));
97 : } else {
98 3 : localMem = malloc(bufferSize);
99 : }
100 :
101 5 : if (localMem == nullptr) {
102 0 : HcclResult eRet = Destroy();
103 0 : HCCL_ERROR("[%s]Failed to Allocate Local Memory. Destroy Flush code=%d", __func__, eRet);
104 0 : return HCCL_E_MEMORY;
105 : }
106 15 : HCCL_DEBUG("[%s]Local memory allocated at %p, size=%u", __func__, localMem, bufferSize);
107 5 : return HCCL_SUCCESS;
108 : }
109 :
110 5 : HcclResult FlushHandle::AllocateDeviceMemory()
111 : {
112 5 : u64 bufferSize = FLUSH_BUFFER_SIZE;
113 5 : deviceMem = HrtMalloc(bufferSize, static_cast<int>(ACL_MEM_TYPE_HIGH_BAND_WIDTH));
114 5 : if (deviceMem == nullptr) {
115 1 : HcclResult eRet = Destroy();
116 3 : HCCL_ERROR("[AllocateDeviceMemory]Failed to Allocate Device Memory. Destroy Flush code=%d", eRet);
117 1 : return HCCL_E_MEMORY;
118 : }
119 12 : HCCL_DEBUG("[AllocateDeviceMemory]Device memory allocated at %p, size=%u", deviceMem, bufferSize);
120 4 : return HCCL_SUCCESS;
121 : }
122 :
123 4 : HcclResult FlushHandle::CreateLoopbackQp()
124 : {
125 4 : int ret = RaLoopbackQpCreate(rdmaHandle, &loopBackQpParam, &qpHandle);
126 4 : if (ret != 0) {
127 1 : HcclResult eRet = Destroy();
128 3 : HCCL_ERROR("[CreateLoopbackQp]Failed to create loopback QP. error_code=%d. Destroy Flush code=%d", ret, eRet);
129 1 : return HCCL_E_ROCE_CONNECT;
130 : }
131 9 : HCCL_DEBUG("[CreateLoopbackQp]Loopback QP created successfully. QP Handle=%p", qpHandle);
132 3 : return HCCL_SUCCESS;
133 : }
134 :
135 3 : HcclResult FlushHandle::RegisterLocalMr()
136 : {
137 3 : u64 bufferSize = FLUSH_BUFFER_SIZE;
138 3 : loopBackQpMrLocalInfo.addr = localMem;
139 3 : loopBackQpMrLocalInfo.size = bufferSize;
140 3 : loopBackQpMrLocalInfo.access = RA_ACCESS_LOCAL_WRITE;
141 :
142 3 : int localRet = RaRegisterMr(rdmaHandle, &loopBackQpMrLocalInfo, &localMrHandle);
143 3 : if (localRet != 0 || localMrHandle == nullptr) {
144 3 : HCCL_ERROR(
145 : "[RegisterLocalMr]Failed to register local MR. localMrHandle=0x%p, error_code=%d", localMrHandle, localRet);
146 1 : HcclResult eRet = Destroy();
147 3 : HCCL_ERROR(
148 : "[RegisterLocalMr]Failed to register local MR. error_code=%d. Destroy Flush code=%d", localRet, eRet);
149 1 : return HCCL_E_MEMORY;
150 : }
151 6 : HCCL_DEBUG("[RegisterLocalMr]Local MR registered successfully. MR Handle=0x%p", localMrHandle);
152 2 : return HCCL_SUCCESS;
153 : }
154 :
155 2 : HcclResult FlushHandle::RegisterRemoteMr()
156 : {
157 2 : u64 bufferSize = FLUSH_BUFFER_SIZE;
158 2 : loopBackQpMrRemoteInfo.addr = deviceMem;
159 2 : loopBackQpMrRemoteInfo.size = bufferSize;
160 2 : loopBackQpMrRemoteInfo.access = static_cast<int>(
161 : static_cast<unsigned int>(RA_ACCESS_REMOTE_WRITE) | static_cast<unsigned int>(RA_ACCESS_LOCAL_WRITE)
162 : | static_cast<unsigned int>(RA_ACCESS_REMOTE_READ) | static_cast<unsigned int>(RA_ACCESS_REMOTE_ATOMIC));
163 :
164 2 : int remoteRet = RaRegisterMr(rdmaHandle, &loopBackQpMrRemoteInfo, &remoteMrHandle);
165 2 : if (remoteRet != 0 || remoteMrHandle == nullptr) {
166 0 : HCCL_ERROR(
167 : "[RegisterRemoteMr]Failed to register remote MR. remoteMrHandle=0x%p, error_code=%d", remoteMrHandle,
168 : remoteRet);
169 0 : HcclResult eRet = Destroy();
170 0 : HCCL_ERROR(
171 : "[RegisterLocalMr]Failed to register remote MR. error_code=%d. Destroy Flush code=%d", remoteRet, eRet);
172 0 : return HCCL_E_MEMORY;
173 : }
174 6 : HCCL_DEBUG("[RegisterRemoteMr]Remote MR registered successfully. MR Handle=0x%p", remoteMrHandle);
175 2 : return HCCL_SUCCESS;
176 : }
177 :
178 : // 销毁 MR
179 5 : HcclResult FlushHandle::DeregisterMr(MrHandle& mrHandle, std::string logTag) const
180 : {
181 15 : HCCL_DEBUG("[DeregisterMr] Starting to destroy %s MR...", logTag.c_str());
182 :
183 5 : if (mrHandle == nullptr || rdmaHandle == nullptr) {
184 0 : HCCL_DEBUG("[DeregisterMr] %s MR is already null, skipping.", logTag.c_str());
185 0 : return HCCL_SUCCESS;
186 : }
187 :
188 5 : int ret = RaDeregisterMr(rdmaHandle, mrHandle);
189 5 : if (ret != 0) {
190 0 : HCCL_ERROR(
191 : "[DeregisterMr] Failed to deregister %s MR, mrHandle=0x%p, error_code=%d.", logTag.c_str(), mrHandle, ret);
192 0 : mrHandle = nullptr; // 防止重复调用
193 0 : return HCCL_E_INTERNAL;
194 : }
195 :
196 5 : mrHandle = nullptr;
197 15 : HCCL_DEBUG("[DeregisterMr] %s MR successfully deregistered.", logTag.c_str());
198 5 : return HCCL_SUCCESS;
199 : }
200 :
201 : // 销毁环回 QP
202 13 : HcclResult FlushHandle::DestroyLoopbackQp()
203 : {
204 39 : HCCL_DEBUG("[DestroyLoopbackQp] Starting to destroy loopback QP...");
205 :
206 13 : if (qpHandle == nullptr) {
207 36 : HCCL_DEBUG("[DestroyLoopbackQp] QP already null, skipping.");
208 12 : return HCCL_SUCCESS;
209 : }
210 :
211 1 : int ret = RaQpDestroy(qpHandle);
212 1 : if (ret != 0) {
213 0 : HCCL_ERROR("[DestroyLoopbackQp] Failed to destroy QP. qpHandle=%p, error=%d", qpHandle, ret);
214 0 : qpHandle = nullptr;
215 0 : return HCCL_E_INTERNAL;
216 : }
217 :
218 1 : qpHandle = nullptr;
219 3 : HCCL_DEBUG("[DestroyLoopbackQp] Loopback QP successfully destroyed.");
220 1 : return HCCL_SUCCESS;
221 : }
222 :
223 : // 释放 Local MR 内存
224 13 : HcclResult FlushHandle::FreeLocalMemory()
225 : {
226 39 : HCCL_DEBUG("[%s] Starting to free local memory...", __func__);
227 :
228 13 : if (localMem == nullptr) {
229 21 : HCCL_DEBUG("[%s] Local memory already null, skipping.", __func__);
230 7 : return HCCL_SUCCESS;
231 : }
232 :
233 : try {
234 6 : if (flushOpcodeSupport_) {
235 3 : HrtFree(localMem);
236 : } else {
237 3 : free(localMem);
238 : }
239 0 : } catch (HcclException& e) {
240 0 : HCCL_ERROR("[%s] Exception occurred: %s", __func__, e.what());
241 0 : return e.GetErrorCode();
242 0 : } catch (...) {
243 0 : HCCL_ERROR("[%s] Exception caught while freeing local memory.", __func__);
244 0 : return HcclResult::HCCL_E_INTERNAL;
245 0 : }
246 6 : localMem = nullptr;
247 18 : HCCL_DEBUG("[%s] Local memory successfully freed.", __func__);
248 6 : return HCCL_SUCCESS;
249 : }
250 :
251 : // 释放 Device 内存
252 13 : HcclResult FlushHandle::FreeDeviceMemory()
253 : {
254 39 : HCCL_DEBUG("[FreeDeviceMemory] Starting to free device memory...");
255 :
256 13 : if (deviceMem == nullptr) {
257 27 : HCCL_DEBUG("[FreeDeviceMemory] Device memory already null, skipping.");
258 9 : return HCCL_SUCCESS;
259 : }
260 :
261 : try {
262 4 : HrtFree(deviceMem);
263 4 : deviceMem = nullptr;
264 12 : HCCL_DEBUG("[FreeDeviceMemory] Device memory successfully freed.");
265 4 : return HCCL_SUCCESS;
266 0 : } catch (...) {
267 0 : HCCL_ERROR("[FreeDeviceMemory] Exception caught while freeing device memory.");
268 0 : deviceMem = nullptr;
269 0 : return HCCL_E_RUNTIME;
270 0 : }
271 : }
272 :
273 : } // namespace Hccl
|