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 : loopBackQpMrRemoteInfo.access
157 2 : = RA_ACCESS_REMOTE_WRITE | RA_ACCESS_LOCAL_WRITE | RA_ACCESS_REMOTE_READ | RA_ACCESS_REMOTE_ATOMIC;
158 :
159 2 : int remoteRet = RaRegisterMr(rdmaHandle, &loopBackQpMrRemoteInfo, &remoteMrHandle);
160 2 : if (remoteRet != 0 || remoteMrHandle == nullptr) {
161 0 : HCCL_ERROR(
162 : "[RegisterRemoteMr]Failed to register remote MR. remoteMrHandle=0x%p, error_code=%d", remoteMrHandle,
163 : remoteRet);
164 0 : HcclResult eRet = Destroy();
165 0 : HCCL_ERROR(
166 : "[RegisterLocalMr]Failed to register remote MR. error_code=%d. Destroy Flush code=%d", remoteRet, 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(
186 : "[DeregisterMr] Failed to deregister %s MR, mrHandle=0x%p, error_code=%d.", logTag.c_str(), mrHandle, ret);
187 0 : mrHandle = nullptr; // 防止重复调用
188 0 : return HCCL_E_INTERNAL;
189 : }
190 :
191 5 : mrHandle = nullptr;
192 15 : HCCL_DEBUG("[DeregisterMr] %s MR successfully deregistered.", logTag.c_str());
193 5 : return HCCL_SUCCESS;
194 : }
195 :
196 : // 销毁环回 QP
197 13 : HcclResult FlushHandle::DestroyLoopbackQp()
198 : {
199 39 : HCCL_DEBUG("[DestroyLoopbackQp] Starting to destroy loopback QP...");
200 :
201 13 : if (qpHandle == nullptr) {
202 36 : HCCL_DEBUG("[DestroyLoopbackQp] QP already null, skipping.");
203 12 : return HCCL_SUCCESS;
204 : }
205 :
206 1 : int ret = RaQpDestroy(qpHandle);
207 1 : if (ret != 0) {
208 0 : HCCL_ERROR("[DestroyLoopbackQp] Failed to destroy QP. qpHandle=%p, error=%d", qpHandle, ret);
209 0 : qpHandle = nullptr;
210 0 : return HCCL_E_INTERNAL;
211 : }
212 :
213 1 : qpHandle = nullptr;
214 3 : HCCL_DEBUG("[DestroyLoopbackQp] Loopback QP successfully destroyed.");
215 1 : return HCCL_SUCCESS;
216 : }
217 :
218 : // 释放 Local MR 内存
219 13 : HcclResult FlushHandle::FreeLocalMemory()
220 : {
221 39 : HCCL_DEBUG("[%s] Starting to free local memory...", __func__);
222 :
223 13 : if (localMem == nullptr) {
224 21 : HCCL_DEBUG("[%s] Local memory already null, skipping.", __func__);
225 7 : return HCCL_SUCCESS;
226 : }
227 :
228 : try {
229 6 : if (flushOpcodeSupport_) {
230 3 : HrtFree(localMem);
231 : } else {
232 3 : free(localMem);
233 : }
234 0 : } catch (HcclException& e) {
235 0 : HCCL_ERROR("[%s] Exception occurred: %s", __func__, e.what());
236 0 : return e.GetErrorCode();
237 0 : } catch (...) {
238 0 : HCCL_ERROR("[%s] Exception caught while freeing local memory.", __func__);
239 0 : return HcclResult::HCCL_E_INTERNAL;
240 0 : }
241 6 : localMem = nullptr;
242 18 : HCCL_DEBUG("[%s] Local memory successfully freed.", __func__);
243 6 : return HCCL_SUCCESS;
244 : }
245 :
246 : // 释放 Device 内存
247 13 : HcclResult FlushHandle::FreeDeviceMemory()
248 : {
249 39 : HCCL_DEBUG("[FreeDeviceMemory] Starting to free device memory...");
250 :
251 13 : if (deviceMem == nullptr) {
252 27 : HCCL_DEBUG("[FreeDeviceMemory] Device memory already null, skipping.");
253 9 : return HCCL_SUCCESS;
254 : }
255 :
256 : try {
257 4 : HrtFree(deviceMem);
258 4 : deviceMem = nullptr;
259 12 : HCCL_DEBUG("[FreeDeviceMemory] Device memory successfully freed.");
260 4 : return HCCL_SUCCESS;
261 0 : } catch (...) {
262 0 : HCCL_ERROR("[FreeDeviceMemory] Exception caught while freeing device memory.");
263 0 : deviceMem = nullptr;
264 0 : return HCCL_E_RUNTIME;
265 0 : }
266 : }
267 :
268 : } // namespace Hccl
|