LCOV - code coverage report
Current view: top level - legacy/ascend950/service/collective/alg/coll_alg_factory/alg_ccu_context/all_to_all - ccu_context_all_to_all_mesh2d.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 94.3 % 348 328
Test Date: 2026-07-28 12:11:00 Functions: 100.0 % 14 14

            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_all_to_all_mesh2d.h"
      12              : #include "ccu_instruction_all_to_all_mesh2d.h"
      13              : 
      14              : namespace Hccl {
      15              : 
      16              : constexpr uint16_t CKE_ID_0 = 0;
      17              : constexpr uint16_t CKE_ID_1 = 1;
      18              : constexpr uint16_t CKE_ID_2 = 2;
      19              : constexpr uint16_t CKE_ID_3 = 3;
      20              : constexpr uint16_t FST_AXIS_ID = 0;
      21              : constexpr uint16_t SEC_AXIS_ID = 1;
      22              : 
      23            3 : CcuContextAlltoAllMesh2D::CcuContextAlltoAllMesh2D(const CcuCtxArg &arg, const std::vector<CcuTransport*> &transports,
      24            3 :                                                    const CcuTransportGroup &group)
      25            3 :     : CcuContextAlgBase(arg, transports, group)
      26              : {
      27            3 :     goSize_                   = CreateGroupOpSize();
      28            3 :     input                     = CreateVariable();
      29            3 :     bufferB                   = CreateVariable();
      30            3 :     sliceSize_                = CreateVariable();
      31            3 :     baseOffset                = CreateVariable();
      32            3 :     firstTransportSize        = CreateVariable();
      33            3 :     firstChunkOffset          = CreateVariable();
      34            3 :     firstInputStrideLocal     = CreateVariable();
      35            3 :     firstInputStrideAnother   = CreateVariable();
      36            3 :     firstBufferOffset         = CreateVariable();
      37            3 :     firstBufferStride         = CreateVariable();
      38            3 :     firstOutputOffset         = CreateVariable();
      39            3 :     secondTransportSize       = CreateVariable();
      40            3 :     secondChunkOffset         = CreateVariable();
      41            3 :     secondInputOffset         = CreateVariable();
      42            3 :     secondInputStride         = CreateVariable();
      43            3 :     secondBufferStrideLocal   = CreateVariable();
      44            3 :     secondBufferStrideAnother = CreateVariable();
      45            3 :     secondOutputOffset        = CreateVariable();
      46            3 :     secondOutputStride        = CreateVariable();
      47            3 :     localAxisSignal           = CreateMaskSignal();
      48              : 
      49            3 :     const CcuCtxArgAlltoAllMesh2D *ctxArg = dynamic_cast<const CcuCtxArgAlltoAllMesh2D *>(&arg);
      50            3 :     if (ctxArg == nullptr) {
      51            0 :         THROW<NullPtrException>(StringFormat("CcuContextAlltoAllMesh2D::ctxArg ptr is null"));
      52              :     }
      53            3 :     if (transports.size() == 0) {
      54            0 :         THROW<NullPtrException>(StringFormat("CcuContextAlltoAllMesh2D transports is empty"));
      55              :     }
      56            3 :     rankId_ = ctxArg->rankId;
      57            3 :     dimSize = ctxArg->dimSize;
      58            3 :     axisId = ctxArg->axisId;
      59            3 :     uint32_t max_dimSize = 2;
      60            3 :     if (dimSize.size() != max_dimSize or axisId > 1) {  // dimSize不为2,或axisId超过1,则不为2D场景
      61            0 :         THROW<NullPtrException>(StringFormat("[CcuContextAlltoAllMesh2D] dimSize[%u] or axisId[%u] is invalid",
      62              :             dimSize.size(), axisId));
      63              :     }
      64            3 :     CHK_PRT_THROW(dimSize[0] == 0 || dimSize[1] == 0,
      65              :                     HCCL_ERROR("[CcuContextAlltoAllMesh2D] dimSize0[%llu] or dimSize1[%llu] is zero",
      66              :                     dimSize[0], dimSize[1]),
      67              :                     InvalidParamsException, "dimSize[0] or dimSize[1] is invalid");
      68            3 :     dimId.emplace_back(rankId_ % dimSize[0]);
      69            3 :     dimId.emplace_back(rankId_ / dimSize[0]);
      70            3 :     localId     = dimId[axisId];
      71            3 :     localSize   = dimSize[axisId];
      72            3 :     anotherId   = dimId[1 - axisId];  // 本rank在另一个轴上的Id
      73            3 :     anotherSize = dimSize[1 - axisId];
      74            9 :     HCCL_INFO("[CcuContextAlltoAllMesh2D] RankId[%u], DimSize: D0[%u]--D1[%u], localId[%u], lcoalSize[%u]",
      75              :         rankId_, dimSize[0], dimSize[1], localId, localSize);
      76              : 
      77            3 :     AllocGoResource(LOC_CPY_LOOP_NUM);  // 只用8个loop做本地搬运,每个loop搬4K
      78              : 
      79            3 :     localAxisSignalName = "CcuContextAlltoAllMesh2DAxisSync_" + std::to_string(axisId);
      80            3 :     anotherAxisSignalName = "CcuContextAlltoAllMesh2DAxisSync_" + std::to_string(1 - axisId);
      81            3 : }
      82              : 
      83            2 : void CcuContextAlltoAllMesh2D::InitResources()
      84              : {
      85              :     // 用write语义,input只有本地的1个,scratch和output需要交换
      86            2 :     ExportMaskSignal(localAxisSignal, localAxisSignalName);
      87            2 :     anotherAxisSignal = ImportMaskSignal(anotherAxisSignalName);
      88              : 
      89            2 :     uint32_t transportIdx = 0;
      90            6 :     for (uint32_t peerId = 0; peerId < localSize; peerId++) {
      91            4 :         if (peerId == localId) {
      92            2 :             bufferA.emplace_back(CreateVariable());
      93            2 :             output.emplace_back(CreateVariable());
      94            2 :             token.emplace_back(CreateVariable());
      95              :         } else {
      96            6 :             HCCL_INFO("[CcuContextAlltoAllMesh2D]Rank[%u], PeerId[%u], TransportId[%u]", rankId_, peerId, transportIdx);
      97            2 :             bufferA.emplace_back(CreateVariable(*(transports[transportIdx]), 0));  // 获取transport中id=1的Var来传递bufferA
      98            2 :             output.emplace_back(CreateVariable(*(transports[transportIdx]), 1));  // 1 for output
      99            2 :             token.emplace_back(CreateVariable(*(transports[transportIdx]), 2));  // 2 for token
     100            2 :             transportIdx++;
     101              :         }
     102              :     }
     103              : 
     104            6 :     for (uint16_t i = 0; i < localSize; i++) {
     105            4 :         inputAddrs.emplace_back(CreateMemory());
     106            4 :         bufferAddrs.emplace_back(CreateMemory());
     107            4 :         outputAddrs.emplace_back(CreateMemory());
     108              :     }
     109              : 
     110            6 :     for (uint16_t sliceId = 0; sliceId < anotherSize; sliceId++) {
     111            4 :         firstSignal.emplace_back(CreateMaskSignal());  // 每个对端发anotherSize个分片,localSize个分片共用一个信号,共anotherSize个
     112            4 :         secondSignal.emplace_back(CreateMaskSignal());
     113              :     }
     114              : 
     115            2 :     return;
     116              : }
     117              : 
     118            2 : void CcuContextAlltoAllMesh2D::LoadArgs()
     119              : {
     120            2 :     Load(input);
     121            2 :     Load(output[localId]);
     122            2 :     Load(token[localId]);
     123            2 :     Load(bufferA[localId]);
     124            2 :     Load(bufferB);
     125            2 :     Load(sliceSize_);
     126            2 :     Load(goSize_);
     127              : 
     128            2 :     Load(baseOffset);  // 10号
     129            2 :     Load(firstTransportSize);
     130            2 :     Load(firstChunkOffset);
     131            2 :     Load(firstInputStrideLocal);
     132            2 :     Load(firstInputStrideAnother);
     133            2 :     Load(firstBufferOffset);  // 15号
     134            2 :     Load(firstBufferStride);  // 16号
     135            2 :     Load(firstOutputOffset);
     136              : 
     137            2 :     Load(secondTransportSize);
     138            2 :     Load(secondChunkOffset);
     139            2 :     Load(secondInputOffset);
     140            2 :     Load(secondInputStride);
     141            2 :     Load(secondBufferStrideLocal);
     142            2 :     Load(secondBufferStrideAnother);
     143            2 :     Load(secondOutputOffset);
     144            2 :     Load(secondOutputStride);
     145              : 
     146            2 :     return;
     147              : }
     148              : 
     149            2 : void CcuContextAlltoAllMesh2D::ExchangeInfoAndSync()
     150              : {
     151              :     // 交换信息并做同步,前同步固定用1,2,3号信号
     152            2 :     uint16_t selfBit = 1 << localId;
     153            2 :     uint16_t allBit  = ((1 << localSize) - 1) & (~(1 << localId));
     154              : 
     155            8 :     for (auto t : transports) {
     156            6 :         if (t == nullptr) {
     157            0 :             THROW<NullPtrException>(StringFormat("CcuContextAlltoAllMesh2D::Algorithm transport ptr is null"));
     158              :         }
     159            6 :         WriteVariableWithSignal(*t, bufferA[localId], 0, CKE_ID_1, selfBit); // index = 0,传递第一轮output信息
     160            6 :         WriteVariableWithSignal(*t, output[localId], 1, CKE_ID_2, selfBit); // index = 1,传递第二轮output信息
     161            6 :         WriteVariableWithSignal(*t, token[localId], 2, CKE_ID_3, selfBit);  // index = 2,传递token信息
     162              :     }
     163            2 :     GroupWait(*transportGroup, CKE_ID_1, allBit);
     164            2 :     GroupWait(*transportGroup, CKE_ID_2, allBit);
     165            2 :     GroupWait(*transportGroup, CKE_ID_3, allBit);
     166              : 
     167            2 :     return;
     168              : }
     169              : 
     170            6 : void CcuContextAlltoAllMesh2D::RankSync(uint32_t signalIndex)
     171              : {
     172              :     // 与远端做同步
     173            6 :     uint16_t selfBit = 1 << localId;
     174            6 :     uint16_t allBit  = ((1 << localSize) - 1) & (~(1 << localId));
     175              : 
     176           24 :     for (auto t : transports) {
     177           18 :         if (t == nullptr) {
     178            0 :             THROW<NullPtrException>(StringFormat("CcuContextAlltoAllMesh2D::Algorithm transport ptr is null"));
     179              :         }
     180           18 :         RemotePost(*t, signalIndex, selfBit);
     181              :     }
     182            6 :     GroupWait(*transportGroup, signalIndex, allBit);
     183              : 
     184            6 :     return;
     185              : }
     186              : 
     187            4 : void CcuContextAlltoAllMesh2D::AxisSync(uint32_t signalIndex)
     188              : {
     189            4 :     const uint32_t DIE_NUM = 2;  // 2个die
     190            4 :     if (signalIndex > 1) {
     191            0 :         THROW<InvalidParamsException>(StringFormat(
     192              :             "[CcuContextAlltoAllMesh2D] Unexpected SignalInex[%u]", signalIndex));
     193              :     }
     194            4 :     LocalCtxPost(anotherAxisSignal, 1 << (axisId + signalIndex * DIE_NUM));
     195            4 :     LocalWait(localAxisSignal, 1 << (1 - axisId + signalIndex * DIE_NUM));
     196            4 :     return;
     197              : }
     198              : 
     199            4 : void CcuContextAlltoAllMesh2D::FirstStepOneSlice(uint16_t sliceId)
     200              : {
     201            4 :     if (sliceId == anotherId) {
     202              :         // 当前分片属于对端,直接写到对端output
     203            2 :         uint32_t transIdx = 0;  // 约定transport中的link按照rankId从小到大的顺序排列
     204            6 :         for (uint32_t peerId = 0; peerId < localSize; peerId++) {
     205            4 :             if (peerId == localId) {
     206            2 :                 LocalPost(firstSignal[sliceId], (1 << peerId));
     207              :             } else {
     208            2 :                 Write(*(transports[transIdx]), outputAddrs[peerId], inputAddrs[peerId], firstTransportSize,
     209            2 :                     firstSignal[sliceId], (1 << peerId));
     210            2 :                 transIdx++;
     211              :             }
     212            4 :             inputAddrs[peerId].addr += firstInputStrideAnother;  // 给每个对端的下一片slice的input地址,增加对应偏移
     213            4 :             bufferAddrs[peerId].addr += firstBufferStride;  // 跳过对端buffer中不需要转发的那一片
     214              :         }
     215              :     } else {
     216              :         // 当前分片需要对端转发,写到对端的bufferX/bufferY
     217            2 :         uint32_t transIdx = 0;
     218            6 :         for (uint32_t peerId = 0; peerId < localSize; peerId++) {
     219            4 :             if (peerId == localId) {
     220            2 :                 LocalPost(firstSignal[sliceId], (1 << peerId));  // 对于本die经过转发无法到达的对端,只设置标记不发送数据
     221            2 :                 continue;
     222              :             }
     223            2 :             Write(*(transports[transIdx]), bufferAddrs[peerId], inputAddrs[peerId], firstTransportSize,
     224            2 :                 firstSignal[sliceId], (1 << peerId));
     225            2 :             inputAddrs[peerId].addr += firstInputStrideAnother;
     226            2 :             bufferAddrs[peerId].addr += firstBufferStride;  // 给对端用于转发的分片,每片相对前片加localSize*sliceSize
     227            2 :             transIdx++;
     228              :         }
     229              :     }
     230              : 
     231            4 :     return;
     232              : }
     233              : 
     234            2 : void CcuContextAlltoAllMesh2D::FirstStep()
     235              : {
     236            2 :     CcuRep::Memory lgSrc = CreateMemory();
     237            2 :     CcuRep::Memory lgDst = CreateMemory();
     238              : 
     239              :     // 统一处理token,访问第i个对端需要使用对应的token
     240            6 :     for (uint16_t i = 0; i < localSize; i++) {
     241            4 :         inputAddrs[i].token = token[i];
     242            4 :         bufferAddrs[i].token = token[i];
     243            4 :         outputAddrs[i].token = token[i];
     244              :     }
     245            2 :     lgSrc.token = token[localId];
     246            2 :     lgDst.token = token[localId];
     247              :     // 本rank的input内存块用一组mem地址来分割
     248            2 :     inputAddrs[0].addr = input;
     249            2 :     inputAddrs[0].addr += baseOffset;
     250            2 :     inputAddrs[0].addr += firstChunkOffset;
     251            4 :     for (uint16_t i = 1; i < localSize; i++) {
     252              :         // 准备发送给rank0对应分片的地址即为input首地址,后续rank的偏移依次递增
     253            2 :         inputAddrs[i].addr = inputAddrs[i - 1].addr + firstInputStrideLocal;
     254              :     }
     255            6 :     for (uint16_t i = 0; i < localSize; i++) {
     256              :         // output offset
     257            4 :         outputAddrs[i].addr = output[i];
     258            4 :         outputAddrs[i].addr += baseOffset;
     259            4 :         outputAddrs[i].addr += firstChunkOffset;
     260            4 :         outputAddrs[i].addr += firstOutputOffset;  // 第一轮直接发送给对端的slice的偏移
     261              :         // buffer offset
     262            4 :         bufferAddrs[i].addr = bufferA[i];
     263            4 :         bufferAddrs[i].addr += firstBufferOffset;  // 发送给对端用于转发的分片,第一片的起始偏移,后续每片步进相同长度
     264              :     }
     265              :     // 准备LG搬运的地址
     266            2 :     lgSrc.addr = inputAddrs[localId].addr;
     267            2 :     lgDst.addr = outputAddrs[localId].addr;
     268            2 :     for (uint16_t sliceId = 0; sliceId < anotherSize; sliceId++) {
     269            2 :         if (sliceId == anotherId) {
     270            2 :             break;
     271              :         }
     272            0 :         lgSrc.addr += firstInputStrideAnother;  // 在input中找到自身对应的那个分片,跳出循环
     273              :     }
     274              : 
     275              :     {
     276              :         // 当第一轮的搬运量为零时,跳过搬运
     277            2 :         CcuRep::Condition cond(this, firstTransportSize != 0);
     278              : 
     279            6 :         for (uint16_t sliceId = 0; sliceId < anotherSize; sliceId++) {  // sliceId等于dstRank在另一个维度上的id
     280            4 :             FirstStepOneSlice(sliceId);
     281              :         }
     282            2 :     }
     283              :     // Loopgroup做本地搬运,必然不为零
     284            2 :     if (axisId == 0) {
     285            1 :         LocalCopyByLoopGroup(lgDst, lgSrc, goSize_);
     286              :     }
     287              : 
     288              :     // 检查第一轮的数据是否已发完
     289              :     {
     290              :         // 当第一轮的搬运量非零时,检查相应完成标记
     291            2 :         CcuRep::Condition cond(this, firstTransportSize != 0);
     292            6 :         for (uint16_t sliceId = 0; sliceId < anotherSize; sliceId++) {
     293            4 :             LocalWait(firstSignal[sliceId], (1 << localSize) - 1);  // 等待第一轮所有分片都发完
     294              :         }
     295            2 :     }
     296              : 
     297            4 :     return;
     298            2 : }
     299              : 
     300            2 : void CcuContextAlltoAllMesh2D::SecondStep()
     301              : {
     302              :     {
     303              :         // 当第二轮的搬运量为零时,跳过搬运
     304            2 :         CcuRep::Condition cond(this, secondTransportSize != 0);
     305              : 
     306              :         // 地址计算
     307              :         // input offset,本rank的input内存块用一组GSA来分割
     308            2 :         inputAddrs[0].addr = input;
     309            2 :         inputAddrs[0].addr += baseOffset;
     310            2 :         bufferAddrs[0].addr = bufferB;
     311            2 :         inputAddrs[0].addr += secondChunkOffset;
     312            2 :         inputAddrs[0].addr += secondInputOffset;  // 一共从input发送localSize-1个分片(跳过自己),用localSize个input地址
     313            4 :         for (uint16_t i = 1; i < localSize; i++) {
     314            2 :             inputAddrs[i].addr = inputAddrs[i - 1].addr + secondInputStride;
     315              :             // 每轮给每个对端从buffer发送1个分片,共anotherSize-1轮
     316            2 :             bufferAddrs[i].addr = bufferAddrs[i - 1].addr + secondBufferStrideLocal;
     317              :         }
     318              :         // output offset
     319            6 :         for (uint16_t i = 0; i < localSize; i++) {
     320              :             // 给每个对端的output写anotherSize个分片,这些分片的src的rankId从offset开始,以stride步进
     321            4 :             outputAddrs[i].addr = output[i];
     322            4 :             outputAddrs[i].addr += baseOffset;
     323            4 :             outputAddrs[i].addr += secondChunkOffset;
     324            4 :             outputAddrs[i].addr += secondOutputOffset;
     325              :         }
     326              : 
     327              :         // 从input与buffer中给每个对端发anotherSize个分片
     328            6 :         for (uint16_t sliceId = 0; sliceId < anotherSize; sliceId++) {
     329            4 :             uint32_t transIdx = 0;
     330           12 :             for (uint32_t peerId = 0; peerId < localSize; peerId++) {
     331            8 :                 if (peerId == localId) {
     332            4 :                     LocalPost(secondSignal[sliceId], (1 << peerId));  // 给自己的分片在第一轮已经发过,第二轮只设置标记
     333            4 :                     continue;
     334              :                 }
     335            4 :                 if (sliceId == anotherId) {
     336              :                     // 从input发出
     337            2 :                     Write(*(transports[transIdx]), outputAddrs[peerId], inputAddrs[peerId], secondTransportSize,
     338            2 :                         secondSignal[sliceId], (1 << peerId));
     339              :                 } else {
     340              :                     // 从buffer发出
     341            2 :                     Write(*(transports[transIdx]), outputAddrs[peerId], bufferAddrs[peerId], secondTransportSize,
     342            2 :                         secondSignal[sliceId], (1 << peerId));
     343              :                 }
     344            4 :                 transIdx++;
     345            4 :                 outputAddrs[peerId].addr += secondOutputStride;
     346            4 :                 bufferAddrs[peerId].addr += secondBufferStrideAnother;
     347              :             }
     348              :         }
     349            6 :         for (uint16_t sliceId = 0; sliceId < anotherSize; sliceId++) {
     350            4 :             LocalWait(secondSignal[sliceId], (1 << localSize) - 1);  // 等待第二轮所有分片都发完
     351              :         }
     352            2 :     }
     353              : 
     354            2 :     return;
     355              : }
     356              : 
     357            1 : void CcuContextAlltoAllMesh2D::CreateLocalCopyLoop()
     358              : {
     359            1 :     std::string opStr = "a2a_localcpy_loopgroup";
     360            3 :     for (uint32_t index = 0; index < 2; index++) { // 需要2个Loop
     361            2 :         CcuRep::LoopBlock           lb(this, "a2a_localcpy_loop_" + std::to_string(index));
     362            2 :         CcuRep::Memory              src = CreateMemory();
     363            2 :         CcuRep::Variable            len = CreateVariable();
     364            2 :         CcuRep::Memory              dst = CreateMemory();
     365            2 :         lb(src, dst, len);
     366              : 
     367            2 :         CcuRep::CcuBuffer  buf = moRes.ccuBuffer[index * moConfig.msInterleave];
     368            2 :         CcuRep::MaskSignal sem = moRes.maskSignal[index];
     369              : 
     370            2 :         LocalCopy(buf, src, len, sem);
     371            2 :         LocalWait(sem);
     372            2 :         LocalCopy(dst, buf, len, sem);
     373            2 :         LocalWait(sem);
     374            2 :     }
     375            2 :     return;
     376            1 : }
     377              : 
     378            1 : void CcuContextAlltoAllMesh2D::LocalCopyByLoopGroup(CcuRep::Memory dst, CcuRep::Memory src, GroupOpSize &goPara)
     379              : {
     380            1 :     std::string opStr = "a2a_localcpy_loopgroup";
     381            1 :     CreateLocalCopyLoop();
     382              : 
     383              :     {
     384            1 :         CcuRep::Condition cond(this, goPara.loopParam != 0);
     385              : 
     386            1 :         CcuRep::Variable loopParam = CreateVariable();
     387            1 :         loopParam = CcuRep::GetLoopParam(0, moConfig.memSlice * moConfig.loopCount, 0);
     388            1 :         loopParam += goPara.loopParam;
     389              : 
     390            1 :         CcuRep::Variable sliceSize = CreateVariable();
     391            1 :         sliceSize = moConfig.memSlice;
     392            2 :         auto lc   = Loop("a2a_localcpy_loop_0")(src, dst, sliceSize);
     393              : 
     394            1 :         CcuRep::Variable paraCfg = CreateVariable();
     395            1 :         paraCfg = CcuRep::GetParallelParam(moConfig.loopCount - 1, 0, 1);
     396            1 :         CcuRep::Variable offsetCfg = CreateVariable();
     397            1 :         offsetCfg = CcuRep::GetOffsetParam(moConfig.memSlice, moConfig.msInterleave, 1);
     398            6 :         LoopGroup({lc}, {loopParam}, paraCfg, offsetCfg);
     399            1 :     }
     400              : 
     401              :     {
     402            1 :         CcuRep::Condition cond(this, goPara.parallelParam != 0);
     403              :         
     404            1 :         dst.addr += goPara.addrOffset;
     405            1 :         src.addr += goPara.addrOffset;
     406            2 :         auto lc0 = Loop("a2a_localcpy_loop_0")(src, dst, goPara.residual);
     407              : 
     408            1 :         src.addr += goPara.residual;
     409            1 :         dst.addr += goPara.residual;
     410            1 :         CcuRep::Variable sliceSize = CreateVariable();
     411            1 :         sliceSize = moConfig.memSlice;
     412            2 :         auto lc1  = Loop("a2a_localcpy_loop_1")(src, dst, sliceSize);
     413              : 
     414            1 :         CcuRep::Variable loopCfg0 = CreateVariable();
     415            1 :         loopCfg0 = CcuRep::GetLoopParam(0, 0, 1);
     416            1 :         CcuRep::Variable loopCfg1 = CreateVariable();
     417            1 :         loopCfg1 = CcuRep::GetLoopParam(0, 0, 1);
     418            1 :         CcuRep::Variable offsetCfg = CreateVariable();
     419            1 :         offsetCfg = CcuRep::GetOffsetParam(moConfig.memSlice, moConfig.msInterleave, 1);
     420            8 :         LoopGroup({lc0, lc1}, {loopCfg0, loopCfg1}, goPara.parallelParam, offsetCfg);
     421            1 :     }
     422            5 : }
     423              : 
     424            2 : void CcuContextAlltoAllMesh2D::Algorithm()
     425              : {
     426              :     // 初始化寄存器资源 & 加载外部输入参数
     427            6 :     HCCL_INFO("[CcuContextAlltoAllMesh2D] AllgatherMesh1D Algorithm Init Begins.");
     428            2 :     InitResources();
     429            2 :     LoadArgs();
     430              : 
     431              :     // 第一轮,X方向发a,Y方向发后b,到对端的块均放在output,要沿X转发的b块放在对端的bufferX,根据转发目的、自身locId两级偏移
     432            6 :     HCCL_INFO("[CcuContextAlltoAllMesh2D] Algorithm first step begins.");
     433            2 :     ExchangeInfoAndSync();
     434            2 :     FirstStep();
     435            2 :     RankSync(CKE_ID_0);
     436            2 :     AxisSync(FST_AXIS_ID);
     437              : 
     438              :     // 第二轮,从input和buffer中将剩余的本端分片以及待转发分片发给对端;其中给每个对端发1个本端分片,localSize-1个转发分片
     439            6 :     HCCL_INFO("[CcuContextAlltoAllMesh2D] Algorithm second step begins.");
     440            2 :     RankSync(CKE_ID_1);
     441            2 :     SecondStep();
     442            2 :     RankSync(CKE_ID_0);
     443            2 :     AxisSync(SEC_AXIS_ID);
     444              : 
     445            6 :     HCCL_INFO("[CcuContextAlltoAllMesh2D] Algorithm Ends.");
     446            2 :     return;
     447              : }
     448              : 
     449            2 : void CcuContextAlltoAllMesh2D::CalculateArgs(const CcuTaskArgAlltoAllMesh2D *taskArg)
     450              : {
     451            2 :     if (taskArg == nullptr) {
     452            0 :         THROW<NullPtrException>(StringFormat("CcuContextAlltoAllMesh2D::taskArg ptr is null"));
     453              :     }
     454              : 
     455            2 :     uint64_t sendStride = taskArg->sendStride;
     456            2 :     uint64_t recvStride = taskArg->recvStride;
     457            2 :     uint64_t aSize = taskArg->aSize;
     458            2 :     uint64_t bSize = taskArg->bSize;
     459            2 :     uint64_t sendLength = taskArg->sendLength;
     460              : 
     461            2 :     uint64_t sliceSize = aSize + bSize;
     462            2 :     uint64_t srcStride = sendLength + sendStride;
     463            2 :     uint64_t dstStride = sendLength + recvStride;
     464              : 
     465              :     // 根据axisId决定bufferA与bufferB的地址,暂定a与b的大小相等
     466            2 :     if (axisId == 0) {
     467            2 :         firstTransportSizeValue      = aSize;
     468            2 :         firstChunkOffsetValue        = 0;
     469            2 :         firstInputStrideLocalValue   = srcStride;
     470            2 :         firstInputStrideAnotherValue = dimSize[0] * srcStride;
     471              : 
     472            2 :         secondTransportSizeValue = bSize;
     473            2 :         secondChunkOffsetValue   = aSize;
     474            2 :         secondInputOffsetValue   = dimId[1] * dimSize[0] * srcStride;
     475            2 :         secondInputStrideValue   = srcStride;
     476            2 :         secondOutputOffsetValue  = dimId[0] * dstStride;
     477            2 :         secondOutputStrideValue  = dimSize[0] * dstStride;
     478              :     } else {
     479            0 :         firstTransportSizeValue      = bSize;
     480            0 :         firstChunkOffsetValue        = aSize;
     481            0 :         firstInputStrideLocalValue   = dimSize[0] * srcStride;
     482            0 :         firstInputStrideAnotherValue = srcStride;
     483              : 
     484            0 :         secondTransportSizeValue = aSize;
     485            0 :         secondChunkOffsetValue   = 0;
     486            0 :         secondInputOffsetValue   = dimId[0] * srcStride;
     487            0 :         secondInputStrideValue   = dimSize[0] * srcStride;
     488            0 :         secondOutputOffsetValue  = dimId[1] * dimSize[0] * dstStride;
     489            0 :         secondOutputStrideValue  = dstStride;
     490              :     }
     491              : 
     492            2 :     firstBufferOffsetValue = dimId[axisId] * sliceSize;
     493            2 :     firstBufferStrideValue = dimSize[axisId] * sliceSize;
     494            2 :     firstOutputOffsetValue = rankId_ * dstStride;
     495              : 
     496            2 :     secondBufferStrideLocalValue = dimSize[1 - axisId] * sliceSize;
     497            2 :     secondBufferStrideAnotherValue = sliceSize;
     498              : 
     499            2 :     return;
     500              : }
     501              : 
     502            8 : std::vector<uint64_t> CcuContextAlltoAllMesh2D::GeneArgs(const CcuTaskArg &arg)
     503              : {
     504            8 :     const CcuTaskArgAlltoAllMesh2D *taskArg = dynamic_cast<const CcuTaskArgAlltoAllMesh2D *>(&arg);
     505            8 :     if (taskArg == nullptr) {
     506           12 :         THROW<NullPtrException>(StringFormat("CcuContextAlltoAllMesh2D::taskArg ptr is null"));
     507              :     }
     508              : 
     509              :     // input&output&buffer地址
     510            2 :     uint64_t inputAddr      = taskArg->inputAddr;
     511            2 :     uint64_t outputAddr     = taskArg->outputAddr;
     512            2 :     uint64_t scratchAddr    = taskArg->scratchAddr;
     513            2 :     uint64_t tokenInfo      = taskArg->token;
     514            2 :     uint64_t sliceSizeValue = taskArg->aSize + taskArg->bSize;
     515              : 
     516              :     // scratch的前rankSize*sliceSize大小为bufferY,后一块为bufferX
     517              :     // die0第一轮写到对端的bufferY,第二轮从本端bufferX发送;die1第一轮写到对端的bufferX,第二轮从本端bufferY发送
     518            2 :     uint64_t bufferAAddr = 0;
     519            2 :     uint64_t bufferBAddr = 0;
     520            2 :     if (axisId == 0) {
     521            2 :         bufferAAddr = scratchAddr;  // 需要交换给对端,是bufferY
     522            2 :         bufferBAddr = scratchAddr + dimSize[0] * dimSize[1] * sliceSizeValue;  // bufferX rankSize * sliceSize
     523              :     } else {
     524            0 :         bufferAAddr = scratchAddr + dimSize[0] * dimSize[1] * sliceSizeValue;  // bufferX
     525            0 :         bufferBAddr = scratchAddr;  // 不需要交换给对端,是bufferY
     526              :     }
     527              : 
     528              :     // loopgroup按照sliceSize大小做本地搬运,只die0执行
     529            2 :     auto goSize = CalGoSize(taskArg->aSize + taskArg->bSize);
     530            2 :     CalculateArgs(taskArg);
     531              : 
     532            6 :     HCCL_INFO("[CcuContextAlltoAllMesh2D][GeneArgs] RankId[%u]--AxisId[%u], inputAddr[%llu], outputAddr[%llu], \
     533              : bufferA[%llu], bufferB[%llu], goSize--[%llu][%llu][%llu][%llu], sendStride[%llu], recvStride[%llu], \
     534              : sendRecvSize[%llu], sendLength[%llu], aSize[%llu], bSize[%llu], baseOffset[%llu]",
     535              :         rankId_, axisId, inputAddr, outputAddr, bufferAAddr, bufferBAddr, goSize[0], goSize[1], goSize[2], goSize[3],
     536              :         taskArg->sendStride, taskArg->recvStride, sliceSizeValue, taskArg->sendLength, taskArg->aSize, taskArg->bSize,
     537              :         taskArg->baseOffset);
     538              : 
     539            6 :     HCCL_INFO("[CcuContextAlltoAllMesh2D][CalculateArgs] firstTransportSize[%llu], firstChunkOffset[%llu], \
     540              : firstInputStrideLocal[%llu], firstInputStrideAnother[%llu], firstBufferOffset[%llu], firstBufferStride[%llu], \
     541              : firstOutputOffset[%llu], secondTransportSize[%llu], secondChunkOffset[%llu], secondInputOffset[%llu], \
     542              : secondInputStride[%llu], secondBufferStrideLocal[%llu], secondBufferStrideAnother[%llu], \
     543              : secondOutputOffset[%llu], secondOutputStride[%llu]", firstTransportSizeValue, firstChunkOffsetValue,
     544              :         firstInputStrideLocalValue, firstInputStrideAnotherValue, firstBufferOffsetValue, firstBufferStrideValue,
     545              :         firstOutputOffsetValue, secondTransportSizeValue, secondChunkOffsetValue, secondInputOffsetValue,
     546              :         secondInputStrideValue, secondBufferStrideLocalValue, secondBufferStrideAnotherValue, secondOutputOffsetValue,
     547              :         secondOutputStrideValue);
     548              : 
     549            8 :     return {inputAddr, outputAddr, tokenInfo, bufferAAddr, bufferBAddr, sliceSizeValue, goSize[0], goSize[1], goSize[2], goSize[3],
     550            2 :         taskArg->baseOffset, firstTransportSizeValue, firstChunkOffsetValue, firstInputStrideLocalValue,
     551            2 :         firstInputStrideAnotherValue, firstBufferOffsetValue, firstBufferStrideValue, firstOutputOffsetValue,
     552            2 :         secondTransportSizeValue, secondChunkOffsetValue, secondInputOffsetValue, secondInputStrideValue,
     553            6 :         secondBufferStrideLocalValue, secondBufferStrideAnotherValue, secondOutputOffsetValue, secondOutputStrideValue};
     554            2 : }
     555              : }
        

Generated by: LCOV version 2.0-1