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