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 "ins_temp_reduce_scatter_nhr.h"
12 : #include "log.h"
13 : #include "alg_data_trans_wrapper.h"
14 :
15 : namespace Hccl {
16 0 : InsTempReduceScatterNHR::InsTempReduceScatterNHR(
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 : InsTempReduceScatterNHR::~InsTempReduceScatterNHR() {}
23 :
24 0 : HcclResult InsTempReduceScatterNHR::CalcRes(AlgTempResReq& tempResReq)
25 : {
26 0 : CHK_PRT_RET(
27 : CalcResLinksNHR(myRank_, tempRankSize_, tempVTopo_, tempResReq) != HcclResult::HCCL_SUCCESS,
28 : HCCL_ERROR("[CollAlgFactory] [InsTempReduceScatterNHR] Rank [%d], resLinks calculation error!", myRank_),
29 : HcclResult::HCCL_E_INTERNAL);
30 0 : auto& linkReq = tempResReq.links;
31 0 : u32 pathNum = 0;
32 0 : for (auto resReqIter = linkReq.begin(); resReqIter != linkReq.end(); resReqIter++) {
33 0 : auto remoteRank = resReqIter->first;
34 0 : if (rank2PathNumMap_.find(remoteRank) == rank2PathNumMap_.end() || rank2PathNumMap_[remoteRank] == 0) {
35 0 : HCCL_ERROR("[InsTempReduceScatterNHR] No path to remoteRank[%d]", remoteRank);
36 0 : return HcclResult::HCCL_E_INTERNAL;
37 : }
38 0 : if (pathNum == 0) {
39 0 : pathNum = rank2PathNumMap_[remoteRank];
40 0 : } else if (rank2PathNumMap_[remoteRank] != pathNum) {
41 0 : HCCL_ERROR(
42 : "[InsTempReduceScatterNHR] Inconsistency pathNum to remoteRanks, Previous consistent pathNum=[%u], "
43 : "mismatched "
44 : "remoteRank=[%d], pathNum=[%u]",
45 : pathNum, remoteRank, rank2PathNumMap_[remoteRank]);
46 0 : return HcclResult::HCCL_E_INTERNAL;
47 : }
48 0 : resReqIter->second = pathNum;
49 : }
50 : // NHR 需要的 que Num 为 1 * pathNum
51 0 : tempResReq.queNum = pathNum;
52 0 : tempResReq.streamNum = tempResReq.queNum;
53 0 : tempResReq.queNotifys = CreateMasterSlaveQueNotifiesRequest(tempResReq.queNum);
54 0 : return HcclResult::HCCL_SUCCESS;
55 : }
56 :
57 : /*
58 : dataSize / (rankSize) --> chunkSize
59 : dataSize / (rankSize * queNum) --> sliceSize
60 :
61 : SliceInfoVecforNHR: [1st chunk: [1st Slice, 2nd Slice, ...], 2nd chunk: [1st Slice, 2nd Slice, ...], ...]
62 : */
63 : HcclResult
64 0 : InsTempReduceScatterNHR::CalcSliceInfo(const AllignInfo& allignInfo, const u64 dataSize, RankSliceInfo& sliceInfoVec)
65 : {
66 0 : std::vector<SliceInfo> tmp(tempVTopo_.size());
67 0 : sliceInfoVec.resize(tempRankSize_, tmp);
68 0 : CHK_RET(CalcRsAgSliceInfoNHR(myRank_, tempRankSize_, allignInfo, dataSize, sliceInfoVec));
69 :
70 0 : return HcclResult::HCCL_SUCCESS;
71 0 : }
72 :
73 0 : HcclResult InsTempReduceScatterNHR::Run(
74 : const TempFuncs& tempFuncs, const RankSliceInfo& sliceInfoVec, const BuffInfo& buffInfo, const ResLinks& tempLinks,
75 : std::vector<InsQuePtr>& tempInsQues)
76 : {
77 0 : if (IsPcieLink(tempLinks)) {
78 0 : dmaMode_ = DmaMode::GET;
79 : }
80 0 : opMode_ = tempFuncs.opMode;
81 0 : enableCounterNotify_ = tempFuncs.enableCounterNotify;
82 0 : buffInfo_ = buffInfo;
83 0 : queNum_ = tempVTopo_.size();
84 0 : CHK_PRT_RET(
85 : queNum_ != tempInsQues.size(),
86 : HCCL_ERROR("[CollAlgFactory] [InsTempReduceScatterNHR] Rank [%d], requiredQue Error.", myRank_),
87 : HcclResult::HCCL_E_INTERNAL);
88 0 : CHK_RET(PreCopy(tempFuncs, sliceInfoVec, tempInsQues));
89 0 : CHK_RET(RunReduceScatter(sliceInfoVec, tempLinks, tempInsQues));
90 0 : CHK_RET(PostCopy(tempFuncs, sliceInfoVec, tempInsQues));
91 0 : return HcclResult::HCCL_SUCCESS;
92 : }
93 :
94 0 : HcclResult InsTempReduceScatterNHR::PreCopy(
95 : const TempFuncs& tempFuncs, const RankSliceInfo& sliceInfoVec, std::vector<InsQuePtr>& tempInsQues)
96 : {
97 : (void)sliceInfoVec;
98 : // 通信前需要将所有的数据统一拷贝到 inBuff 上的对应位置。
99 0 : if (tempFuncs.isForepart && opMode_ == OpMode::OPBASE) {
100 : // 单算子模式下,第一个算子,需要将数据从 userIn 拷贝到 inBuff
101 0 : HCCL_INFO("[InsTempReduceScatterNHR][PreCopy] Opbase Forepart, copy from userIn to outBuff");
102 0 : CHK_RET(MultiSliceLocalCopy(tempInsQues[0], tempFuncs.usrData.usrInSlices, tempFuncs.usrData.scratchInSlices));
103 : } else {
104 : // 图模式或者单算子模式下非第一个算子,数据已经在 inbuff 上了,不需要拷贝
105 0 : HCCL_INFO("[InsTempReduceScatterNHR][PreCopy] not forpat and opbse, skip precopy");
106 : }
107 0 : return HcclResult::HCCL_SUCCESS;
108 : }
109 :
110 0 : HcclResult InsTempReduceScatterNHR::PostCopy(
111 : const TempFuncs& tempFuncs, const RankSliceInfo& sliceInfoVec, std::vector<InsQuePtr>& tempInsQues)
112 : {
113 : // 通信结束之后,数据都在 inbuff 上,需要搬运到对应的输出位置。
114 0 : if (tempFuncs.isBottom && opMode_ == OpMode::OPBASE) {
115 : // 如果是单算子模式, 并且是最后一步算子,需要将数据从 inBuff 拷贝到 userOut
116 : // 是否需要将数据搬运到 OutBuff 上再搬运到 UserOut 上??
117 0 : HCCL_INFO("[InsTempReduceScatterNHR][PostCopy] Opbase Bottom, copy from outBuff to userOut");
118 0 : CHK_RET(
119 : MultiSliceLocalCopy(tempInsQues[0], tempFuncs.usrData.scratchOutSlices, tempFuncs.usrData.usrOutSlices));
120 0 : } else if (tempFuncs.forAllReduce) {
121 : // 如果是 forAllReduce 算子的前半部分需要将数据从 inBuff 拷贝到 outBuff 并且加上本rank的偏移
122 0 : if (buffInfo_.inBuffType != buffInfo_.outBuffType || buffInfo_.inBuffBaseOff != buffInfo_.outBuffBaseOff) {
123 0 : HCCL_INFO("[InsTempReduceScatterNHR][PostCopy] forAllReduce, copy from inBuff to outBuff");
124 0 : u64 size = sliceInfoVec[tempVirtRankMap_[myRank_]][0].size;
125 0 : u64 srcOffset = sliceInfoVec[tempVirtRankMap_[myRank_]][0].offset;
126 0 : u64 dstOffset = sliceInfoVec[tempVirtRankMap_[myRank_]][0].offset;
127 0 : DataSlice srcSlice = DataSlice(buffInfo_.inBuffType, srcOffset + buffInfo_.inBuffBaseOff, size);
128 0 : DataSlice dstSlice = DataSlice(buffInfo_.outBuffType, dstOffset + buffInfo_.outBuffBaseOff, size);
129 0 : CHK_RET(LocalCopy(tempInsQues[0], srcSlice, dstSlice));
130 : } else {
131 0 : HCCL_INFO("[InsTempReduceScatterNHR][PostCopy] forAllReduce, inBuff same as outBuff, skip copy");
132 : }
133 : } else {
134 : // 如果是图模式,或者单算子模式但不是最后一步算子需要将数据从 inBuff 拷贝到 outBuff 顶头放
135 0 : u64 size = sliceInfoVec[tempVirtRankMap_[myRank_]][0].size;
136 0 : u64 srcOffset = sliceInfoVec[tempVirtRankMap_[myRank_]][0].offset + buffInfo_.inBuffBaseOff;
137 0 : u64 dstOffset = buffInfo_.outBuffBaseOff;
138 0 : if (buffInfo_.inBuffType == buffInfo_.outBuffType && srcOffset == dstOffset) {
139 0 : HCCL_INFO(
140 : "[InsTempReduceScatterNHR][PostCopy] not forpat and opbse, inBuffType same as outBuffType, skip copy");
141 : } else {
142 0 : HCCL_INFO("[InsTempReduceScatterNHR][PostCopy] not forpat and opbse, copy from outBuff to userOut");
143 0 : DataSlice srcSlice = DataSlice(buffInfo_.inBuffType, srcOffset, size);
144 0 : DataSlice dstSlice = DataSlice(buffInfo_.outBuffType, dstOffset, size);
145 0 : CHK_RET(LocalCopy(tempInsQues[0], srcSlice, dstSlice));
146 : }
147 : }
148 0 : return HcclResult::HCCL_SUCCESS;
149 : }
150 :
151 0 : HcclResult InsTempReduceScatterNHR::MultiSliceLocalCopy(
152 : InsQuePtr& insQue, const std::vector<DataSlice>& srcList, const std::vector<DataSlice>& dstList) const
153 : {
154 0 : CHK_PRT_RET(
155 : srcList.size() != dstList.size(),
156 : HCCL_ERROR(
157 : "[InsTempReduceScatterNHR] [LocalCopy] Rank [%d], srcList size[%llu] and "
158 : "dstList size[%llu] not same.",
159 : myRank_, srcList.size(), dstList.size()),
160 : HcclResult::HCCL_E_INTERNAL);
161 0 : CHK_RET(LocalCopySlices(insQue, srcList, dstList));
162 0 : return HcclResult::HCCL_SUCCESS;
163 : }
164 :
165 0 : HcclResult InsTempReduceScatterNHR::RunReduceScatter(
166 : const RankSliceInfo& sliceInfoVec, const ResLinks& tempLinks, std::vector<InsQuePtr>& tempInsQues)
167 : {
168 0 : std::vector<AicpuNHRStepInfo> stepInfoList;
169 0 : GetStepInfoList(stepInfoList);
170 0 : for (auto& stepInfo : stepInfoList) {
171 0 : HCCL_DEBUG(
172 : "[InsTempReduceScatterNHR][RunReduceScatter] step[%u], myRank[%u], toRank[%u], fromRank[%u], nSlices[%u].",
173 : stepInfo.step, stepInfo.myRank, stepInfo.toRank, stepInfo.fromRank, stepInfo.nSlices);
174 :
175 0 : const std::vector<LinkData>& linkRecv = tempLinks.at(GetRankFromMap(stepInfo.fromRank));
176 0 : const std::vector<LinkData>& linkSend = tempLinks.at(GetRankFromMap(stepInfo.toRank));
177 0 : std::vector<DataSlice> txSlices;
178 0 : std::vector<DataSlice> rxSlices;
179 :
180 : // 在 inBuff 上进行 ReduceScatter 操作
181 0 : for (u32 i = 0; i < stepInfo.nSlices; i++) {
182 0 : u64 txOffset = sliceInfoVec[stepInfo.txSliceIdxs[i]][0].offset + buffInfo_.inBuffBaseOff;
183 0 : u64 txSize = sliceInfoVec[stepInfo.txSliceIdxs[i]][0].size;
184 0 : u64 rxOffset = sliceInfoVec[stepInfo.rxSliceIdxs[i]][0].offset + buffInfo_.inBuffBaseOff;
185 0 : u64 rxSize = sliceInfoVec[stepInfo.rxSliceIdxs[i]][0].size;
186 0 : DataSlice txSlice = DataSlice(buffInfo_.inBuffType, txOffset, txSize);
187 0 : DataSlice rxSlice = DataSlice(buffInfo_.inBuffType, rxOffset, rxSize);
188 0 : txSlices.push_back(txSlice);
189 0 : rxSlices.push_back(rxSlice);
190 : }
191 : SendRecvReduceInfo sendRecvReduceInfo{
192 0 : {linkSend[0], linkRecv[0]}, {{txSlices, txSlices}, {rxSlices, rxSlices}}, dataType_, redOp_};
193 0 : CHK_PRT_RET(
194 : SendRecvReduce(sendRecvReduceInfo, tempInsQues[0], 0, true, dmaMode_),
195 : HCCL_ERROR("[InsTempReduceScatterNHR] RunReduceScatter SendRecvReduce failed"),
196 : HcclResult::HCCL_E_INTERNAL);
197 0 : }
198 0 : return HcclResult::HCCL_SUCCESS;
199 0 : }
200 :
201 0 : HcclResult InsTempReduceScatterNHR::GenExtIns(
202 : const TempFuncs& tempFuncs, const TemplateDataParams& tempAlgParams, const ResLinks& tempLinks,
203 : std::vector<InsQuePtr>& tempInsQues)
204 : {
205 0 : HCCL_INFO("[InsTempReduceScatterNHR] GenExtIns start");
206 0 : if (IsPcieLink(tempLinks)) {
207 0 : dmaMode_ = DmaMode::GET;
208 : }
209 0 : opMode_ = tempFuncs.opMode;
210 0 : enableCounterNotify_ = tempFuncs.enableCounterNotify;
211 0 : tempAlgParams_ = tempAlgParams;
212 0 : tempLinks_ = tempLinks;
213 0 : buffInfo_ = tempAlgParams_.buffInfo;
214 :
215 0 : uint32_t linkNum = tempLinks.begin()->second.size();
216 : // 流的数量不能少于linkNum
217 0 : CHK_PRT_RET(
218 : linkNum > tempInsQues.size(),
219 : HCCL_ERROR("[CollAlgFactory] [InsTempAllReduceNHR] Rank [%d], requiredQue Error.", myRank_),
220 : HcclResult::HCCL_E_INTERNAL);
221 :
222 0 : std::vector<float> dataSplitRate(linkNum);
223 0 : CHK_RET(CalcDataSplitRateForLinks(tempLinks.begin()->second, dataSplitRate));
224 : // 将一个RankSliceInfo,拆分成linkNum 个RankSliceInfo
225 0 : u64 typeSize = DataTypeSizeGet(dataType_);
226 0 : u64 dataCnt = tempAlgParams.sliceSize / typeSize;
227 0 : std::vector<RankSliceInfo> sliceInfoVecForAllLinks(linkNum);
228 0 : u64 linkSliceOffset = 0;
229 0 : for (u32 linkIdx = 0; linkIdx < linkNum; linkIdx++) {
230 0 : processSize_.emplace_back();
231 0 : linkSliceOffsetVec_.emplace_back();
232 0 : HCCL_INFO("[InsTempAllReduceNHR] linkIdx =%u", linkIdx);
233 0 : if (linkIdx != linkNum - 1) {
234 0 : processSize_[linkIdx] = static_cast<u64>(static_cast<float>(dataCnt) * dataSplitRate[linkIdx]) * typeSize;
235 : } else {
236 0 : processSize_[linkIdx] = tempAlgParams.sliceSize - linkSliceOffset;
237 : }
238 0 : linkSliceOffsetVec_[linkIdx] = linkSliceOffset;
239 0 : linkSliceOffset += processSize_[linkIdx];
240 : }
241 :
242 0 : u32 mainQueIdx = 0;
243 : // 流间前同步,主流通知从流,只有一个流则不做任何事
244 0 : CHK_RET(PreSyncQues(tempInsQues, mainQueIdx));
245 :
246 0 : for (uint32_t linkIdx = 0; linkIdx < linkNum; linkIdx++) {
247 0 : CHK_RET(LocalDataCopy(tempInsQues, tempFuncs, linkIdx));
248 :
249 0 : if (tempRankSize_ <= 1) {
250 0 : CHK_RET(PostLocalCopy(tempInsQues, linkIdx)); // input->scratch
251 0 : return HcclResult::HCCL_SUCCESS;
252 : }
253 :
254 0 : CHK_RET(RunNHR(tempInsQues, linkIdx));
255 0 : CHK_RET(PostLocalCopy(tempInsQues, linkIdx));
256 : }
257 0 : CHK_RET(PostSyncQues(tempInsQues, mainQueIdx));
258 0 : return HcclResult::HCCL_SUCCESS;
259 0 : }
260 :
261 : HcclResult
262 0 : InsTempReduceScatterNHR::LocalDataCopy(std::vector<InsQuePtr>& tempInsQues, const TempFuncs& tempFuncs, u32 linkIdx)
263 : {
264 0 : CHK_PRT_RET(tempInsQues.empty(), HCCL_ERROR("[RS-NHR][LocalDataCopy] empty queue"), HcclResult::HCCL_E_INTERNAL);
265 0 : InsQuePtr q = tempInsQues[linkIdx];
266 : u64 inBaseOff;
267 : u64 inOff;
268 0 : const u64 rptNum = std::max<u64>(1, tempAlgParams_.repeatNum);
269 0 : for (u32 localRandId = 0; localRandId < tempRankSize_; ++localRandId) {
270 0 : for (u64 rpt = 0; rpt < rptNum; ++rpt) {
271 0 : if (tempFuncs.isBottom) { // 后nhr 前一半数据
272 0 : inBaseOff = tempAlgParams_.buffInfo.inBuffBaseOff + rpt * tempAlgParams_.inputRepeatStride;
273 0 : inOff = inBaseOff + localRandId * tempAlgParams_.inputSliceStride + linkSliceOffsetVec_[linkIdx];
274 : } else { // 前nhr,后一半数据
275 0 : inBaseOff = tempAlgParams_.buffInfo.inBuffBaseOff + localRandId * tempAlgParams_.inputRepeatStride;
276 0 : inOff = inBaseOff + rpt * tempAlgParams_.inputSliceStride + linkSliceOffsetVec_[linkIdx];
277 : }
278 0 : const u64 scratchBase
279 0 : = tempAlgParams_.buffInfo.scratchBuffBaseOff + rpt * tempAlgParams_.outputRepeatStride;
280 0 : const u64 scOff = scratchBase + localRandId * tempAlgParams_.sliceSize + linkSliceOffsetVec_[linkIdx];
281 : // 如果源地址和目标地址相同,则不需要做拷贝
282 0 : if (tempAlgParams_.buffInfo.inBuffType != tempAlgParams_.buffInfo.scratBuffType || inOff != scOff) {
283 0 : DataSlice src(tempAlgParams_.buffInfo.inBuffType, inOff, processSize_[linkIdx]);
284 0 : DataSlice dst(tempAlgParams_.buffInfo.scratBuffType, scOff, processSize_[linkIdx]);
285 0 : auto ins = std::make_unique<InsLocalCopy>(src, dst);
286 0 : q->Append(std::move(ins));
287 0 : }
288 : }
289 : }
290 0 : return HcclResult::HCCL_SUCCESS;
291 0 : }
292 :
293 0 : HcclResult InsTempReduceScatterNHR::PostLocalCopy(std::vector<InsQuePtr>& tempInsQues, u32 linkIdx)
294 : {
295 0 : CHK_PRT_RET(tempInsQues.empty(), HCCL_ERROR("[RS-NHR][PostLocalCopy] empty queue"), HcclResult::HCCL_E_INTERNAL);
296 :
297 0 : const u32 myAlgIdx = tempVirtRankMap_.at(myRank_);
298 0 : InsQuePtr q = tempInsQues[linkIdx];
299 :
300 0 : const u64 rptNum = std::max<u64>(1, tempAlgParams_.repeatNum);
301 0 : for (u64 rpt = 0; rpt < rptNum; ++rpt) {
302 0 : const u64 outBaseOff = tempAlgParams_.buffInfo.outBuffBaseOff + rpt * tempAlgParams_.outputRepeatStride;
303 0 : const u64 scratchBase = tempAlgParams_.buffInfo.scratchBuffBaseOff + rpt * tempAlgParams_.outputRepeatStride;
304 :
305 0 : const u64 scOff = scratchBase + tempAlgParams_.sliceSize * myAlgIdx + linkSliceOffsetVec_[linkIdx];
306 0 : const u64 outOff = outBaseOff + linkSliceOffsetVec_[linkIdx];
307 0 : DataSlice src(tempAlgParams_.buffInfo.scratBuffType, scOff, processSize_[linkIdx]);
308 0 : DataSlice dst(tempAlgParams_.buffInfo.outBuffType, outOff, processSize_[linkIdx]);
309 0 : if (tempAlgParams_.buffInfo.scratBuffType != tempAlgParams_.buffInfo.outBuffType || scOff != outOff) {
310 0 : auto ins = std::make_unique<InsLocalCopy>(src, dst);
311 0 : q->Append(std::move(ins));
312 0 : }
313 : }
314 0 : return HcclResult::HCCL_SUCCESS;
315 0 : }
316 :
317 0 : HcclResult InsTempReduceScatterNHR::RunNHR(std::vector<InsQuePtr>& tempInsQues, u32 linkIdx)
318 : {
319 0 : CHK_PRT_RET(tempInsQues.empty(), HCCL_ERROR("[RS-NHR][RunNHR] empty queue"), HcclResult::HCCL_E_INTERNAL);
320 :
321 0 : if (tempRankSize_ <= 1)
322 0 : return HcclResult::HCCL_SUCCESS;
323 :
324 0 : InsQuePtr q = tempInsQues[linkIdx];
325 :
326 : // 步进参数
327 0 : const u64 rptNum = std::max<u64>(1, tempAlgParams_.repeatNum);
328 :
329 : // 预计算步骤列表(算法序)
330 0 : std::vector<AicpuNHRStepInfo> steps;
331 0 : CHK_RET(GetStepInfoList(steps));
332 0 : for (u32 s = 0; s < steps.size(); ++s) {
333 0 : const auto& st = steps[s];
334 :
335 0 : const RankId recvFromRank = GetRankFromMap(st.fromRank);
336 0 : const RankId sendToRank = GetRankFromMap(st.toRank);
337 0 : CHK_PRT_RET(
338 : recvFromRank == static_cast<RankId>(-1) || sendToRank == static_cast<RankId>(-1),
339 : HCCL_ERROR("[RS-NHR][RunNHR] rank map failed: from[%u] to[%u]", st.fromRank, st.toRank),
340 : HcclResult::HCCL_E_INTERNAL);
341 :
342 0 : auto itRecv = tempLinks_.find(recvFromRank);
343 0 : auto itSend = tempLinks_.find(sendToRank);
344 0 : CHK_PRT_RET(
345 : itRecv == tempLinks_.end() || itRecv->second.empty() || itSend == tempLinks_.end()
346 : || itSend->second.empty(),
347 : HCCL_ERROR("[RS-NHR][RunNHR] link missing: recvFrom=%d sendTo=%d", recvFromRank, sendToRank),
348 : HcclResult::HCCL_E_INTERNAL);
349 :
350 0 : const LinkData& linkRecv = itRecv->second[linkIdx];
351 0 : const LinkData& linkSend = itSend->second[linkIdx];
352 :
353 0 : std::vector<DataSlice> txSlices;
354 0 : std::vector<DataSlice> rxSlices;
355 0 : txSlices.reserve(st.nSlices);
356 0 : rxSlices.reserve(st.nSlices);
357 0 : for (u64 rpt = 0; rpt < rptNum; ++rpt) {
358 0 : const u64 scratchBase
359 0 : = tempAlgParams_.buffInfo.scratchBuffBaseOff + rpt * tempAlgParams_.outputRepeatStride;
360 :
361 : // RS:在 SCRATCH 上进行规约交换
362 0 : for (u32 i = 0; i < st.nSlices; ++i) {
363 0 : const u32 txIdx = st.txSliceIdxs[i]; // 算法序
364 0 : const u32 rxIdx = st.rxSliceIdxs[i];
365 0 : const u64 txScOff = scratchBase + tempAlgParams_.sliceSize * txIdx + linkSliceOffsetVec_[linkIdx];
366 0 : const u64 rxScOff = scratchBase + tempAlgParams_.sliceSize * rxIdx + linkSliceOffsetVec_[linkIdx];
367 0 : txSlices.emplace_back(tempAlgParams_.buffInfo.scratBuffType, txScOff, processSize_[linkIdx]);
368 0 : rxSlices.emplace_back(tempAlgParams_.buffInfo.scratBuffType, rxScOff, processSize_[linkIdx]);
369 : }
370 : }
371 0 : SendRecvReduceInfo info{{linkSend, linkRecv}, {{txSlices, txSlices}, {rxSlices, rxSlices}}, dataType_, redOp_};
372 :
373 0 : CHK_PRT_RET(
374 : SendRecvReduce(info, tempInsQues[linkIdx], 0, true, dmaMode_),
375 : HCCL_ERROR("[RS-NHR][RunNHR] SendRecvReduce failed (step=%u)", st.step), HcclResult::HCCL_E_INTERNAL);
376 0 : }
377 :
378 0 : return HcclResult::HCCL_SUCCESS;
379 0 : }
380 :
381 : // 计算每轮收发的对端以及slice编号
382 0 : HcclResult InsTempReduceScatterNHR::GetStepInfoList(std::vector<AicpuNHRStepInfo>& stepInfoList)
383 : {
384 : // 将本 rank 号转换成算法使用的索引号
385 0 : u32 rankIdx = tempVirtRankMap_[myRank_];
386 0 : stepInfoList.clear();
387 :
388 0 : u32 nSteps = GetNHRStepNum(tempRankSize_);
389 0 : stepInfoList.resize(nSteps);
390 0 : for (u32 step = 0; step < nSteps; step++) {
391 : // 计算通信对象
392 0 : u32 deltaRank = 1 << step;
393 0 : u32 sendTo = (rankIdx + tempRankSize_ - deltaRank) % tempRankSize_;
394 0 : u32 recvFrom = (rankIdx + deltaRank) % tempRankSize_;
395 :
396 : // 数据份数和数据编号增量
397 0 : u32 nSlices = (tempRankSize_ - 1 + (1 << step)) / (1 << (step + 1));
398 0 : u32 deltaSliceIndex = 1 << (step + 1);
399 0 : u32 txSliceIdx = sendTo;
400 0 : u32 rxSliceIdx = rankIdx;
401 :
402 0 : AicpuNHRStepInfo& currStepInfo = stepInfoList[step];
403 0 : currStepInfo.step = step;
404 0 : currStepInfo.myRank = rankIdx;
405 0 : currStepInfo.nSlices = nSlices;
406 0 : currStepInfo.toRank = sendTo;
407 0 : currStepInfo.fromRank = recvFrom;
408 :
409 : // 计算本rank在每轮收/发中的slice编号
410 0 : currStepInfo.txSliceIdxs.reserve(nSlices);
411 0 : currStepInfo.rxSliceIdxs.reserve(nSlices);
412 0 : for (u32 i = 0; i < nSlices; i++) {
413 0 : currStepInfo.txSliceIdxs.push_back(txSliceIdx);
414 0 : currStepInfo.rxSliceIdxs.push_back(rxSliceIdx);
415 0 : HCCL_DEBUG(
416 : "[InsTempReduceScatterNHR][GetStepInfoList] i[%u] txSliceIdx[%u] rxSliceIdx[%u]", i, txSliceIdx,
417 : rxSliceIdx);
418 0 : txSliceIdx = (txSliceIdx + tempRankSize_ - deltaSliceIndex) % tempRankSize_;
419 0 : rxSliceIdx = (rxSliceIdx + tempRankSize_ - deltaSliceIndex) % tempRankSize_;
420 : }
421 : }
422 0 : return HcclResult::HCCL_SUCCESS;
423 : }
424 :
425 0 : RankId InsTempReduceScatterNHR::GetRankFromMap(const u32 rankIdx)
426 : {
427 0 : HCCL_INFO("[InsTempReduceScatterNHR] GetRankFromMap");
428 0 : RankId rank = -1;
429 0 : for (auto& pair : tempVirtRankMap_) {
430 0 : if (pair.second == rankIdx) {
431 0 : rank = pair.first;
432 0 : break;
433 : }
434 : }
435 0 : return rank;
436 : }
437 :
438 0 : HcclResult InsTempReduceScatterNHR::GetScratchBufferInfo(const uint64_t scratchBufferSize, DataType dataType) const
439 : {
440 : (void)scratchBufferSize;
441 : (void)dataType;
442 0 : return HcclResult::HCCL_SUCCESS;
443 : }
444 : } // namespace Hccl
|