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 "ccu_context_scatter_mesh2d.h"
12 : #include "ccu_instruction_scatter_mesh2d.h"
13 :
14 : namespace Hccl {
15 :
16 : constexpr int VAR_IDX_0 = 0; // transport远端变量,一个transport当前最多只能有3个Var
17 : constexpr int VAR_IDX_1 = 1;
18 : constexpr int VAR_IDX_2 = 2;
19 : constexpr int CKE_IDX_0 = 0; // 专门给后同步使用
20 : constexpr int CKE_IDX_1 = 1; // 前同步使用
21 : constexpr int CKE_IDX_2 = 2; // 前同步使用
22 : constexpr int CKE_IDX_3 = 3; // 前同步使用
23 : constexpr int CKE_AXIS = 4; // 给die间同步使用
24 : constexpr int DIM_NUM = 2;
25 : constexpr int ZERO = 0;
26 : constexpr int DIM_X = 0;
27 : constexpr int DIM_Y = 1;
28 :
29 0 : CcuContextScatterMesh2D::CcuContextScatterMesh2D(const CcuCtxArg &arg, const std::vector<CcuTransport *> &transports,
30 0 : const CcuTransportGroup &group)
31 0 : : CcuContextAlgBase(arg, transports, group)
32 : {
33 0 : const CcuCtxArgScatterMesh2D *ctxArg = dynamic_cast<const CcuCtxArgScatterMesh2D *>(&arg);
34 0 : if (ctxArg == nullptr) {
35 0 : THROW<NullPtrException>(StringFormat("CcuContextScatterMesh2D::ctxArg ptr is null"));
36 : }
37 0 : rankId_ = ctxArg->rankId_;
38 0 : dimSize_ = ctxArg->dimSize_; // vector, dimSize_[0]表示X轴的rank数,dimSize_[1]表示Y轴的rank数
39 0 : axisId_ = ctxArg->axisId_; // 由外部传入,指明当前在X轴或者Y轴的CCU上
40 0 : rankSize_ = ctxArg->rankSize_;
41 0 : root_ = ctxArg->root_;
42 : // 参数校验
43 0 : if (transports.size() == 0) {
44 0 : THROW<NullPtrException>(StringFormat("CcuContextScatterMesh2D transports is empty"));
45 : }
46 0 : if (dimSize_.size() != DIM_NUM || dimSize_[0] == ZERO || dimSize_[1] == ZERO || rankSize_ == ZERO ||
47 0 : axisId_ >= DIM_NUM) {
48 0 : THROW<NullPtrException>(StringFormat("[CcuContextScatterMesh2D]ctxArg params is invalid"));
49 : }
50 :
51 : // 分解出当前Rank的行列坐标
52 0 : dimId_.emplace_back(rankId_ % dimSize_[0]); // dimId_[0]表示在X轴1Dmesh拓扑中的localId
53 0 : dimId_.emplace_back(rankId_ / dimSize_[0]); // dimId_[1]表示在Y轴1Dmesh拓扑中的localId
54 :
55 : // 分解出Root的行列坐标
56 0 : rootDimId_.emplace_back(root_ % dimSize_[0]);
57 0 : rootDimId_.emplace_back(root_ / dimSize_[0]);
58 :
59 0 : localId_ = dimId_[axisId_];
60 0 : localSize_ = dimSize_[axisId_];
61 :
62 0 : localAxisSignal_ = CreateMaskSignal();
63 :
64 0 : localAxisSignalName_ = "CcuContextScatter2DAxisSync_" + std::to_string(axisId_);
65 0 : anotherAxisSignalName_ = "CcuContextScatter2DAxisSync_" + std::to_string(1 - axisId_);
66 :
67 0 : HCCL_INFO("[ContextScatter2DMesh.init] rankId_[%llu], dimSize_[0][%llu], dimSize_[1][%llu], axisId_[%llu], "
68 : "root_[%llu], localId_[%llu], localSize_[%llu] ",
69 : rankId_, dimSize_[0], dimSize_[1], axisId_, root_, localId_, localSize_);
70 0 : }
71 :
72 0 : bool CcuContextScatterMesh2D::SameRowWithRoot()
73 : {
74 0 : bool directConnected = false;
75 0 : if (dimId_[DIM_Y] == rootDimId_[DIM_Y]) {
76 0 : directConnected = true;
77 : }
78 0 : return directConnected;
79 : }
80 :
81 0 : bool CcuContextScatterMesh2D::SameColumnWithRoot()
82 : {
83 0 : bool directConnected = false;
84 0 : if (dimId_[DIM_X] == rootDimId_[DIM_X]) {
85 0 : directConnected = true;
86 : }
87 0 : return directConnected;
88 : }
89 :
90 0 : void CcuContextScatterMesh2D::PrepareVariables()
91 : {
92 0 : u32 transportId = 0;
93 0 : CHK_PRT_RET(transports.size() < localSize_,
94 : HCCL_ERROR("[CcuContextScatterMesh2D] transports size is less than localSize"),);
95 0 : input_ = CreateVariable();
96 0 : sliceSize_ = CreateVariable();
97 0 : stride_ = CreateVariable();
98 0 : for (u64 id = 0; id < localSize_; id++) {
99 0 : if (id == localId_) {
100 0 : scratch_.push_back(CreateVariable());
101 0 : output_.push_back(CreateVariable());
102 0 : token_.push_back(CreateVariable());
103 : } else { // 非本地,使用远端Variable
104 0 : CHK_PRT_RET(transports[transportId] == nullptr,
105 : HCCL_ERROR("[CcuContextScatterMesh2D] Algorithm transport ptr is null"),);
106 0 : scratch_.push_back(CreateVariable((*transports[transportId]), VAR_IDX_0));
107 0 : output_.push_back(CreateVariable((*transports[transportId]), VAR_IDX_1));
108 0 : token_.push_back(CreateVariable((*transports[transportId]), VAR_IDX_2));
109 0 : transportId++;
110 : }
111 : }
112 0 : axisSliceSize_.push_back(CreateVariable());
113 0 : axisSliceSize_.push_back(CreateVariable());
114 :
115 0 : ExportMaskSignal(localAxisSignal_, localAxisSignalName_); // 将本地的信号export出去
116 0 : anotherAxisSignal_ = ImportMaskSignal(anotherAxisSignalName_); // 导入另一个die的mask信号
117 0 : curGoSize_ = CreateGroupOpSize();
118 0 : return;
119 : }
120 :
121 0 : void CcuContextScatterMesh2D::LoadArgs()
122 : {
123 : // 模板中的可变入参
124 : // 地址相关参数:input_,output_,scratch_, token_
125 : // 数据相关参数:sliceSize_, stride_, axisSliceSize_ (axisSliceSize[DIM_X]为slice中通过x轴先传输的部分)
126 : // 顺序:inputAddr, outputAddr, scratchAddr, tokenInfo, sliceSize, stride, xSliceSize, ySliceSize
127 0 : Load(input_);
128 0 : Load(output_[localId_]);
129 0 : Load(token_[localId_]);
130 0 : Load(scratch_[localId_]);
131 0 : Load(sliceSize_);
132 0 : Load(stride_);
133 0 : Load(axisSliceSize_[DIM_X]);
134 0 : Load(axisSliceSize_[DIM_Y]);
135 0 : Load(curGoSize_);
136 0 : return;
137 : }
138 :
139 0 : void CcuContextScatterMesh2D::PreSync()
140 : {
141 0 : uint16_t selfBit = 1 << localId_; // 本rank的mask
142 0 : uint16_t allBit = ((1 << localSize_) - 1) & (~(1 << localId_));
143 :
144 0 : for (auto t : transports) {
145 0 : if (t == nullptr) {
146 0 : THROW<NullPtrException>(StringFormat("CcuContextScatterMesh2D::PreSync, transport ptr is null"));
147 : }
148 0 : WriteVariableWithSignal(*t, scratch_[localId_], VAR_IDX_0, CKE_IDX_1,
149 : selfBit); // 传递CCLBuf信息, 把自己的CCLbuf给所有对端
150 0 : WriteVariableWithSignal(*t, output_[localId_], VAR_IDX_1, CKE_IDX_2, selfBit); // 传递output信息
151 0 : WriteVariableWithSignal(*t, token_[localId_], VAR_IDX_2, CKE_IDX_3, selfBit); // 传递token信息
152 : }
153 :
154 0 : GroupWait(*transportGroup, CKE_IDX_1, allBit); //等齐所有对端的信息
155 0 : GroupWait(*transportGroup, CKE_IDX_2, allBit);
156 0 : GroupWait(*transportGroup, CKE_IDX_3, allBit);
157 0 : return;
158 : }
159 :
160 0 : void CcuContextScatterMesh2D::Sync(uint32_t ckeId)
161 : {
162 0 : uint16_t selfBit = 1 << localId_; // 本rank的mask
163 0 : uint16_t allBit = ((1 << localSize_) - 1) & (~(1 << localId_));
164 :
165 0 : for (auto t : transports) {
166 0 : if (t == nullptr) {
167 0 : THROW<NullPtrException>(StringFormat("CcuContextScatterMesh2D::PostSync, transport ptr is null"));
168 : }
169 0 : RemotePost(*t, ckeId, selfBit);
170 : }
171 :
172 0 : GroupWait(*transportGroup, ckeId, allBit);
173 0 : return;
174 : }
175 :
176 0 : void CcuContextScatterMesh2D::AxisSync(uint32_t signalIndex)
177 : {
178 0 : if (signalIndex > 1) {
179 0 : THROW<InvalidParamsException>(StringFormat("[CcuContextScatterMesh2D] Unexpected SignalInex[%u]", signalIndex));
180 : }
181 0 : LocalCtxPost(anotherAxisSignal_, 1 << (axisId_ + signalIndex * DIM_NUM));
182 0 : LocalWait(localAxisSignal_, 1 << (1 - axisId_ + signalIndex * DIM_NUM));
183 0 : return;
184 : }
185 :
186 : // 每次调用,准备好1D范围内,所有需要传递的src和dst,size固定为(localSize-1)
187 0 : void CcuContextScatterMesh2D::CcuWrite1DMesh(std::vector<CcuRep::Memory> &src, std::vector<CcuRep::Memory> &dst,
188 : CcuRep::Variable &size)
189 : {
190 0 : CcuRep::MaskSignal locMask = CreateMaskSignal();
191 0 : uint16_t allBitWithoutLocal = ((1 << localSize_) - 1) & (~(1 << src.size()));
192 0 : uint64_t transportId = 0;
193 0 : for (uint16_t r = 0; r < src.size(); r++) {
194 0 : CCU_IF(size == 0) {
195 0 : LocalPost(locMask, 1 << r);
196 0 : }
197 0 : CCU_IF(size != 0) {
198 0 : Write(*transports[transportId], dst[r], src[r], size, locMask, 1 << r);
199 0 : }
200 0 : transportId++;
201 : }
202 : // 等写完所有对端
203 0 : LocalWait(locMask, allBitWithoutLocal);
204 0 : return;
205 0 : }
206 :
207 0 : uint64_t CcuContextScatterMesh2D::CoordinateToGlobalId(uint32_t x, uint32_t y)
208 : {
209 0 : uint64_t id = 0;
210 0 : if (axisId_ == DIM_X) {
211 0 : id = x + y * dimSize_[0];
212 : } else {
213 0 : id = y + x * dimSize_[0];
214 : }
215 0 : return id;
216 : }
217 :
218 : // a = a + i * b
219 0 : void CcuContextScatterMesh2D::CcuMultiply(CcuRep::Memory &a, CcuRep::Variable &b, uint64_t i) const
220 : {
221 0 : for (uint64_t j = 0; j < i; j++) {
222 0 : a.addr += b;
223 : }
224 0 : return;
225 : }
226 :
227 0 : void CcuContextScatterMesh2D::RelaySendFor1D(std::vector<CcuRep::Memory> &relaySrc,
228 : std::vector<CcuRep::Memory> &relayDst, uint64_t j)
229 : {
230 0 : uint64_t globalId = 0;
231 0 : relaySrc.clear();
232 0 : relayDst.clear();
233 0 : for (uint64_t i = 0; i < dimSize_[axisId_]; i++) {
234 0 : if (i != dimId_[axisId_]) {
235 : // 准备中转数据
236 0 : CcuRep::Memory src = CreateMemory();
237 0 : CcuRep::Memory dst = CreateMemory();
238 0 : src.token = token_[i];
239 0 : dst.token = token_[i];
240 : // i,j的顺序为先本轴(axisId), 再另外一个轴(anotherAxisId)
241 0 : globalId = CoordinateToGlobalId(i, j);
242 0 : HCCL_INFO("[CcuContextScatterMesh2D][PrepareRootSendInfo] src globalId[%llu], curRank[%u], j[%llu], i[%llu] ",
243 : globalId, rankId_, j, i);
244 0 : src.addr = input_;
245 0 : CcuMultiply(src, stride_, globalId); // src偏移:src += stride_ * globalId
246 0 : dst.addr = scratch_[i];
247 0 : CcuMultiply(dst, sliceSize_,
248 : globalId); // dst偏移, dst为scratch,没有stride相关,dst += sliceSize_ * globalId
249 0 : if (axisId_ == DIM_Y) {
250 0 : src.addr += axisSliceSize_[DIM_X];
251 0 : dst.addr += axisSliceSize_[DIM_X];
252 : }
253 0 : relaySrc.emplace_back(src);
254 0 : relayDst.emplace_back(dst);
255 0 : }
256 : }
257 0 : HCCL_INFO("[CcuContextScatterMesh2D][PrepareRootSendInfo] relaySrcSize[%zu], relayDstSize_[%zu] ", relaySrc.size(),
258 : relayDst.size());
259 0 : CcuWrite1DMesh(relaySrc, relayDst, axisSliceSize_[axisId_]);
260 0 : return;
261 : }
262 :
263 : // ********************************************
264 : // 准备Root需要发送的“中转”地址,并发送
265 : // relaySrc: “中转”数据,从Root的inputAddr发送到同轴其他卡的scratchAddr
266 : // relayDst: 对端的scratchAddr
267 : // ********************************************
268 0 : void CcuContextScatterMesh2D::PrepareAndTransferRootRelayInfo(std::vector<CcuRep::Memory> &relaySrc,
269 : std::vector<CcuRep::Memory> &relayDst)
270 : {
271 0 : HCCL_INFO("[CcuContextScatterMesh2D][PrepareRootSendInfo] start axisId_[%llu]", axisId_);
272 : // 准备中转数据: i 为所有对端,负责中转数据,所有数据均发至i上; j为中转目的地
273 0 : HCCL_INFO("[CcuContextScatterMesh2D][PrepareRootSendInfo] axisId[%llu], dimSize_[%llu] ", axisId_,
274 : dimSize_[1 - axisId_]);
275 0 : for (uint64_t j = 0; j < dimSize_[1 - axisId_]; j++) {
276 0 : if (j != dimId_[1 - axisId_]) {
277 0 : RelaySendFor1D(relaySrc, relayDst, j);
278 : }
279 : }
280 0 : HCCL_INFO("[CcuContextScatterMesh2D][PrepareRootSendInfo] Done axisId_[%llu]", axisId_);
281 0 : return;
282 : }
283 :
284 : // directSrc:“直达”数据,从root的inputAddr发送到同轴其他卡的outputAddr
285 : // directDst; 对端的outputAddr
286 0 : void CcuContextScatterMesh2D::PrepareAndTransferRootDirectInfo(std::vector<CcuRep::Memory> &directSrc,
287 : std::vector<CcuRep::Memory> &directDst)
288 : {
289 0 : uint64_t globalId = 0;
290 : // 准备直达数据,直达数据只在自己的axisId上做1D的发送
291 : // i为要发送直达数据的对端, 不包含本地
292 0 : directSrc.clear();
293 0 : directDst.clear();
294 0 : for (uint64_t i = 0; i < dimSize_[axisId_]; i++) {
295 0 : if (i != dimId_[axisId_]) {
296 0 : CcuRep::Memory src = CreateMemory();
297 0 : CcuRep::Memory dst = CreateMemory();
298 0 : src.token = token_[i];
299 0 : dst.token = token_[i];
300 0 : globalId = CoordinateToGlobalId(i, dimId_[1 - axisId_]);
301 0 : HCCL_INFO("[CcuContextScatterMesh2D][PrepareRootSendInfo] src globalId[%u], curRank[%u]", globalId,
302 : rankId_);
303 0 : src.addr = input_;
304 0 : CcuMultiply(src, stride_, globalId);
305 0 : dst.addr = output_[i]; // output只有一片,不需要偏移
306 0 : directSrc.emplace_back(src);
307 0 : directDst.emplace_back(dst);
308 0 : }
309 : }
310 0 : CcuWrite1DMesh(directSrc, directDst, sliceSize_);
311 0 : return;
312 : }
313 :
314 0 : void CcuContextScatterMesh2D::LocalTransfer()
315 : {
316 0 : CcuRep::MaskSignal locMask = CreateMaskSignal();
317 0 : CcuRep::Memory src = CreateMemory();
318 0 : CcuRep::Memory dst = CreateMemory();
319 0 : src.token = token_[localId_];
320 0 : dst.token = token_[localId_];
321 0 : src.addr = input_;
322 0 : if (axisId_ == DIM_Y) {
323 0 : src.addr += axisSliceSize_[DIM_X];
324 : }
325 :
326 0 : CcuMultiply(src, stride_, root_);
327 0 : dst.addr = output_[localId_];
328 :
329 0 : if (axisId_ == DIM_Y) {
330 0 : dst.addr += axisSliceSize_[DIM_X];
331 : }
332 0 : HCCL_DEBUG("[CcuContextScatterMesh2D] use GroupCopy");
333 0 : GroupCopy(dst, src, curGoSize_);
334 :
335 0 : return;
336 0 : }
337 :
338 : // 准备转发节点,需要的转发数据地址
339 0 : void CcuContextScatterMesh2D::RelaySend(std::vector<CcuRep::Memory> &relaySrc, std::vector<CcuRep::Memory> &relayDst)
340 : {
341 : uint64_t globalId;
342 0 : relaySrc.clear();
343 0 : relayDst.clear();
344 0 : for (uint64_t i = 0; i < dimSize_[axisId_]; i++) {
345 0 : if (i != dimId_[axisId_]) {
346 0 : CcuRep::Memory src = CreateMemory();
347 0 : CcuRep::Memory dst = CreateMemory();
348 0 : src.token = token_[i];
349 0 : dst.token = token_[i];
350 0 : globalId = CoordinateToGlobalId(i, dimId_[1 - axisId_]);
351 0 : HCCL_INFO("[CcuContextScatterMesh2D][PrepareRelaySendInfo] src globalId[%llu], curRank[%u], axisId[%llu], "
352 : "i:[%llu], localId[%llu]",
353 : globalId, rankId_, axisId_, i, localId_);
354 0 : src.addr = scratch_[localId_];
355 0 : CcuMultiply(src, sliceSize_, globalId);
356 0 : dst.addr = output_[i]; // output只有一片,不需要偏移
357 0 : if (axisId_ == DIM_X) {
358 0 : src.addr += axisSliceSize_[DIM_X];
359 0 : dst.addr += axisSliceSize_[DIM_X];
360 : }
361 0 : relaySrc.emplace_back(src);
362 0 : relayDst.emplace_back(dst);
363 0 : }
364 : }
365 0 : CcuWrite1DMesh(relaySrc, relayDst, axisSliceSize_[1 - axisId_]);
366 0 : return;
367 : }
368 :
369 : // *************************************************
370 : // root的行为模式说明: X轴和Y轴行为一致;都是给1DMesh的其他卡发数据, 任一轴的行为:
371 : // 1) 前同步
372 : // 2)给与本轴mesh直连卡发“中转”数据
373 : // 3)后同步
374 : // 4)轴同步
375 : // 5)前同步
376 : // 6)给与本轴mesh直连卡发“直达”数据
377 : // 7)后同步
378 : // 8)轴同步,与4)中成对使用,保证正确性
379 : // *************************************************
380 0 : void CcuContextScatterMesh2D::RootSendAlgorithm()
381 : {
382 0 : HCCL_INFO("[CcuContextScatterMesh2D][RootSendAlgorithm] Start");
383 0 : PrepareVariables();
384 0 : LoadArgs();
385 : // step1
386 0 : PreSync();
387 :
388 : // 准备"直达"&“中转”传输地址
389 0 : std::vector<CcuRep::Memory> directSrc;
390 0 : std::vector<CcuRep::Memory> directDst;
391 0 : std::vector<CcuRep::Memory> relaySrc;
392 0 : std::vector<CcuRep::Memory> relayDst;
393 0 : PrepareAndTransferRootRelayInfo(relaySrc, relayDst);
394 :
395 0 : Sync(CKE_IDX_0); // 后同步
396 0 : AxisSync(0);
397 : // step2
398 0 : Sync(CKE_IDX_1); // 前同步的功能
399 :
400 0 : PrepareAndTransferRootDirectInfo(directSrc, directDst);
401 0 : LocalTransfer();
402 :
403 0 : Sync(CKE_IDX_0); // 后同步
404 0 : AxisSync(1); // 轴同步
405 0 : HCCL_INFO("[CcuContextScatterMesh2D][RootSendAlgorithm] Step2 AxisSync Done");
406 0 : return;
407 0 : }
408 :
409 : // *****************************************
410 : // 与Root同行或同列的rank
411 : // step1: 与Root同行的只有ccuX有,与Root同列的只有ccuY有;(目前先搞所有卡都有)
412 : // 1) 前同步
413 : // 2)后同步
414 : // step2:收直达数据(同行的ccuX有,同列的ccuY有);发step1收到的中转数据(同行的ccuY有,同列的ccuX有)
415 : // 3)轴同步
416 : // 4)前同步
417 : // 5)发中转数据
418 : // 6)后同步
419 : // 7)轴同步
420 : // *****************************************
421 0 : void CcuContextScatterMesh2D::RelaySendAlgorithm()
422 : {
423 0 : HCCL_INFO("[CcuContextScatterMesh2D][RelaySendAlgorithm] Start");
424 0 : PrepareVariables();
425 0 : LoadArgs();
426 :
427 : // step1:
428 0 : PreSync(); // 前同步
429 0 : Sync(CKE_IDX_0); // 后同步
430 0 : AxisSync(0);
431 :
432 : // step2:
433 : // 与Root同行的ccuX,或者 与Root同列的ccuY;才有step2的收直达数据
434 0 : if ((SameRowWithRoot() && axisId_ == DIM_X) or (SameColumnWithRoot() && axisId_ == DIM_Y)) {
435 0 : HCCL_INFO("[CcuContextScatterMesh2D][RelaySendAlgorithm][1 actual Relay] into Relay action, axisId[%llu], "
436 : "isSameRowWithRoot[%d], isSameColwithRoot[%d], myRank[%llu], root[%llu]",
437 : axisId_, SameRowWithRoot(), SameColumnWithRoot(), rankId_, root_);
438 0 : Sync(CKE_IDX_1); // 前同步
439 0 : Sync(CKE_IDX_0); // 后同步
440 : }
441 : // 与Root同行的ccuY,或者 与Root同列的ccuX;才有step2的发中转数据
442 0 : if ((SameRowWithRoot() && axisId_ == DIM_Y) or (SameColumnWithRoot() && axisId_ == DIM_X)) {
443 0 : HCCL_INFO("[CcuContextScatterMesh2D][RelaySendAlgorithm][2 actual Relay] into Relay action, axisId[%llu], "
444 : "isSameRowWithRoot[%d], isSameColwithRoot[%d], myRank[%llu], root[%llu]",
445 : axisId_, SameRowWithRoot(), SameColumnWithRoot(), rankId_, root_);
446 0 : Sync(CKE_IDX_1); // 前同步
447 :
448 : // 准备"直达"&“中转”传输地址
449 0 : std::vector<CcuRep::Memory> relaySrc;
450 0 : std::vector<CcuRep::Memory> relayDst;
451 0 : RelaySend(relaySrc, relayDst);
452 :
453 0 : Sync(CKE_IDX_0); // 后同步
454 0 : }
455 0 : AxisSync(1);
456 0 : HCCL_INFO("[CcuContextScatterMesh2D][RelaySendAlgorithm] step2 Done");
457 0 : return;
458 : }
459 :
460 0 : void CcuContextScatterMesh2D::NonDirectRecvAlgorithm()
461 : {
462 0 : HCCL_INFO("[CcuContextScatterMesh2D][NonDirectRecvAlgorithm] start, dimIdX_[%llu], dimIdY_[%llu]", dimId_[0],
463 : dimId_[1]);
464 0 : PrepareVariables();
465 0 : LoadArgs();
466 0 : PreSync(); // 前同步
467 0 : Sync(CKE_IDX_0); // 后同步
468 0 : AxisSync(0);
469 0 : Sync(CKE_IDX_1); // 前同步
470 0 : Sync(CKE_IDX_0); // 后同步
471 0 : AxisSync(1);
472 0 : HCCL_INFO("[CcuContextScatterMesh2D][NonDirectRecvAlgorithm] Done, dimIdX_[%llu], dimIdY_[%llu]", dimId_[0], dimId_[1]);
473 0 : return;
474 : }
475 :
476 0 : void CcuContextScatterMesh2D::Algorithm()
477 : {
478 0 : HCCL_INFO("[ccuScatterMesh2D_context] ScatterMesh2D run");
479 : // 分3种角色讨论,1)root; 2)与root同行同列的; 3)非直连的
480 0 : if (rankId_ == root_) {
481 : // root节点,X轴与Y轴的行为一致
482 0 : RootSendAlgorithm();
483 0 : return;
484 0 : } else if (SameRowWithRoot() or SameColumnWithRoot()) {
485 0 : RelaySendAlgorithm();
486 0 : return;
487 : } else {
488 : // 非直连
489 0 : NonDirectRecvAlgorithm();
490 0 : return;
491 : }
492 : HCCL_INFO("[ccuScatterMesh2D_context] ScatterMesh2D end");
493 : return;
494 : }
495 :
496 0 : std::vector<uint64_t> CcuContextScatterMesh2D::GeneArgs(const CcuTaskArg &arg)
497 : {
498 0 : const CcuTaskArgScatterMesh2D *taskArg = dynamic_cast<const CcuTaskArgScatterMesh2D *>(&arg);
499 0 : if (taskArg == nullptr) {
500 0 : THROW<NullPtrException>(StringFormat("CcuContextScatterMesh2D::taskArg ptr is null"));
501 : }
502 :
503 0 : uint64_t inputAddr = taskArg->inputAddr_;
504 0 : uint64_t outputAddr = taskArg->outputAddr_;
505 0 : uint64_t tokenInfo = taskArg->token_;
506 0 : uint64_t scratchAddr = taskArg->scratchAddr_;
507 :
508 0 : uint64_t sliceSize = taskArg->sliceSize_;
509 0 : uint64_t stride = taskArg->stride_;
510 0 : uint64_t xSliceSize = taskArg->xSliceSize_;
511 0 : uint64_t ySliceSize = taskArg->ySliceSize_;
512 :
513 0 : auto xSliceGoSize = CalGoSize(xSliceSize);
514 0 : auto ySliceGoSize = CalGoSize(ySliceSize);
515 0 : auto curGosize = (axisId_ == DIM_X) ? xSliceGoSize : ySliceGoSize;
516 :
517 0 : HCCL_INFO("[CcuContextScatterMesh2DAlgo] inputAddr[%llu], outputAddr[%llu], scratchAddr[%llu], sliceSize[%llu], "
518 : "stride[%llu], xSliceSize[%llu], ySliceSize[%llu] ",
519 : inputAddr, outputAddr, scratchAddr, sliceSize, stride, xSliceSize, ySliceSize);
520 : // 8个参数
521 : return {inputAddr, outputAddr, tokenInfo, scratchAddr, sliceSize, stride,
522 0 : xSliceSize, ySliceSize, curGosize[0], curGosize[1], curGosize[2], curGosize[3]};
523 0 : }
524 : }
|