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