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