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 "local_rdma_rma_buffer_impl.h"
12 : #include "adapter_hccp.h"
13 : #include "hccl_network.h"
14 : #include "network_manager_pub.h"
15 : #include "mem_mapping_manager.h"
16 :
17 : namespace hccl {
18 : namespace {
19 0 : void* GetAliasDevAddr(void* addr, const LocalRdmaRmaBufferImpl& parent)
20 : {
21 0 : const uintptr_t childAddr = reinterpret_cast<uintptr_t>(addr);
22 0 : const uintptr_t parentAddr = reinterpret_cast<uintptr_t>(parent.GetAddr());
23 0 : const uintptr_t parentDevAddr = reinterpret_cast<uintptr_t>(parent.GetDevAddr());
24 0 : return reinterpret_cast<void*>(parentDevAddr + (childAddr - parentAddr));
25 : }
26 : } // namespace
27 :
28 6 : LocalRdmaRmaBufferImpl::LocalRdmaRmaBufferImpl(
29 6 : const HcclNetDevCtx netDevCtx, void* addr, u64 size, const RmaMemType memType)
30 18 : : RmaBuffer(netDevCtx, addr, size, memType, RmaType::RDMA_RMA)
31 6 : {}
32 :
33 4 : LocalRdmaRmaBufferImpl::LocalRdmaRmaBufferImpl(
34 4 : const HcclNetDevCtx netDevCtx, void* addr, u64 size, const RmaMemType memType, const LocalRdmaRmaBufferImpl& parent)
35 : : RmaBuffer(netDevCtx, addr, size, memType, RmaType::RDMA_RMA, true),
36 4 : deviceLogicId(parent.deviceLogicId),
37 4 : rdmaHandle(parent.rdmaHandle),
38 4 : mrHandle(parent.mrHandle),
39 4 : lkey(parent.lkey),
40 4 : devAddrID(parent.devAddrID),
41 4 : initialized_(true)
42 : {
43 4 : devAddr = (memType == RmaMemType::DEVICE) ? addr : GetAliasDevAddr(addr, parent);
44 4 : HCCL_INFO("[LocalRdmaRmaBufferImpl] alias constructor, lkey[%u] mrHandle[%p]", lkey, mrHandle);
45 4 : }
46 :
47 20 : LocalRdmaRmaBufferImpl::~LocalRdmaRmaBufferImpl()
48 : {
49 10 : if (!isAlias_) {
50 6 : HcclResult res = Destroy();
51 6 : if (res != HCCL_SUCCESS) {
52 0 : HCCL_ERROR("[LocalRdmaRmaBufferImpl][~LocalRdmaRmaBufferImpl]failed, ret[%d]", res);
53 : }
54 : }
55 20 : }
56 :
57 : std::unordered_map<s32, std::unordered_map<std::string, u32>> g_devAddrIdentifierMap;
58 : std::mutex g_devAddrIdentifierMutex;
59 :
60 0 : bool IsDevAddrExistInDevAddrIdentifierMap(s32 deviceLogicId, const std::string& devAddrID)
61 : {
62 0 : std::lock_guard<std::mutex> lock(g_devAddrIdentifierMutex);
63 0 : if (g_devAddrIdentifierMap.find(deviceLogicId) != g_devAddrIdentifierMap.end()) {
64 0 : return (g_devAddrIdentifierMap[deviceLogicId].find(devAddrID) != g_devAddrIdentifierMap[deviceLogicId].end());
65 : }
66 0 : return false;
67 0 : }
68 :
69 0 : HcclResult AddDevAddrIdentifierMap(s32 deviceLogicId, const std::string& devAddrID)
70 : {
71 0 : CHK_PRT_RET(
72 : deviceLogicId == INVALID_INT, HCCL_ERROR("[AddDevAddrIdentifierMap] deviceLogicId is error."), HCCL_E_PARA);
73 0 : CHK_PRT_RET(devAddrID.empty(), HCCL_ERROR("[AddDevAddrIdentifierMap] devAddrID is error."), HCCL_E_PARA);
74 : // devAddrID exit
75 0 : bool isDevAddrExist = IsDevAddrExistInDevAddrIdentifierMap(deviceLogicId, devAddrID);
76 0 : std::lock_guard<std::mutex> lock(g_devAddrIdentifierMutex);
77 0 : if (isDevAddrExist) {
78 0 : g_devAddrIdentifierMap[deviceLogicId][devAddrID] += 1;
79 0 : return HCCL_SUCCESS;
80 : }
81 : // 确保 deviceLogicId 和 devAddrID 的 map 已经被初始化
82 0 : if (g_devAddrIdentifierMap.find(deviceLogicId) == g_devAddrIdentifierMap.end()) {
83 0 : g_devAddrIdentifierMap[deviceLogicId] = {};
84 : }
85 0 : g_devAddrIdentifierMap[deviceLogicId][devAddrID] = 1;
86 0 : return HCCL_SUCCESS;
87 0 : }
88 :
89 0 : HcclResult DeDevAddrIdentifierMap(s32 deviceLogicId, const std::string& devAddrID)
90 : {
91 0 : bool isDevAddrExist = IsDevAddrExistInDevAddrIdentifierMap(deviceLogicId, devAddrID);
92 0 : CHK_PRT_RET(
93 : !isDevAddrExist, HCCL_ERROR("[LocalRdmaRmaBufferImpl][DeDevAddrIdentifierMap]devAddrID is not existed."),
94 : HCCL_E_PARA);
95 0 : std::lock_guard<std::mutex> lock(g_devAddrIdentifierMutex);
96 0 : if (g_devAddrIdentifierMap[deviceLogicId][devAddrID] > 0) {
97 0 : g_devAddrIdentifierMap[deviceLogicId][devAddrID]--;
98 0 : if (g_devAddrIdentifierMap[deviceLogicId][devAddrID] == 0) {
99 0 : g_devAddrIdentifierMap[deviceLogicId].erase(devAddrID);
100 0 : HCCL_RUN_INFO("Entry-%s: deviceLogicId[%d] erased.", __func__, deviceLogicId);
101 : }
102 : }
103 0 : return HCCL_SUCCESS;
104 0 : }
105 :
106 0 : HcclResult LocalRdmaRmaBufferImpl::Init()
107 : {
108 0 : CHK_PTR_NULL(netDevCtx);
109 0 : deviceLogicId = (static_cast<NetDevContext*>(netDevCtx))->GetLogicId();
110 0 : HcclIpAddress localIp = (static_cast<NetDevContext*>(netDevCtx))->GetLocalIp();
111 0 : bool isBackupIpValid = !(static_cast<NetDevContext*>(netDevCtx))->GetBackupIp().IsInvalid();
112 0 : RaResourceInfo raResourceInfo;
113 0 : CHK_RET(NetworkManager::GetInstance(deviceLogicId).GetRaResourceInfo(raResourceInfo));
114 0 : rdmaHandle = raResourceInfo.nicSocketMap[localIp].nicRdmaHandle;
115 0 : CHK_PTR_NULL(rdmaHandle);
116 0 : if (isBackupIpValid) {
117 0 : HCCL_INFO(
118 : "[%s] before hrtGetDevice deviceLogicId[%d], isBackupIpValid[%d]", __func__, deviceLogicId,
119 : isBackupIpValid);
120 0 : CHK_RET(hrtGetDevice(&deviceLogicId));
121 0 : HCCL_INFO("[%s] after hrtGetDevice deviceLogiID[%d]", __func__, deviceLogicId);
122 : }
123 : // host内存地址映射
124 0 : devAddr = addr;
125 0 : if (memType == RmaMemType::HOST) {
126 0 : CHK_RET(MemMappingManager::GetInstance(deviceLogicId).GetDevVA(deviceLogicId, addr, size, devAddr));
127 : }
128 0 : HCCL_DEBUG("[Init]addr[%p], size[%llu], devAddr[%p], memType[%d]", addr, size, devAddr, memType);
129 :
130 : // 内存注册
131 0 : MrInfoT info = {};
132 0 : info.size = size;
133 0 : info.access = RA_ACCESS_REMOTE_WRITE | RA_ACCESS_LOCAL_WRITE | RA_ACCESS_REMOTE_READ;
134 0 : info.addr = devAddr;
135 :
136 0 : std::ostringstream oss;
137 0 : oss.write(reinterpret_cast<const char_t*>(&rdmaHandle), sizeof(rdmaHandle));
138 0 : oss.write(reinterpret_cast<const char_t*>(&addr), sizeof(addr));
139 0 : oss.write(reinterpret_cast<const char_t*>(&size), sizeof(size));
140 0 : devAddrID = oss.str();
141 :
142 0 : CHK_RET(hrtRaRegGlobalMr(rdmaHandle, info, mrHandle));
143 0 : HCCL_DEBUG("[Init][RegMr] LocalRdmaRmaBuffer rdmaHandle[%p], mrHandle[%p].", rdmaHandle, mrHandle);
144 : // 信息保存
145 0 : CHK_RET(AddDevAddrIdentifierMap(deviceLogicId, devAddrID));
146 0 : this->lkey = info.lkey;
147 0 : initialized_ = true;
148 0 : return HCCL_SUCCESS;
149 0 : }
150 :
151 0 : std::string& LocalRdmaRmaBufferImpl::Serialize()
152 : {
153 0 : if (!serializeStr_.empty()) {
154 0 : return serializeStr_;
155 : }
156 : // 序列化信息
157 0 : std::ostringstream oss;
158 0 : u8 type{static_cast<u8>(rmaType)};
159 0 : oss.write(reinterpret_cast<const char_t*>(&type), sizeof(type));
160 0 : oss.write(reinterpret_cast<const char_t*>(&addr), sizeof(addr));
161 0 : oss.write(reinterpret_cast<const char_t*>(&size), sizeof(size));
162 0 : oss.write(reinterpret_cast<const char_t*>(&devAddr), sizeof(devAddr));
163 0 : oss.write(reinterpret_cast<const char_t*>(&memType), sizeof(memType));
164 0 : oss.write(reinterpret_cast<const char_t*>(&lkey), sizeof(lkey));
165 :
166 0 : serializeStr_ = oss.str();
167 0 : return serializeStr_;
168 0 : }
169 :
170 12 : HcclResult LocalRdmaRmaBufferImpl::Destroy()
171 : {
172 12 : if (addr != nullptr && initialized_) {
173 : // 内存解注册
174 0 : HcclResult ret = HCCL_SUCCESS;
175 0 : if (mrHandle != nullptr) {
176 0 : HCCL_DEBUG("[Destroy][DeRegMr] LocalRdmaRmaBuffer rdmaHandle[%p], mrHandle[%p].", rdmaHandle, mrHandle);
177 :
178 : // 防止重复释放内存,仅在内存使用个数 = 0 时,释放内存
179 0 : HcclResult retDe = HCCL_SUCCESS;
180 0 : retDe = DeDevAddrIdentifierMap(deviceLogicId, devAddrID);
181 0 : if (retDe != HCCL_SUCCESS) {
182 0 : HCCL_WARNING("[Destroy][DeRegMr][DeDevAddrIdentifierMap]err[%d] deDevAddrIdentifierMap failed.", retDe);
183 : }
184 0 : if (!IsDevAddrExistInDevAddrIdentifierMap(deviceLogicId, devAddrID)) {
185 0 : ret = hrtRaDeRegGlobalMr(rdmaHandle, mrHandle);
186 : }
187 :
188 0 : if (ret != HCCL_SUCCESS) {
189 0 : HCCL_ERROR(
190 : "[LocalRdmaRmaBufferImpl][Destroy]deReg Global Mr failed, "
191 : "ret[%d], dev[%d], ptr[%p], size[%llu]",
192 : ret, deviceLogicId, addr, size);
193 : }
194 : }
195 :
196 : // host内存解映射
197 0 : if (memType == RmaMemType::HOST) {
198 0 : ret = MemMappingManager::GetInstance(deviceLogicId).ReleaseDevVA(deviceLogicId, addr, size);
199 0 : if (ret != HCCL_SUCCESS) {
200 0 : HCCL_ERROR(
201 : "[LocalRdmaRmaBufferImpl][Destroy]release dev va failed, "
202 : "ret[%d], dev[%d], ptr[%p], size[%llu]",
203 : ret, deviceLogicId, addr, size);
204 : }
205 : }
206 :
207 0 : addr = nullptr;
208 0 : size = 0;
209 0 : mrHandle = nullptr;
210 0 : devAddrID = std::string();
211 0 : initialized_ = false;
212 0 : return ret;
213 : }
214 :
215 12 : return HCCL_SUCCESS;
216 : }
217 :
218 0 : HcclResult LocalRdmaRmaBufferImpl::Remap(void* addr, u64 length)
219 : {
220 0 : CHK_PTR_NULL(addr);
221 0 : CHK_PRT_RET(length == 0, HCCL_ERROR("[Remap]memorySize[%llu] must be greater than 0.", length), HCCL_E_PARA);
222 :
223 0 : struct MemRemapInfo info = {};
224 0 : info.addr = addr;
225 0 : info.size = length;
226 0 : unsigned int num = 1;
227 0 : return HrtRaRemapMr(rdmaHandle, &info, num);
228 : }
229 :
230 : } // namespace hccl
|