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()
20 : {
21 7 : Destroy();
22 7 : }
23 :
24 5 : HcclResult FlushHandle::Init(IpAddress ip, u32 devPhyId)
25 : {
26 5 : int lbMax = 0;
27 : // 获取 RDMA handle
28 5 : CHK_RET(GetRdmaHandle(ip, devPhyId, &rdmaHandle));
29 :
30 : // 获取 LbMax
31 5 : CHK_RET(GetLbMax(&lbMax));
32 :
33 5 : if (lbMax > 0) {
34 2 : SetFlushOpcodeSupport();
35 : }
36 :
37 : // 分配 Local Memory
38 5 : CHK_RET(AllocateLocalMemory());
39 :
40 : // 分配 Device Memory
41 8 : CHK_RET(AllocateDeviceMemory());
42 :
43 : // 创建环回 QP
44 7 : CHK_RET(CreateLoopbackQp());
45 :
46 : // 注册 Local MR
47 6 : CHK_RET(RegisterLocalMr());
48 :
49 : // 注册 Remote MR
50 2 : CHK_RET(RegisterRemoteMr());
51 :
52 2 : flushIsInitialized = true;
53 2 : return HCCL_SUCCESS;
54 : }
55 :
56 5 : HcclResult FlushHandle::GetLbMax(int *lbMax) const
57 : {
58 5 : int ret = RaGetLbMax(rdmaHandle, lbMax);
59 5 : if (ret != 0) {
60 0 : HCCL_ERROR("[GetLbMax]Failed to get load balance max value. error_code=%d.", ret);
61 0 : return HCCL_E_ROCE_CONNECT;
62 : }
63 15 : HCCL_INFO("[GetLbMax]Get load balance max value successfully, ibMax = %d", *lbMax);
64 5 : return HCCL_SUCCESS;
65 : }
66 :
67 13 : HcclResult FlushHandle::Destroy()
68 : {
69 13 : HcclResult finalResult = HCCL_SUCCESS;
70 26 : finalResult = std::max(finalResult, DeregisterMr(remoteMrHandle, "Remote"));
71 13 : finalResult = std::max(finalResult, DeregisterMr(localMrHandle, "Local"));
72 13 : finalResult = std::max(finalResult, DestroyLoopbackQp());
73 13 : finalResult = std::max(finalResult, FreeLocalMemory());
74 13 : finalResult = std::max(finalResult, FreeDeviceMemory());
75 13 : return finalResult;
76 : }
77 :
78 5 : HcclResult FlushHandle::GetRdmaHandle(IpAddress ip, u32 devPhyId, void **rdmaHandle) const
79 : {
80 5 : *rdmaHandle =
81 5 : RdmaHandleManager::GetInstance().GetByAddr(devPhyId, LinkProtoType::RDMA, ip, PortDeploymentType::HOST_NET);
82 5 : CHK_PTR_NULL(*rdmaHandle);
83 :
84 15 : HCCL_DEBUG("[GetRdmaHandle]RDMA handle initialized. ");
85 :
86 5 : return HCCL_SUCCESS;
87 : }
88 :
89 5 : HcclResult FlushHandle::AllocateLocalMemory()
90 : {
91 5 : u64 bufferSize = FLUSH_BUFFER_SIZE;
92 5 : if (flushOpcodeSupport_) {
93 : // 1825 主动排空要求使用device 内存
94 2 : localMem = HrtMalloc(bufferSize, static_cast<int>(ACL_MEM_TYPE_HIGH_BAND_WIDTH));
95 : } else {
96 3 : localMem = malloc(bufferSize);
97 : }
98 :
99 5 : if (localMem == nullptr) {
100 0 : HcclResult eRet = Destroy();
101 0 : HCCL_ERROR("[%s]Failed to Allocate Local Memory. Destroy Flush code=%d", __func__, eRet);
102 0 : return HCCL_E_MEMORY;
103 : }
104 15 : HCCL_DEBUG("[%s]Local memory allocated at %p, size=%u", __func__, localMem, bufferSize);
105 5 : return HCCL_SUCCESS;
106 : }
107 :
108 5 : HcclResult FlushHandle::AllocateDeviceMemory()
109 : {
110 5 : u64 bufferSize = FLUSH_BUFFER_SIZE;
111 5 : deviceMem = HrtMalloc(bufferSize, static_cast<int>(ACL_MEM_TYPE_HIGH_BAND_WIDTH));
112 5 : if (deviceMem == nullptr) {
113 1 : HcclResult eRet = Destroy();
114 3 : HCCL_ERROR("[AllocateDeviceMemory]Failed to Allocate Device Memory. Destroy Flush code=%d", eRet);
115 1 : return HCCL_E_MEMORY;
116 : }
117 12 : HCCL_DEBUG("[AllocateDeviceMemory]Device memory allocated at %p, size=%u", deviceMem, bufferSize);
118 4 : return HCCL_SUCCESS;
119 : }
120 :
121 4 : HcclResult FlushHandle::CreateLoopbackQp()
122 : {
123 4 : int ret = RaLoopbackQpCreate(rdmaHandle, &loopBackQpParam, &qpHandle);
124 4 : if (ret != 0) {
125 1 : HcclResult eRet = Destroy();
126 3 : HCCL_ERROR("[CreateLoopbackQp]Failed to create loopback QP. error_code=%d. Destroy Flush code=%d", ret, eRet);
127 1 : return HCCL_E_ROCE_CONNECT;
128 : }
129 9 : HCCL_DEBUG("[CreateLoopbackQp]Loopback QP created successfully. QP Handle=%p", qpHandle);
130 3 : return HCCL_SUCCESS;
131 : }
132 :
133 3 : HcclResult FlushHandle::RegisterLocalMr()
134 : {
135 3 : u64 bufferSize = FLUSH_BUFFER_SIZE;
136 3 : loopBackQpMrLocalInfo.addr = localMem;
137 3 : loopBackQpMrLocalInfo.size = bufferSize;
138 3 : loopBackQpMrLocalInfo.access = RA_ACCESS_LOCAL_WRITE;
139 :
140 3 : int localRet = RaRegisterMr(rdmaHandle, &loopBackQpMrLocalInfo, &localMrHandle);
141 3 : if (localRet != 0 || localMrHandle == nullptr) {
142 3 : HCCL_ERROR("[RegisterLocalMr]Failed to register local MR. localMrHandle=0x%p, error_code=%d", localMrHandle,
143 : localRet);
144 1 : HcclResult eRet = Destroy();
145 3 : HCCL_ERROR("[RegisterLocalMr]Failed to register local MR. error_code=%d. Destroy Flush code=%d", localRet,
146 : eRet);
147 1 : return HCCL_E_MEMORY;
148 : }
149 6 : HCCL_DEBUG("[RegisterLocalMr]Local MR registered successfully. MR Handle=0x%p", localMrHandle);
150 2 : return HCCL_SUCCESS;
151 : }
152 :
153 2 : HcclResult FlushHandle::RegisterRemoteMr()
154 : {
155 2 : u64 bufferSize = FLUSH_BUFFER_SIZE;
156 2 : loopBackQpMrRemoteInfo.addr = deviceMem;
157 2 : loopBackQpMrRemoteInfo.size = bufferSize;
158 2 : loopBackQpMrRemoteInfo.access = RA_ACCESS_REMOTE_WRITE | RA_ACCESS_LOCAL_WRITE | RA_ACCESS_REMOTE_READ | RA_ACCESS_REMOTE_ATOMIC;
159 :
160 2 : int remoteRet = RaRegisterMr(rdmaHandle, &loopBackQpMrRemoteInfo, &remoteMrHandle);
161 2 : if (remoteRet != 0 || remoteMrHandle == nullptr) {
162 0 : HCCL_ERROR("[RegisterRemoteMr]Failed to register remote MR. remoteMrHandle=0x%p, error_code=%d", remoteMrHandle,
163 : remoteRet);
164 0 : HcclResult eRet = Destroy();
165 0 : HCCL_ERROR("[RegisterLocalMr]Failed to register remote MR. error_code=%d. Destroy Flush code=%d", remoteRet,
166 : eRet);
167 0 : return HCCL_E_MEMORY;
168 : }
169 6 : HCCL_DEBUG("[RegisterRemoteMr]Remote MR registered successfully. MR Handle=0x%p", remoteMrHandle);
170 2 : return HCCL_SUCCESS;
171 : }
172 :
173 : // 销毁 MR
174 26 : HcclResult FlushHandle::DeregisterMr(MrHandle &mrHandle, std::string logTag) const
175 : {
176 78 : HCCL_DEBUG("[DeregisterMr] Starting to destroy %s MR...", logTag.c_str());
177 :
178 26 : if (mrHandle == nullptr || rdmaHandle == nullptr) {
179 63 : HCCL_DEBUG("[DeregisterMr] %s MR is already null, skipping.", logTag.c_str());
180 21 : return HCCL_SUCCESS;
181 : }
182 :
183 5 : int ret = RaDeregisterMr(rdmaHandle, mrHandle);
184 5 : if (ret != 0) {
185 0 : HCCL_ERROR("[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
|