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 "alg_data_trans_wrapper.h"
12 : #include "ins_temp_reduce_mesh_2D.h"
13 :
14 : namespace Hccl {
15 :
16 0 : InsTempReduceMesh2D::InsTempReduceMesh2D(
17 : const RankId virtualRank, const u32 tempRankSize, const std::vector<std::vector<RankId>>& tempVTopo,
18 0 : const std::map<RankId, u32>& tempVirtRankMap)
19 0 : : InsAlgTemplateBase(virtualRank, tempRankSize, tempVTopo, tempVirtRankMap)
20 0 : {}
21 :
22 0 : InsTempReduceMesh2D::~InsTempReduceMesh2D() {}
23 :
24 0 : HcclResult InsTempReduceMesh2D::CalcRes(AlgTempResReq& tempResReq)
25 : {
26 0 : HCCL_INFO("[InsTempReduceMesh2D] Calculate communication resources start");
27 :
28 0 : CHK_PRT_RET(
29 : tempVTopo_.size() != AXIS_NUM,
30 : HCCL_ERROR(
31 : "[InsTempReduceMesh2D] The dimension of topo is invalid, expect [%u], now is [%u]", AXIS_NUM,
32 : tempVTopo_.size()),
33 : HcclResult::HCCL_E_INTERNAL);
34 :
35 0 : axisRankSize_[AXIS_X] = tempVTopo_.at(AXIS_X).size();
36 0 : axisRankSize_[AXIS_Y] = tempVTopo_.at(AXIS_Y).size();
37 :
38 0 : CHK_PRT_RET(
39 : axisRankSize_[AXIS_X] == 0 || axisRankSize_[AXIS_Y] == 0,
40 : HCCL_ERROR(
41 : "[InsTempReduceMesh2D] The rankSize of dimension is invalid, xRankSize is [%u], yRankSize is [%u]",
42 : axisRankSize_[AXIS_X], axisRankSize_[AXIS_Y]),
43 : HcclResult::HCCL_E_INTERNAL);
44 :
45 0 : tempResReq.queNum = axisRankSize_[AXIS_X] + axisRankSize_[AXIS_Y];
46 0 : tempResReq.streamNum = tempResReq.queNum;
47 :
48 0 : tempResReq.queNotifys = CreateNotifiesRequest(axisRankSize_[AXIS_X], axisRankSize_[AXIS_Y]);
49 :
50 0 : CHK_RET(CalcResLinksConcurrMesh(myRank_, tempRankSize_, tempVTopo_, linkNumBtwPeers_, tempResReq));
51 :
52 0 : HCCL_INFO(
53 : "[InsTempReduceMesh2D] Calculate communication resources finished, queNum[%u], streamNum[%u], "
54 : "queNotifyNum[%zu] linkNum[%zu]",
55 : tempResReq.queNum, tempResReq.streamNum, tempResReq.queNotifys.size(), tempResReq.links.size());
56 :
57 0 : return HcclResult::HCCL_SUCCESS;
58 : }
59 :
60 0 : std::vector<std::tuple<QId, QId, u32>> InsTempReduceMesh2D::CreateNotifiesRequest(u32 xQueueNum, u32 yQueueNum) const
61 : {
62 0 : std::vector<std::tuple<QId, QId, u32>> notifyRequests;
63 0 : if (xQueueNum == 0) {
64 0 : HCCL_INFO("[InsTempReduceMesh2D] xQueueNum is zero, return empty notifyRequests");
65 0 : return notifyRequests;
66 : }
67 0 : if (yQueueNum == 0) {
68 0 : HCCL_INFO("[InsTempReduceMesh2D] yQueueNum is zero, return empty notifyRequests");
69 0 : return notifyRequests;
70 : };
71 0 : u32 queueNum = xQueueNum + yQueueNum;
72 :
73 0 : u32 slaveNum = queueNum - 1;
74 0 : if (slaveNum < 1) {
75 0 : HCCL_INFO("[InsTempReduceMesh2D] slaveNum is zero, return empty notifyRequests");
76 0 : return notifyRequests;
77 : }
78 :
79 0 : u32 ctrlNotfiyReqNum = 2; // X轴向的控制流(主流)和Y轴向的控制流之间的Notify
80 0 : u32 xNotifyReqNum = (xQueueNum - 1) * 2; // X轴向的控制流和业务流之间的Notify
81 0 : u32 yNotifyReqNum = (yQueueNum - 1) * 2; // Y轴向的控制流和业务流之间的Notify
82 0 : u32 totalNotifyReqNum = ctrlNotfiyReqNum + xNotifyReqNum + yNotifyReqNum;
83 0 : notifyRequests.reserve(totalNotifyReqNum);
84 :
85 0 : QId xCtrlId = 0;
86 0 : QId yCtrlId = xCtrlId + xNotifyReqNum;
87 :
88 0 : notifyRequests.emplace_back(std::make_tuple(xCtrlId, yCtrlId, 0));
89 0 : notifyRequests.emplace_back(std::make_tuple(yCtrlId, xCtrlId, 0));
90 :
91 0 : for (QId xId = xCtrlId + 1; xId < xNotifyReqNum; ++xId) {
92 0 : notifyRequests.emplace_back(std::make_tuple(xCtrlId, xId, 0));
93 0 : notifyRequests.emplace_back(std::make_tuple(xId, xCtrlId, 0));
94 : }
95 :
96 0 : for (QId yId = yCtrlId + 1; yId < xNotifyReqNum + yNotifyReqNum; ++yId) {
97 0 : notifyRequests.emplace_back(std::make_tuple(yCtrlId, yId, 0));
98 0 : notifyRequests.emplace_back(std::make_tuple(yId, yCtrlId, 0));
99 : }
100 :
101 0 : HCCL_DEBUG(
102 : "[InsTempReduceMesh2D] Create notifies request: "
103 : "totalNotifyReqNum[%u], ctrlNotfiyReqNum[%u], xNotifyReqNum[%u], yNotifyReqNum[%u]",
104 : totalNotifyReqNum, ctrlNotfiyReqNum, xNotifyReqNum, yNotifyReqNum);
105 :
106 0 : return notifyRequests;
107 0 : }
108 :
109 0 : HcclResult InsTempReduceMesh2D::CalcResLinksConcurrMesh(
110 : const RankId myRank, const u32 tempRankSize, const std::vector<std::vector<RankId>>& tempVTopo,
111 : const u32 linkNumBtwPeers, AlgTempResReq& tempResReq) const
112 : {
113 : (void)tempRankSize;
114 : u32 myAlgRank;
115 0 : for (u32 dim = 0; dim < tempVTopo.size(); dim++) {
116 0 : CHK_RET(GetAlgRank(myRank, tempVTopo[dim], myAlgRank));
117 0 : for (u32 queIdx = 0; queIdx < tempVTopo[dim].size() - 1; queIdx++) {
118 0 : RankId neighborRank = tempVTopo[dim][(myAlgRank + 1 + queIdx) % (tempVTopo[dim].size())];
119 0 : tempResReq.links[neighborRank] = linkNumBtwPeers;
120 : }
121 : }
122 0 : return HcclResult::HCCL_SUCCESS;
123 : }
124 :
125 0 : u32 InsTempReduceMesh2D::CalcScratchMultiple(BufferType inBuffType, BufferType outBuffType)
126 : {
127 : (void)inBuffType;
128 : (void)outBuffType;
129 :
130 : // 数据会在2个维度间切换通信,选择最大的维度切分scratch方便数据处理
131 0 : u32 scratchMultiple = max(tempVTopo_.at(AXIS_X).size(), tempVTopo_.at(AXIS_Y).size());
132 0 : HCCL_INFO("[InsTempReduceMesh2D] Scratch multiple is [%u]", scratchMultiple);
133 0 : return scratchMultiple;
134 : }
135 :
136 0 : HcclResult InsTempReduceMesh2D::GenExtIns(
137 : const TempFuncs& tempFuncs, const TemplateDataParams& templateDataParams, const ResLinks& tempLinks,
138 : std::vector<InsQuePtr>& tempInsQues)
139 : {
140 : (void)tempFuncs;
141 0 : HCCL_INFO("[InsTempReduceMesh2D] GenExtIns start rank[%d]", myRank_);
142 :
143 0 : CHK_RET(CalcParams(templateDataParams));
144 :
145 : // 单卡场景可以直接Input拷贝到Output,单独判断
146 0 : if (tempRankSize_ == 1) {
147 0 : CHK_RET(LocalCopyFromInputToOutput(templateDataParams, tempInsQues));
148 0 : return HcclResult::HCCL_SUCCESS;
149 : }
150 :
151 : // 将队列分为2组,一组负责X轴向通信,一组负责Y轴向通信,两组中的第一条流兼任控制流
152 0 : std::vector<InsQuePtr> ctrlTempInsQues;
153 0 : std::vector<InsQuePtr> xTempInsQues;
154 0 : std::vector<InsQuePtr> yTempInsQues;
155 0 : CHK_RET(SplitInsQues(tempInsQues, ctrlTempInsQues, xTempInsQues, yTempInsQues));
156 :
157 0 : CHK_RET(PreSyncInterQueues(ctrlTempInsQues)); // XY轴并行启动
158 :
159 0 : if (u32(myRank_) == root_) {
160 : // 数据片A第一步通信
161 0 : CHK_RET(GatherFromInput(SLICE_A, AXIS_X, tempLinks, xTempInsQues));
162 0 : CHK_RET(ReduceToScratch(SLICE_A, AXIS_X, xTempInsQues));
163 : // 数据片B第一步通信
164 0 : CHK_RET(GatherFromInput(SLICE_B, AXIS_Y, tempLinks, yTempInsQues));
165 0 : CHK_RET(ReduceToScratch(SLICE_B, AXIS_Y, yTempInsQues));
166 : // X轴和Y轴控制流同步,然后交换处理数据
167 0 : CHK_RET(PreSyncInterQueues(ctrlTempInsQues));
168 0 : CHK_RET(PostSyncInterQueues(ctrlTempInsQues));
169 : // 数据片A第二步通信
170 0 : CHK_RET(GatherFromScratch(SLICE_A, AXIS_Y, tempLinks, yTempInsQues));
171 0 : CHK_RET(ReduceToOutput(SLICE_A, AXIS_Y, yTempInsQues));
172 : // 数据片B第二步通信
173 0 : CHK_RET(GatherFromScratch(SLICE_B, AXIS_X, tempLinks, xTempInsQues));
174 0 : CHK_RET(ReduceToOutput(SLICE_B, AXIS_X, xTempInsQues));
175 0 : } else if (axisRank_[AXIS_X] == axisRoot_[AXIS_X]) {
176 : // 数据片A通信
177 0 : CHK_RET(GatherFromInput(SLICE_A, AXIS_X, tempLinks, xTempInsQues));
178 0 : CHK_RET(ReduceToScratch(SLICE_A, AXIS_X, xTempInsQues));
179 0 : CHK_RET(SendFromScratch(SLICE_A, AXIS_Y, tempLinks, xTempInsQues));
180 : // 数据片B通信
181 0 : CHK_RET(SendFromInput(SLICE_B, AXIS_Y, tempLinks, yTempInsQues));
182 0 : } else if (axisRank_[AXIS_Y] == axisRoot_[AXIS_Y]) {
183 : // 数据片A通信
184 0 : CHK_RET(SendFromInput(SLICE_A, AXIS_X, tempLinks, xTempInsQues));
185 : // 数据片B通信
186 0 : CHK_RET(GatherFromInput(SLICE_B, AXIS_Y, tempLinks, yTempInsQues));
187 0 : CHK_RET(ReduceToScratch(SLICE_B, AXIS_Y, yTempInsQues));
188 0 : CHK_RET(SendFromScratch(SLICE_B, AXIS_X, tempLinks, yTempInsQues));
189 : } else {
190 : // 数据片A通信
191 0 : CHK_RET(SendFromInput(SLICE_A, AXIS_X, tempLinks, xTempInsQues));
192 : // 数据片B通信
193 0 : CHK_RET(SendFromInput(SLICE_B, AXIS_Y, tempLinks, yTempInsQues));
194 : }
195 :
196 0 : CHK_RET(PostSyncInterQueues(ctrlTempInsQues)); // 返回主流
197 :
198 0 : HCCL_INFO("[InsTempReduceMesh2D] GenExtIns finished rank[%d]", myRank_);
199 :
200 0 : return HcclResult::HCCL_SUCCESS;
201 0 : }
202 :
203 0 : HcclResult InsTempReduceMesh2D::CalcParams(const TemplateDataParams& templateDataParams)
204 : {
205 0 : axisRankSize_[AXIS_X] = tempVTopo_.at(AXIS_X).size();
206 0 : axisRankSize_[AXIS_Y] = tempVTopo_.at(AXIS_Y).size();
207 0 : axisRank_[AXIS_X] = u32(myRank_) % axisRankSize_[AXIS_X];
208 0 : axisRank_[AXIS_Y] = u32(myRank_) / axisRankSize_[AXIS_X];
209 0 : axisRoot_[AXIS_X] = root_ % axisRankSize_[AXIS_X];
210 0 : axisRoot_[AXIS_Y] = root_ / axisRankSize_[AXIS_X];
211 :
212 0 : u32 dataTypeSize = DataTypeSizeGet(dataType_);
213 : // 用count均分,防止数据截断;并且保证在奇数情况下SLICE_A的切分比SLICE_B大
214 0 : sliceSize_[SLICE_A] = (templateDataParams.sliceSize / dataTypeSize + 1) / SLICE_NUM * dataTypeSize;
215 0 : sliceSize_[SLICE_B] = templateDataParams.sliceSize - sliceSize_[SLICE_A];
216 :
217 0 : sliceInputBaseOffset_[SLICE_A] = templateDataParams.buffInfo.inBuffBaseOff;
218 0 : sliceInputBaseOffset_[SLICE_B] = sliceInputBaseOffset_[SLICE_A] + sliceSize_[SLICE_A];
219 :
220 0 : sliceOutputBaseOffset_[SLICE_A] = templateDataParams.buffInfo.outBuffBaseOff;
221 0 : sliceOutputBaseOffset_[SLICE_B] = sliceOutputBaseOffset_[SLICE_A] + sliceSize_[SLICE_A];
222 :
223 : // Scratch切分时,上下两部分都按照最大的轴向RankSize来切分,从而保证数据换轴通信时有足够的暂存Buffer来做确定性计算
224 0 : u32 maxAxisRankSize = max(axisRankSize_[AXIS_X], axisRankSize_[AXIS_Y]);
225 0 : sliceScratchBaseOffset_[SLICE_A] = templateDataParams.buffInfo.scratchBuffBaseOff;
226 0 : sliceScratchBaseOffset_[SLICE_B] = sliceScratchBaseOffset_[SLICE_A] + sliceSize_[SLICE_A] * maxAxisRankSize;
227 :
228 0 : return HcclResult::HCCL_SUCCESS;
229 : }
230 :
231 0 : HcclResult InsTempReduceMesh2D::SplitInsQues(
232 : std::vector<InsQuePtr>& tempInsQues, std::vector<InsQuePtr>& ctrlTempInsQues, std::vector<InsQuePtr>& xTempInsQues,
233 : std::vector<InsQuePtr>& yTempInsQues)
234 : {
235 0 : u32 expectQueNum = axisRankSize_[AXIS_X] + axisRankSize_[AXIS_Y];
236 0 : CHK_PRT_RET(
237 : tempInsQues.size() != expectQueNum,
238 : HCCL_ERROR(
239 : "[InsTempReduceMesh2D] The count of queues is invalid, expect [%u], now is [%u]", expectQueNum,
240 : tempInsQues.size()),
241 : HcclResult::HCCL_E_INTERNAL);
242 :
243 0 : ctrlTempInsQues.emplace_back(tempInsQues.at(0));
244 0 : ctrlTempInsQues.emplace_back(tempInsQues.at(axisRankSize_[AXIS_X]));
245 0 : xTempInsQues = std::vector<InsQuePtr>(tempInsQues.begin(), tempInsQues.begin() + axisRankSize_[AXIS_X]);
246 0 : yTempInsQues = std::vector<InsQuePtr>(tempInsQues.begin() + axisRankSize_[AXIS_X], tempInsQues.end());
247 :
248 0 : HCCL_INFO(
249 : "[InsTempReduceMesh2D] splitInsQues success, ctrlTempInsQuesNum[%zu], xTempInsQuesNum[%zu], "
250 : "yTempInsQuesNum[%zu]",
251 : ctrlTempInsQues.size(), xTempInsQues.size(), yTempInsQues.size());
252 :
253 0 : return HcclResult::HCCL_SUCCESS;
254 : }
255 :
256 0 : HcclResult InsTempReduceMesh2D::LocalCopyFromInputToOutput(
257 : const TemplateDataParams& templateDataParams, std::vector<InsQuePtr>& tempInsQues) const
258 : {
259 0 : DataSlice srcLocalSlice(BufferType::INPUT, 0, templateDataParams.sliceSize);
260 0 : DataSlice dstLocalSlice(BufferType::OUTPUT, 0, templateDataParams.sliceSize);
261 0 : CHK_PRT_RET(
262 : LocalCopy(tempInsQues[0], srcLocalSlice, dstLocalSlice),
263 : HCCL_ERROR("[InsTempReduceMesh2D] LocalCopy data failed"), HcclResult::HCCL_E_INTERNAL);
264 0 : return HcclResult::HCCL_SUCCESS;
265 : }
266 :
267 0 : HcclResult InsTempReduceMesh2D::GatherFromInput(
268 : const u32 slice, const u32 axis, const ResLinks& tempLinks, std::vector<InsQuePtr>& axisTempInsQues)
269 : {
270 0 : HCCL_DEBUG("[InsTempReduceMesh2D] Gather from input start.");
271 :
272 0 : CHK_PRT_RET(
273 : axisTempInsQues.empty(), HCCL_ERROR("[InsTempReduceMesh2D][GatherFromInput] axisTempInsQues is empty."),
274 : HcclResult::HCCL_E_INTERNAL);
275 0 : CHK_PTR_NULL(axisTempInsQues[0]);
276 0 : u64 sliceSize = sliceSize_[slice];
277 0 : u64 sliceScratchBaseOffset = sliceScratchBaseOffset_[slice];
278 :
279 0 : DataSlice srcDataSlice(BufferType::INPUT, sliceInputBaseOffset_[slice], sliceSize);
280 :
281 0 : if (axisTempInsQues.size() > 1) {
282 0 : CHK_RET(PreSyncInterQueues(axisTempInsQues));
283 : }
284 :
285 : // 主队列本地拷贝,从Input拷贝到Scratch
286 0 : DataSlice dstLocalSlice(BufferType::SCRATCH, sliceScratchBaseOffset + axisRoot_[axis] * sliceSize, sliceSize);
287 0 : CHK_PRT_RET(
288 : LocalCopy(axisTempInsQues[0], srcDataSlice, dstLocalSlice),
289 : HCCL_ERROR("[InsTempReduceMesh2D] LocalCopy data failed"), HcclResult::HCCL_E_INTERNAL);
290 :
291 : // 从队列负责接收来自其它rank的数据
292 0 : u32 queIdx = 1;
293 0 : for (u32 axisRank = 0; axisRank < tempVTopo_.at(axis).size(); ++axisRank) {
294 0 : RankId rmtRank = tempVTopo_.at(axis).at(axisRank);
295 0 : if (rmtRank == myRank_) {
296 0 : continue;
297 : }
298 :
299 0 : const LinkData& recvLink = tempLinks.at(rmtRank).at(0);
300 : // 按照发送rank的序号来计算接收数据存放的偏移
301 0 : DataSlice dstDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + axisRank * sliceSize, sliceSize);
302 0 : SlicesList recvSlicesList({srcDataSlice}, {dstDataSlice});
303 0 : DataInfo recvInfo(recvLink, recvSlicesList);
304 0 : CHK_PRT_THROW(
305 : queIdx >= axisTempInsQues.size(),
306 : HCCL_ERROR(
307 : "[InsTempReduceMesh2D] queIdx[%u] is bigger than axisTempInsQues size[%zu].", queIdx,
308 : axisTempInsQues.size()),
309 : InvalidParamsException, "queIdx is invalid");
310 0 : CHK_PRT_RET(
311 : Recv(recvInfo, axisTempInsQues[queIdx], 0, true, DmaMode::PUT),
312 : HCCL_ERROR("[InsTempReduceMesh2D] Recv data failed"), HcclResult::HCCL_E_INTERNAL);
313 :
314 0 : queIdx++;
315 0 : }
316 :
317 0 : if (axisTempInsQues.size() > 1) {
318 0 : CHK_RET(PostSyncInterQueues(axisTempInsQues));
319 : }
320 :
321 0 : return HcclResult::HCCL_SUCCESS;
322 : }
323 :
324 0 : HcclResult InsTempReduceMesh2D::GatherFromScratch(
325 : const u32 slice, const u32 axis, const ResLinks& tempLinks, std::vector<InsQuePtr>& axisTempInsQues)
326 : {
327 0 : HCCL_DEBUG("[InsTempReduceMesh2D] Gather from scratch start");
328 :
329 0 : u64 sliceSize = sliceSize_[slice];
330 0 : u64 sliceScratchBaseOffset = sliceScratchBaseOffset_[slice];
331 :
332 0 : DataSlice srcDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + axisRoot_[axis] * sliceSize, sliceSize);
333 :
334 0 : if (axisTempInsQues.size() > 1) {
335 0 : CHK_RET(PreSyncInterQueues(axisTempInsQues));
336 : }
337 :
338 : // 主队列本地拷贝,从Scratch拷贝到Output
339 0 : DataSlice dstLocalSlice(BufferType::OUTPUT, sliceOutputBaseOffset_[slice], sliceSize);
340 0 : CHK_PRT_RET(
341 : LocalCopy(axisTempInsQues[0], srcDataSlice, dstLocalSlice),
342 : HCCL_ERROR("[InsTempReduceMesh2D] LocalCopy data failed"), HcclResult::HCCL_E_INTERNAL);
343 :
344 : // 从队列负责接收来自其它rank的数据
345 0 : u32 queIdx = 1;
346 0 : for (u32 axisRank = 0; axisRank < tempVTopo_.at(axis).size(); ++axisRank) {
347 0 : RankId rmtRank = tempVTopo_.at(axis).at(axisRank);
348 0 : if (rmtRank == myRank_) {
349 0 : continue;
350 : }
351 :
352 0 : const LinkData& recvLink = tempLinks.at(rmtRank).at(0);
353 : // 按照发送rank的序号来计算接收数据存放的偏移
354 0 : DataSlice dstDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + axisRank * sliceSize, sliceSize);
355 0 : SlicesList recvSlicesList({srcDataSlice}, {dstDataSlice});
356 0 : DataInfo recvInfo(recvLink, recvSlicesList);
357 :
358 0 : CHK_PRT_RET(
359 : Recv(recvInfo, axisTempInsQues[queIdx], 0, true, DmaMode::PUT),
360 : HCCL_ERROR("[InsTempReduceMesh2D] Recv data failed"), HcclResult::HCCL_E_INTERNAL);
361 :
362 0 : queIdx++;
363 0 : }
364 :
365 0 : if (axisTempInsQues.size() > 1) {
366 0 : CHK_RET(PostSyncInterQueues(axisTempInsQues));
367 : }
368 :
369 0 : return HcclResult::HCCL_SUCCESS;
370 : }
371 :
372 0 : HcclResult InsTempReduceMesh2D::SendFromInput(
373 : const u32 slice, const u32 axis, const ResLinks& tempLinks, std::vector<InsQuePtr>& axisTempInsQues)
374 : {
375 0 : HCCL_DEBUG("[InsTempReduceMesh2D] Send from input start");
376 :
377 0 : u64 sliceSize = sliceSize_[slice];
378 :
379 0 : RankId rmtRank = tempVTopo_.at(axis).at(axisRoot_[axis]);
380 0 : const LinkData& sendLink = tempLinks.at(rmtRank).at(0);
381 :
382 0 : DataSlice srcDataSlice(BufferType::INPUT, sliceInputBaseOffset_[slice], sliceSize);
383 : DataSlice dstDataSlice(
384 0 : BufferType::SCRATCH, sliceScratchBaseOffset_[slice] + axisRank_[axis] * sliceSize, sliceSize);
385 0 : SlicesList sendSlicesList({srcDataSlice}, {dstDataSlice});
386 0 : DataInfo sendInfo(sendLink, sendSlicesList);
387 :
388 0 : CHK_PRT_RET(
389 : Send(sendInfo, axisTempInsQues[0], 0, true, DmaMode::PUT), HCCL_ERROR("[InsTempReduceMesh2D] Send data failed"),
390 : HcclResult::HCCL_E_INTERNAL);
391 :
392 0 : return HcclResult::HCCL_SUCCESS;
393 0 : }
394 :
395 0 : HcclResult InsTempReduceMesh2D::SendFromScratch(
396 : const u32 slice, const u32 axis, const ResLinks& tempLinks, std::vector<InsQuePtr>& axisTempInsQues)
397 : {
398 0 : HCCL_DEBUG("[InsTempReduceMesh2D] Send from scratch start");
399 :
400 0 : u64 sliceSize = sliceSize_[slice];
401 0 : u64 sliceScratchBaseOffset = sliceScratchBaseOffset_[slice];
402 :
403 0 : RankId rmtRank = tempVTopo_.at(axis).at(axisRoot_[axis]);
404 0 : const LinkData& sendLink = tempLinks.at(rmtRank).at(0);
405 :
406 0 : DataSlice srcDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + axisRoot_[axis] * sliceSize, sliceSize);
407 0 : DataSlice dstDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + axisRank_[axis] * sliceSize, sliceSize);
408 0 : SlicesList sendSlicesList({srcDataSlice}, {dstDataSlice});
409 0 : DataInfo sendInfo(sendLink, sendSlicesList);
410 :
411 0 : CHK_PRT_RET(
412 : Send(sendInfo, axisTempInsQues[0], 0, true, DmaMode::PUT), HCCL_ERROR("[InsTempReduceMesh2D] Send data failed"),
413 : HcclResult::HCCL_E_INTERNAL);
414 :
415 0 : return HcclResult::HCCL_SUCCESS;
416 0 : }
417 :
418 : HcclResult
419 0 : InsTempReduceMesh2D::ReduceToScratch(const u32 slice, const u32 axis, std::vector<InsQuePtr>& axisTempInsQues)
420 : {
421 0 : HCCL_DEBUG("[InsTempReduceMesh2D] Reduce to scratch start");
422 :
423 0 : u64 sliceSize = sliceSize_[slice];
424 0 : u64 sliceScratchBaseOffset = sliceScratchBaseOffset_[slice];
425 :
426 : // 数据规约到scratch时,下一步会交换处理另一片数据,因此数据规约至axisRoot_[1-axis]的偏移位置,便于后续数据搬运
427 0 : DataSlice dstDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + axisRoot_[1 - axis] * sliceSize, sliceSize);
428 :
429 : // 另一轴Root值大于等于当前轴的RankSize时,需要将数据规约至原本无数据的区域,需要先拷贝第一片数据
430 0 : bool needLocalCopy = axisRoot_[1 - axis] >= axisRankSize_[axis];
431 0 : if (needLocalCopy) {
432 0 : DataSlice srcLocalSlice(BufferType::SCRATCH, sliceScratchBaseOffset, sliceSize);
433 0 : CHK_PRT_RET(
434 : LocalCopy(axisTempInsQues[0], srcLocalSlice, dstDataSlice),
435 : HCCL_ERROR("[InsTempReduceMesh2D] LocalCopy data failed"), HcclResult::HCCL_E_INTERNAL);
436 :
437 0 : for (u32 sliceId = 1; sliceId < axisRankSize_[axis]; ++sliceId) {
438 0 : DataSlice srcDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + sliceId * sliceSize, sliceSize);
439 0 : CHK_PRT_RET(
440 : LocalReduce(axisTempInsQues[0], srcDataSlice, dstDataSlice, dataType_, redOp_),
441 : HCCL_ERROR("[InsTempReduceMesh2D] Local reduce data failed"), HcclResult::HCCL_E_INTERNAL);
442 : }
443 :
444 0 : return HcclResult::HCCL_SUCCESS;
445 : }
446 :
447 : // 另一轴Root值小于当前轴RankSize时,按照数据片顺序逐个Reduce
448 0 : for (u32 sliceId = 0; sliceId < axisRankSize_[axis]; ++sliceId) {
449 0 : if (sliceId == axisRoot_[1 - axis]) {
450 0 : continue;
451 : }
452 0 : DataSlice srcDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + sliceId * sliceSize, sliceSize);
453 0 : CHK_PRT_RET(
454 : LocalReduce(axisTempInsQues[0], srcDataSlice, dstDataSlice, dataType_, redOp_),
455 : HCCL_ERROR("[InsTempReduceMesh2D] Local reduce data failed"), HcclResult::HCCL_E_INTERNAL);
456 : }
457 :
458 0 : return HcclResult::HCCL_SUCCESS;
459 : }
460 :
461 0 : HcclResult InsTempReduceMesh2D::ReduceToOutput(const u32 slice, const u32 axis, std::vector<InsQuePtr>& axisTempInsQues)
462 : {
463 0 : HCCL_DEBUG("[InsTempReduceMesh2D] Reduce to output start");
464 :
465 0 : u64 sliceSize = sliceSize_[slice];
466 0 : u64 sliceScratchBaseOffset = sliceScratchBaseOffset_[slice];
467 :
468 0 : DataSlice dstDataSlice(BufferType::OUTPUT, sliceOutputBaseOffset_[slice], sliceSize);
469 :
470 0 : for (u32 sliceId = 0; sliceId < axisRankSize_[axis]; ++sliceId) {
471 0 : if (sliceId == axisRoot_[axis]) { // 跳过轴向root的数据片,这一片已经提前拷贝至Output
472 0 : continue;
473 : }
474 0 : DataSlice srcDataSlice(BufferType::SCRATCH, sliceScratchBaseOffset + sliceId * sliceSize, sliceSize);
475 0 : CHK_PRT_RET(
476 : LocalReduce(axisTempInsQues[0], srcDataSlice, dstDataSlice, dataType_, redOp_),
477 : HCCL_ERROR("[InsTempReduceMesh2D] Local reduce data failed"), HcclResult::HCCL_E_INTERNAL);
478 : }
479 :
480 0 : return HcclResult::HCCL_SUCCESS;
481 : }
482 :
483 : } // namespace Hccl
|