Line data Source code
1 : /**
2 : * Copyright (c) 2026 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 "rdma_conn_lite_v2.h"
12 : #include "rdma_vendor_1825_ops.h"
13 :
14 : namespace Hccl {
15 : constexpr u64 RDMA_DMA_MAX_SIZE = 0x80000000; // Byte, RDMA一次传输的最大size
16 :
17 51 : void RdmaConnLiteV2::ParseSqContext(std::vector<char>& data)
18 : {
19 51 : BinaryStream binaryStream(data);
20 51 : binaryStream >> sqContext.qpn;
21 51 : binaryStream >> sqContext.sqVa;
22 51 : binaryStream >> sqContext.wqeSize;
23 51 : binaryStream >> sqContext.depth;
24 51 : binaryStream >> sqContext.headAddr;
25 51 : binaryStream >> sqContext.tailAddr;
26 51 : binaryStream >> sqContext.dbHwVa;
27 51 : binaryStream >> sqContext.dbSwVa;
28 51 : binaryStream >> sqContext.sl;
29 51 : binaryStream >> sqContext.mtuShift;
30 51 : }
31 :
32 51 : void RdmaConnLiteV2::ParseCqContext(std::vector<char>& data)
33 : {
34 51 : BinaryStream binaryStream(data);
35 51 : binaryStream >> cqContext.cqn;
36 51 : binaryStream >> cqContext.cqVa;
37 51 : binaryStream >> cqContext.cqeSize;
38 51 : binaryStream >> cqContext.cqDepth;
39 51 : binaryStream >> cqContext.headAddr;
40 51 : binaryStream >> cqContext.tailAddr;
41 51 : binaryStream >> cqContext.dbSwVa;
42 51 : }
43 :
44 51 : RdmaConnLiteV2::RdmaConnLiteV2(std::vector<char>& uniqueId) : RmaConnLite()
45 : {
46 51 : BinaryStream binaryStream(uniqueId);
47 51 : binaryStream >> dmaMode_;
48 :
49 51 : std::vector<char> sqUniqueId;
50 51 : binaryStream >> sqUniqueId;
51 51 : ParseSqContext(sqUniqueId);
52 :
53 51 : std::vector<char> cqUniqueId;
54 51 : binaryStream >> cqUniqueId;
55 51 : ParseCqContext(cqUniqueId);
56 :
57 51 : qpVa_ = sqContext.sqVa;
58 51 : sqVa_ = sqContext.sqVa;
59 51 : sqDepth_ = sqContext.depth;
60 :
61 : // 确定厂商
62 51 : GetVendorOps();
63 51 : }
64 :
65 80 : RdmaConnLiteV2::~RdmaConnLiteV2() {}
66 :
67 41 : std::string RdmaConnLiteV2::Describe()
68 : {
69 : return StringFormat(
70 : "RdmaConnLiteV2[QPN=%u, SQ_VA=0x%llx, WQE_SIZE=%u, SQ_DEPTH=%u, SQ_HEAD_ADDR=0x%llx, SQ_TAIL_ADDR=0x%llx, "
71 : "SL=%u, DB_HW_VA=0x%llx, DB_SW_VA=0x%llx, MTU_SHIFT=%u, CQN=%u, CQ_VA=0x%llx, CQE_SIZE=%u, CQ_DEPTH=%u, "
72 : "CQ_HEAD_ADDR=0x%llx, CQ_TAIL_ADDR=0x%llx, DB_HW_VA=0x%llx, DB_SW_VA=0x%llx]",
73 : sqContext.qpn, sqContext.sqVa, sqContext.wqeSize, sqContext.depth, sqContext.headAddr, sqContext.tailAddr,
74 41 : sqContext.sl, sqContext.dbHwVa, sqContext.dbSwVa, sqContext.mtuShift,
75 : cqContext.cqn, cqContext.cqVa, cqContext.cqeSize, cqContext.cqDepth,
76 : cqContext.headAddr, cqContext.tailAddr, cqContext.dbHwVa, cqContext.dbSwVa
77 41 : );
78 : }
79 :
80 52 : void RdmaConnLiteV2::GetVendorOps()
81 : {
82 52 : if (rdmaOps_ != nullptr) {
83 1 : return;
84 : }
85 51 : switch (dmaMode_) {
86 11 : case 0 : { // [PCIe] QBUF_DMA_MODE_DEFAULT
87 29 : HCCL_INFO("[RdmaConnLiteV2::%s] Now Aicpu NDA doesn't support PCIE !", __func__);
88 11 : rdmaOps_ = nullptr;
89 11 : break;
90 : }
91 39 : case 1: { // [UB] QBUF_DMA_MODE_INDEP_UB
92 39 : rdmaOps_ = std::make_unique<Rdma1825Ops>(&sqContext, &cqContext);
93 39 : break;
94 : }
95 1 : default: {
96 3 : HCCL_INFO("[RdmaConnLiteV2::%s] Now dmaMode is invalid !", __func__);
97 1 : rdmaOps_ = nullptr;
98 1 : break;
99 : }
100 : }
101 : }
102 :
103 : // 检查Ops不能为空
104 8 : void RdmaConnLiteV2::CheckVendorOp()
105 : {
106 8 : if (UNLIKELY(rdmaOps_ == nullptr)) {
107 1 : THROW<InternalException>(StringFormat("NDA Op is null. Now dmaMode_ is %d.", dmaMode_));
108 : }
109 7 : }
110 :
111 2 : void RdmaConnLiteV2::Read(const RmaBufSliceLite &loc, const RmtRmaBufSliceLite &rmt, const SqeConfigLite &cfg, u64 &dbAddr, u64 &dbValue)
112 : {
113 6 : HCCL_INFO("[RdmaConnLiteV2::%s] Read start, loc size = %u", __func__, loc.GetSize());
114 2 : CheckVendorOp();
115 :
116 : // 分片操作
117 2 : DoSlice(loc, rmt, [this, &cfg](const RmaBufSliceLite &locSlice, const RmtRmaBufSliceLite &rmtSlice) {
118 3 : rdmaOps_->Read(locSlice, rmtSlice, cfg);
119 3 : });
120 :
121 : // 构造Doorbell并返回
122 2 : rdmaOps_->BuildDoorbell(dbAddr, dbValue);
123 :
124 6 : HCCL_INFO("[RdmaConnLiteV2::%s] Read end, dbAddr = %llu, dbValue = %llu, conn[%s]", __func__, dbAddr, dbValue, Describe().c_str());
125 2 : }
126 :
127 2 : void RdmaConnLiteV2::Write(const RmaBufSliceLite &loc, const RmtRmaBufSliceLite &rmt, const SqeConfigLite &cfg, u64 &dbAddr, u64 &dbValue)
128 : {
129 6 : HCCL_INFO("[RdmaConnLiteV2::%s] Write start, loc size = %u", __func__, loc.GetSize());
130 2 : CheckVendorOp();
131 :
132 : // 分片操作
133 2 : DoSlice(loc, rmt, [this, &cfg](const RmaBufSliceLite &locSlice, const RmtRmaBufSliceLite &rmtSlice) {
134 3 : rdmaOps_->Write(locSlice, rmtSlice, cfg);
135 3 : });
136 :
137 : // 构造Doorbell并返回
138 2 : rdmaOps_->BuildDoorbell(dbAddr, dbValue);
139 :
140 6 : HCCL_INFO("[RdmaConnLiteV2::%s] Write end, dbAddr = 0x%llx, dbValue = 0x%llx, conn[%s]", __func__, dbAddr, dbValue, Describe().c_str());
141 2 : }
142 :
143 1 : void RdmaConnLiteV2::WriteReduce(
144 : const RmaBufSliceLite &loc, const RmtRmaBufSliceLite &rmt, const SqeConfigLite &cfg, DataType dataType, ReduceOp reduceOp, u64 &dbAddr, u64 &dbValue)
145 : {
146 3 : HCCL_INFO("[RdmaConnLiteV2::%s] WriteReduce start, loc size = %u", __func__, loc.GetSize());
147 1 : CheckVendorOp();
148 :
149 : // 分片操作
150 1 : DoSlice(loc, rmt, [this, &cfg, dataType, reduceOp](const RmaBufSliceLite &locSlice, const RmtRmaBufSliceLite &rmtSlice) {
151 1 : rdmaOps_->WriteReduce(locSlice, rmtSlice, cfg, dataType, reduceOp);
152 1 : });
153 :
154 : // 构造Doorbell并返回
155 1 : rdmaOps_->BuildDoorbell(dbAddr, dbValue);
156 :
157 3 : HCCL_INFO("[RdmaConnLiteV2::%s] WriteReduce end, dbAddr = %llu, dbValue = %llu, conn[%s]", __func__, dbAddr, dbValue, Describe().c_str());
158 1 : }
159 :
160 1 : void RdmaConnLiteV2::WriteWithNotify(
161 : const RmaBufSliceLite &loc, const RmtRmaBufSliceLite &rmt,
162 : const RmaBufSliceLite &locNotify, const RmtRmaBufSliceLite ¬ify, const SqeConfigLite &cfg, u64 &dbAddr, u64 &dbValue)
163 : {
164 3 : HCCL_INFO("[RdmaConnLiteV2::%s] WriteWithNotify start, loc size = %u", __func__, loc.GetSize());
165 1 : CheckVendorOp();
166 :
167 : // 分片操作
168 1 : DoSlice(loc, rmt, [this, &cfg](const RmaBufSliceLite &locSlice, const RmtRmaBufSliceLite &rmtSlice) {
169 1 : rdmaOps_->Write(locSlice, rmtSlice, cfg);
170 1 : });
171 :
172 : // 补充一个notify操作
173 1 : rdmaOps_->Write(locNotify, notify, cfg);
174 :
175 : // 构造Doorbell并返回
176 1 : rdmaOps_->BuildDoorbell(dbAddr, dbValue);
177 :
178 3 : HCCL_INFO("[RdmaConnLiteV2::%s] WriteWithNotify end, dbAddr = %llu, dbValue = %llu, conn[%s]", __func__, dbAddr, dbValue, Describe().c_str());
179 1 : }
180 :
181 1 : void RdmaConnLiteV2::WriteReduceWithNotify(
182 : const RmaBufSliceLite &loc, const RmtRmaBufSliceLite &rmt,
183 : const RmaBufSliceLite &locNotify, const RmtRmaBufSliceLite ¬ify, const SqeConfigLite &cfg,
184 : DataType dataType, ReduceOp reduceOp, u64 &dbAddr, u64 &dbValue)
185 : {
186 3 : HCCL_INFO("[RdmaConnLiteV2::%s] WriteReduceWithNotify start, loc size = %u", __func__, loc.GetSize());
187 1 : CheckVendorOp();
188 :
189 : // 分片操作
190 1 : DoSlice(loc, rmt, [this, &cfg, dataType, reduceOp](const RmaBufSliceLite &locSlice, const RmtRmaBufSliceLite &rmtSlice) {
191 1 : rdmaOps_->WriteReduce(locSlice, rmtSlice, cfg, dataType, reduceOp);
192 1 : });
193 :
194 : // 补充一个notify操作
195 1 : rdmaOps_->Write(locNotify, notify, cfg);
196 :
197 : // 构造Doorbell并返回
198 1 : rdmaOps_->BuildDoorbell(dbAddr, dbValue);
199 :
200 3 : HCCL_INFO("[RdmaConnLiteV2::%s] WriteReduceWithNotify end, dbAddr = %llu, dbValue = %llu, conn[%s]", __func__, dbAddr, dbValue, Describe().c_str());
201 1 : }
202 :
203 7 : void RdmaConnLiteV2::DoSlice(
204 : const RmaBufSliceLite &loc, const RmtRmaBufSliceLite &rmt,
205 : const std::function<void(const RmaBufSliceLite &, const RmtRmaBufSliceLite &)> &op) const
206 : {
207 7 : const u64 len = loc.GetSize();
208 7 : const u32 fullSlices = static_cast<u32>(len / RDMA_DMA_MAX_SIZE);
209 7 : const u32 remain = static_cast<u32>(len % RDMA_DMA_MAX_SIZE);
210 7 : const u32 totalSlices = fullSlices + (remain > 0 ? 1 : 0);
211 :
212 16 : for (u32 sliceIdx = 0; sliceIdx < totalSlices; sliceIdx++) {
213 9 : const u64 offset = static_cast<u64>(sliceIdx) * RDMA_DMA_MAX_SIZE;
214 9 : const u64 localAddr = loc.GetAddr() + offset;
215 9 : const u64 remoteAddr = rmt.GetAddr() + offset;
216 9 : const u32 sliceSize = (sliceIdx == totalSlices - 1 && remain > 0)
217 : ? remain : RDMA_DMA_MAX_SIZE;
218 :
219 9 : RmaBufSliceLite locSlice(localAddr, sliceSize, loc.GetLkey(), 0);
220 9 : RmtRmaBufSliceLite rmtSlice(remoteAddr, sliceSize, rmt.GetRkey(), 0, 0, UINT32_MAX);
221 :
222 27 : HCCL_INFO("[RdmaConnLiteV2::%s] Slice[%u]: offset=0x%llx, localAddr=0x%llx, "
223 : "remoteAddr=0x%llx, size=0x%x",
224 : __func__, sliceIdx, offset, localAddr, remoteAddr, sliceSize);
225 :
226 9 : op(locSlice, rmtSlice);
227 : }
228 7 : }
229 :
230 3 : HcclResult RdmaConnLiteV2::PollCq(int32_t numEntries, int32_t timeOut, std::vector<int32_t> &errList, u64 &dbAddr, u64 &dbValue)
231 : {
232 3 : HcclResult ret = HCCL_SUCCESS;
233 :
234 : // Poll numEntries个Cqe, 只返回异常的status
235 3 : ret = rdmaOps_->PollCq(numEntries, timeOut, errList);
236 :
237 : // Build And Ring Cq Soft DB
238 3 : rdmaOps_->BuildCqDoorbell(dbAddr, dbValue);
239 :
240 : // 返回前构造cq DB
241 3 : if (ret != HCCL_SUCCESS) {
242 6 : HCCL_ERROR("[RdmaConnLiteV2::%s] PollCq error, error code: %u", __func__, ret);
243 2 : return ret;
244 : }
245 1 : return HCCL_SUCCESS;
246 : }
247 :
248 :
249 : } // namespace Hccl
|