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