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 "log.h"
12 :
13 : #include "alg_data_trans_wrapper.h"
14 : #include "executor_utils.h"
15 : #include "ins_temp_all_gather_mesh_2D.h"
16 :
17 : namespace Hccl {
18 0 : InsTempAllGatherMesh2D::InsTempAllGatherMesh2D(
19 : const RankId virtualRank, const u32 tempRankSize, const std::vector<std::vector<RankId>>& tempVTopo,
20 0 : const std::map<RankId, u32>& tempVirtRankMap)
21 0 : : InsAlgTemplateBase(virtualRank, tempRankSize, tempVTopo, tempVirtRankMap)
22 0 : {}
23 :
24 0 : InsTempAllGatherMesh2D::~InsTempAllGatherMesh2D() {}
25 :
26 0 : HcclResult InsTempAllGatherMesh2D::CalcRes(AlgTempResReq& tempResReq)
27 : {
28 0 : HCCL_DEBUG("Enter InsTempAllGatherMesh2D::CalcRes");
29 0 : const int TwoD = 2;
30 0 : CHK_PRT_RET(
31 : tempVTopo_.size() < TwoD,
32 : HCCL_ERROR("[InsTempAllGatherMesh2D] tempVTopo_ mismatch size:%zu", tempVTopo_.size()),
33 : HcclResult::HCCL_E_INTERNAL);
34 0 : CHK_PRT_RET(
35 : tempVTopo_[0].size() <= 1 || tempVTopo_[1].size() <= 1,
36 : HCCL_ERROR(
37 : "[InsTempAllGatherMesh2D] tempVTopo_ size error, size:%zu %zu", tempVTopo_[0].size(), tempVTopo_[1].size()),
38 : HcclResult::HCCL_E_INTERNAL);
39 0 : tempResReq.queNum = tempVTopo_[0].size() - 1 + tempVTopo_[1].size() - 1;
40 :
41 0 : tempResReq.streamNum = tempResReq.queNum;
42 0 : tempResReq.queNotifys = CreateMasterSlaveQueNotifiesRequest(tempResReq.queNum);
43 0 : HCCL_DEBUG("InsTempAllGatherMesh2D::CalcRes queNotifys size[%zu]", tempResReq.queNotifys.size());
44 :
45 0 : QId centerQ = 0;
46 0 : tempResReq.localWaitGroupCntNotify.emplace_back(centerQ, 0);
47 0 : tempResReq.localBcastPostCntNotify.emplace_back(centerQ, 0);
48 :
49 : uint32_t myAlgRank;
50 0 : for (u32 dim = 0; dim < tempVTopo_.size(); dim++) {
51 0 : CHK_RET(GetAlgRank(myRank_, tempVTopo_[dim], myAlgRank));
52 0 : for (u32 queIdx = 0; queIdx < tempVTopo_[dim].size() - 1; queIdx++) {
53 0 : u32 neighborAlgRank = (myAlgRank + 1 + queIdx) % (tempVTopo_[dim].size());
54 0 : RankId neighborRank = tempVTopo_[dim][neighborAlgRank];
55 0 : HCCL_INFO(
56 : "InsTempAllGatherMesh2D::CalcRes Rank[%d], Dim[%u], NeighborRank[%d].", myRank_, dim, neighborRank);
57 : // LinkNum
58 0 : tempResReq.links[neighborRank] = 1;
59 : }
60 : }
61 0 : HCCL_INFO("InsTempAllGatherMesh2D::CalcRes done");
62 0 : return HcclResult::HCCL_SUCCESS;
63 : }
64 :
65 0 : HcclResult InsTempAllGatherMesh2D::GenExtIns(
66 : const TempFuncs& tempFuncs, const TemplateDataParams& tempAlgParams, const ResLinks& tempLinks,
67 : std::vector<InsQuePtr>& tempInsQues)
68 : {
69 0 : HCCL_INFO("[InsTempGatherMesh2D] Run start");
70 :
71 0 : opMode_ = tempFuncs.opMode;
72 0 : tempAlgParams_ = tempAlgParams;
73 0 : tempLinks_ = tempLinks;
74 0 : tempFuncs_ = tempFuncs;
75 0 : const int TwoD = 2;
76 0 : CHK_PRT_RET(
77 : tempVTopo_.size() < TwoD,
78 : HCCL_ERROR("[InsTempAllGatherMesh2D] tempVTopo_ mismatch size:%zu", tempVTopo_.size()),
79 : HcclResult::HCCL_E_INTERNAL);
80 0 : CHK_PRT_RET(
81 : tempVTopo_[0].size() <= 1 || tempVTopo_[1].size() <= 1,
82 : HCCL_ERROR(
83 : "[InsTempAllGatherMesh2D] tempVTopo_ size error, size:%zu %zu", tempVTopo_[0].size(), tempVTopo_[1].size()),
84 : HcclResult::HCCL_E_INTERNAL);
85 0 : majorQueNum_ = tempVTopo_[0].size() - 1 + tempVTopo_[1].size() - 1;
86 0 : xQueNum_ = tempVTopo_[0].size() - 1;
87 0 : yQueNum_ = tempVTopo_[1].size() - 1;
88 :
89 : // queue arrangement
90 0 : std::vector<InsQuePtr> mainInsQues;
91 0 : std::vector<InsQuePtr> xInsQues;
92 0 : std::vector<InsQuePtr> yInsQues;
93 0 : for (u32 queIdx = 0; queIdx < majorQueNum_; queIdx++) {
94 0 : mainInsQues.push_back(tempInsQues[queIdx]);
95 0 : if (queIdx < xQueNum_) {
96 0 : xInsQues.push_back(tempInsQues[queIdx]);
97 : } else {
98 0 : yInsQues.push_back(tempInsQues[queIdx]);
99 : }
100 : }
101 :
102 : // Local Copy from Input to Output
103 0 : CHK_RET(LocalDataCopy(mainInsQues));
104 0 : if (tempRankSize_ == 1) {
105 0 : return HcclResult::HCCL_SUCCESS;
106 : }
107 : // semaphore sync
108 0 : CHK_RET(PreSyncInterQueues(mainInsQues));
109 :
110 : // // step1
111 0 : CHK_RET(Run2DStep1(xInsQues, yInsQues));
112 :
113 : // semaphore sync
114 0 : CHK_RET(PostSyncInterQueues(mainInsQues));
115 0 : CHK_RET(PreSyncInterQueues(mainInsQues));
116 :
117 : // step2 run Mesh
118 0 : CHK_RET(Run2DStep2(xInsQues, yInsQues));
119 0 : CHK_RET(PostSyncInterQueues(mainInsQues));
120 : // LocalCopy: from scratch to output for opbase
121 0 : if ((opMode_ == OpMode::OPBASE) && tempFuncs.isBottom) {
122 0 : CHK_RET(PostLocalCopy(mainInsQues));
123 : }
124 0 : return HcclResult::HCCL_SUCCESS;
125 0 : }
126 :
127 0 : HcclResult InsTempAllGatherMesh2D::Run2DStep1(std::vector<InsQuePtr>& xInsQues, std::vector<InsQuePtr>& yInsQues)
128 : {
129 : u32 myAlgRankX;
130 : u32 myAlgRankY;
131 0 : CHK_RET(GetAlgRank(myRank_, tempVTopo_[0], myAlgRankX));
132 0 : CHK_RET(GetAlgRank(myRank_, tempVTopo_[1], myAlgRankY));
133 :
134 0 : CHK_PRT_RET(
135 : RunMesh(myAlgRankX, myRank_, 0, tempVTopo_[0], xInsQues, 0, tempAlgParams_.sliceSize, DmaMode::PUT)
136 : != HcclResult::HCCL_SUCCESS,
137 : HCCL_ERROR(
138 : "[InsCollAlgFactory] [InsTempAllGatherMesh2D] Rank [%d], unable to run the mesh x0 algorithm.", myRank_),
139 : HcclResult::HCCL_E_INTERNAL);
140 0 : CHK_PRT_RET(
141 : RunMesh(myAlgRankY, myRank_, 0, tempVTopo_[1], yInsQues, 0, tempAlgParams_.sliceSize, DmaMode::PUT)
142 : != HcclResult::HCCL_SUCCESS,
143 : HCCL_ERROR(
144 : "[InsCollAlgFactory] [InsTempAllGatherMesh2D] Rank [%d], unable to run the mesh y0 algorithm.", myRank_),
145 : HcclResult::HCCL_E_INTERNAL);
146 0 : return HcclResult::HCCL_SUCCESS;
147 : }
148 :
149 0 : HcclResult InsTempAllGatherMesh2D::Run2DStep2(std::vector<InsQuePtr>& xInsQues, std::vector<InsQuePtr>& yInsQues)
150 : {
151 : u32 myAlgRankX;
152 : u32 myAlgRankY;
153 0 : CHK_RET(GetAlgRank(myRank_, tempVTopo_[0], myAlgRankX));
154 0 : CHK_RET(GetAlgRank(myRank_, tempVTopo_[1], myAlgRankY));
155 0 : u64 xSize = tempAlgParams_.sliceSize / 2;
156 0 : u64 ySize = tempAlgParams_.sliceSize - xSize;
157 0 : for (u32 rank = 0; rank < tempVTopo_[0].size(); rank++) { // 转发哪一个rank
158 0 : if (rank == myAlgRankX) { // 只处理转发,直连的在step1传输完成
159 0 : continue;
160 : }
161 0 : RankId globalRank = tempVTopo_[0][rank];
162 0 : int rankOffset = rank - myAlgRankX;
163 : // 上半部分数据通过Y轴传输
164 0 : CHK_PRT_RET(
165 : RunMesh(myAlgRankY, globalRank, rankOffset, tempVTopo_[1], yInsQues, 0, xSize, DmaMode::GET)
166 : != HcclResult::HCCL_SUCCESS,
167 : HCCL_ERROR(
168 : "[InsCollAlgFactory] [InsTempAllGatherMesh2D] Rank [%d], unable to run the mesh y1 algorithm.",
169 : myRank_),
170 : HcclResult::HCCL_E_INTERNAL);
171 : }
172 0 : for (u32 rank = 0; rank < tempVTopo_[1].size(); rank++) {
173 0 : if (rank == myAlgRankY) {
174 0 : continue;
175 : }
176 0 : RankId globalRank = tempVTopo_[1][rank];
177 0 : int rankOffset = (rank - myAlgRankY) * tempVTopo_[0].size();
178 : // 下半部分数据通过X轴传输
179 0 : CHK_PRT_RET(
180 : RunMesh(myAlgRankX, globalRank, rankOffset, tempVTopo_[0], xInsQues, xSize, ySize, DmaMode::GET)
181 : != HcclResult::HCCL_SUCCESS,
182 : HCCL_ERROR(
183 : "[InsCollAlgFactory] [InsTempAllGatherMesh2D] Rank [%d], unable to run the mesh x1 algorithm.",
184 : myRank_),
185 : HcclResult::HCCL_E_INTERNAL);
186 : }
187 0 : return HcclResult::HCCL_SUCCESS;
188 : }
189 :
190 0 : HcclResult InsTempAllGatherMesh2D::RunMesh(
191 : const u32 myAlgRank, RankId globalSrcRank, int rankOffset, const std::vector<RankId>& vTopo,
192 : std::vector<InsQuePtr>& tempInsQues, u64 xyOffset, u64 size, DmaMode dmaMode)
193 : {
194 0 : if (size == 0) {
195 0 : HCCL_INFO("[InsTempAllGatherMesh2D] 0 data skip sendrecv");
196 0 : return HcclResult::HCCL_SUCCESS;
197 : }
198 0 : const u64 scratchRepeatStride = tempAlgParams_.sliceSize * tempRankSize_;
199 0 : for (u32 rpt = 0; rpt < tempAlgParams_.repeatNum; ++rpt) {
200 0 : for (u32 queIdx = 0; queIdx < vTopo.size() - 1; queIdx++) {
201 : // find neighbors -> virtualRank
202 0 : RankId connectedRank = vTopo[(myAlgRank + 1 + queIdx) % vTopo.size()];
203 0 : RankId globalDstRank = connectedRank + rankOffset;
204 0 : HCCL_INFO(
205 : "[InsTempAllGatherMesh2D] RunAllGather opbase find neighbors: ==============="
206 : "myRank=%d, connectedRank=%d, globalSrcRank=%d, globalDstRank=%d, myAlgRank=%u, queIdx=%u,",
207 : myRank_, connectedRank, globalSrcRank, globalDstRank, myAlgRank, queIdx);
208 :
209 0 : RankId srcAlgRank = globalSrcRank % tempRankSize_;
210 0 : RankId dstAlgRank = globalDstRank % tempRankSize_;
211 :
212 0 : CHK_PRT_RET(
213 : queIdx >= tempInsQues.size() or tempLinks_.at(connectedRank).size() <= 0,
214 : HCCL_ERROR(
215 : "InsTempAllGatherMesh2D: tempInsQues.size()=%zu, connectedRank=%d, tempLinks_.size()=%zu, ",
216 : tempInsQues.size(), connectedRank, tempLinks_.size()),
217 : HcclResult::HCCL_E_INTERNAL);
218 0 : InsQuePtr currQue = tempInsQues[queIdx];
219 0 : LinkData& neighborLinkData = tempLinks_.at(connectedRank)[0];
220 :
221 : BufferType type
222 0 : = (opMode_ == OpMode::OPBASE || !tempFuncs_.isBottom) ? BufferType::SCRATCH : BufferType::OUTPUT;
223 0 : const u64 txOutOffset = tempAlgParams_.buffInfo.outBuffBaseOff + rpt * tempAlgParams_.outputRepeatStride
224 0 : + tempAlgParams_.outputSliceStride * srcAlgRank + xyOffset;
225 0 : const u64 txScratchOffset = tempAlgParams_.buffInfo.scratchBuffBaseOff + rpt * scratchRepeatStride
226 0 : + +tempAlgParams_.sliceSize * srcAlgRank + xyOffset;
227 0 : const u64 txDstOffset = (opMode_ == OpMode::OPBASE || !tempFuncs_.isBottom) ? txScratchOffset : txOutOffset;
228 0 : HCCL_DEBUG(
229 : "[InsTempAllGatherMesh2D] RunAllGather opbase sendrecv: "
230 : "txOutOffset=%llu, txScratchOffset=%llu, txDstOffset=%llu "
231 : "(globalSrcRank=%d, globalDstRank=%d, opMode=%d)",
232 : txOutOffset, txScratchOffset, txDstOffset, globalSrcRank, globalDstRank, opMode_);
233 0 : const u64 rxOutOffset = tempAlgParams_.buffInfo.outBuffBaseOff + rpt * tempAlgParams_.outputRepeatStride
234 0 : + tempAlgParams_.outputSliceStride * dstAlgRank + xyOffset;
235 0 : const u64 rxScratchOffset = tempAlgParams_.buffInfo.scratchBuffBaseOff + rpt * scratchRepeatStride
236 0 : + tempAlgParams_.sliceSize * dstAlgRank + xyOffset;
237 0 : const u64 rxSrcOffset = (opMode_ == OpMode::OPBASE || !tempFuncs_.isBottom) ? rxScratchOffset : rxOutOffset;
238 0 : HCCL_DEBUG(
239 : "[InsTempAllGatherMesh2D] RunAllGather opbase sendrecv: "
240 : "rxOutOffset=%llu, rxScratchOffset=%llu, rxSrcOffset=%llu "
241 : "(globalSrcRank=%d, globalDstRank=%d, opMode=%d)",
242 : rxOutOffset, rxScratchOffset, rxSrcOffset, globalSrcRank, globalDstRank, opMode_);
243 :
244 0 : BufferType txrxBufType = !tempFuncs_.isBottom ? BufferType::SCRATCH : BufferType::OUTPUT;
245 0 : vector<DataSlice> txSrcSlice = vector<DataSlice>{DataSlice(txrxBufType, txOutOffset, size)}; // 发送源
246 0 : vector<DataSlice> txDstSlice = vector<DataSlice>{DataSlice(type, txDstOffset, size)}; // 发送目标
247 0 : HCCL_INFO(
248 : "[InsTempAllGatherMesh2D] RunAllGather opbase *****sendrecv*****, txSrcSlice: %s, txDstSlice: %s",
249 : txSrcSlice[0].Describe().c_str(), txDstSlice[0].Describe().c_str());
250 :
251 0 : vector<DataSlice> rxSrcSlice = vector<DataSlice>{DataSlice(type, rxSrcOffset, size)}; // 接收源
252 0 : vector<DataSlice> rxDstSlice = vector<DataSlice>{DataSlice(txrxBufType, rxOutOffset, size)}; // 接收目标
253 0 : HCCL_INFO(
254 : "[InsTempAllGatherMesh2D] RunAllGather opbase *****sendrecv*****, rxSrcSlice: %s, rxDstSlice: %s",
255 : rxSrcSlice[0].Describe().c_str(), rxDstSlice[0].Describe().c_str());
256 :
257 0 : TxRxSlicesList sendRecvSlicesList({txSrcSlice, txDstSlice}, {rxSrcSlice, rxDstSlice});
258 0 : TxRxLinks sendRecvLinks(neighborLinkData, neighborLinkData);
259 0 : SendRecvInfo sendRecvInfo(sendRecvLinks, sendRecvSlicesList);
260 0 : CHK_PRT_RET(
261 : SendRecv(sendRecvInfo, currQue, 0, true, dmaMode),
262 : HCCL_ERROR("[InsTempAllGatherMesh2D] RunAllGather opbase sendrecv failed"),
263 : HcclResult::HCCL_E_INTERNAL);
264 0 : }
265 : }
266 0 : return HcclResult::HCCL_SUCCESS;
267 : }
268 :
269 0 : HcclResult InsTempAllGatherMesh2D::LocalDataCopy(std::vector<InsQuePtr>& tempInsQues)
270 : {
271 0 : if (tempAlgParams_.buffInfo.inBuffType == tempAlgParams_.buffInfo.outBuffType) {
272 0 : return HcclResult::HCCL_SUCCESS;
273 : }
274 0 : for (u32 rpt = 0; rpt < tempAlgParams_.repeatNum; ++rpt) {
275 0 : RankId algRank = myRank_ % tempRankSize_;
276 0 : const u64 inOffset = tempAlgParams_.buffInfo.inBuffBaseOff + rpt * tempAlgParams_.inputRepeatStride;
277 0 : DataSlice usrInSlice = DataSlice(BufferType::INPUT, inOffset, tempAlgParams_.sliceSize);
278 0 : const u64 outOffset = tempAlgParams_.buffInfo.outBuffBaseOff + rpt * tempAlgParams_.outputRepeatStride
279 0 : + tempAlgParams_.outputSliceStride * algRank;
280 0 : DataSlice usrOutSlice = DataSlice(BufferType::OUTPUT, outOffset, tempAlgParams_.sliceSize);
281 0 : HCCL_INFO(
282 : "[InsTempAllGatherMesh2D] PreCopy usrInSlice: %s, usrOutSlice: %s", usrInSlice.Describe().c_str(),
283 : usrOutSlice.Describe().c_str());
284 0 : std::unique_ptr<Instruction> insLocalCopy = std::make_unique<InsLocalCopy>(usrInSlice, usrOutSlice);
285 0 : tempInsQues[0]->Append(std::move(insLocalCopy));
286 0 : }
287 0 : return HcclResult::HCCL_SUCCESS;
288 : }
289 :
290 0 : HcclResult InsTempAllGatherMesh2D::PostLocalCopy(std::vector<InsQuePtr>& tempInsQues)
291 : {
292 0 : CHK_PRT_RET(
293 : tempInsQues.empty(), HCCL_ERROR("[InsTempAllGatherMesh2D][PostLocalCopy] empty tempInsQues"),
294 : HcclResult::HCCL_E_INTERNAL);
295 0 : CHK_PTR_NULL(tempInsQues[0]);
296 0 : const u64 scratchRepeatStride = tempAlgParams_.sliceSize * tempRankSize_;
297 0 : for (u32 rpt = 0; rpt < tempAlgParams_.repeatNum; ++rpt) {
298 0 : for (u32 i = 0; i < tempVTopo_.size(); i++) {
299 0 : for (auto rank : tempVTopo_[i]) {
300 0 : if (rank == myRank_) {
301 0 : continue;
302 : }
303 : // 只拷贝step1的对端
304 0 : RankId algRank = (rank % tempRankSize_);
305 0 : u64 scratchOffset = tempAlgParams_.buffInfo.scratchBuffBaseOff + rpt * scratchRepeatStride
306 0 : + tempAlgParams_.sliceSize * algRank;
307 0 : u64 outOffset = tempAlgParams_.buffInfo.outBuffBaseOff + rpt * tempAlgParams_.outputRepeatStride
308 0 : + tempAlgParams_.outputSliceStride * algRank;
309 0 : DataSlice usrInSlice = DataSlice(BufferType::SCRATCH, scratchOffset, tempAlgParams_.sliceSize);
310 0 : DataSlice usrOutSlice = DataSlice(BufferType::OUTPUT, outOffset, tempAlgParams_.sliceSize);
311 0 : HCCL_INFO(
312 : "[InsTempAllGatherMesh2D] rank[%d] algRank[%d] PostCopy usrInSlice: %s, usrOutSlice: %s", myRank_,
313 : algRank, usrInSlice.Describe().c_str(), usrOutSlice.Describe().c_str());
314 0 : std::unique_ptr<Instruction> insLocalCopy = std::make_unique<InsLocalCopy>(usrInSlice, usrOutSlice);
315 0 : tempInsQues[0]->Append(std::move(insLocalCopy));
316 0 : }
317 : }
318 : }
319 0 : return HcclResult::HCCL_SUCCESS;
320 : }
321 :
322 : } // namespace Hccl
|