LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_alltoallv - alltoallv_staged_pairwise.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 208 0
Test Date: 2026-07-28 12:11:00 Functions: 0.0 % 15 0

            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 "alltoallv_staged_pairwise.h"
      12              : #include "log.h"
      13              : #include "alg_template_register.h"
      14              : 
      15              : namespace hccl {
      16              : using namespace std;
      17              : 
      18            0 : AlltoAllVStagedPairwise::AlltoAllVStagedPairwise(const HcclDispatcher dispatcher)
      19            0 :     : AlltoAllVStagedBase(dispatcher)
      20              : {
      21            0 : }
      22              : 
      23            0 : AlltoAllVStagedPairwise::~AlltoAllVStagedPairwise() {}
      24              : 
      25              : // 图模式Prepare入口
      26            0 : HcclResult AlltoAllVStagedPairwise::Prepare(DeviceMem &sendMem, DeviceMem &recvMem,
      27              :     StageAlltoAllVAddrInfo &sendAddrInfo, StageAlltoAllVAddrInfo &recvAddrInfo,
      28              :     bool isAlltoAllZCopyMode, Stream &mainStream)
      29              : {
      30            0 :     DeviceMem scratchInputMem = DeviceMem();
      31            0 :     DeviceMem scratchOutputMem = DeviceMem();
      32            0 :     return AlltoAllVStagedPairwise::Prepare(sendMem, recvMem, scratchInputMem, scratchOutputMem,
      33            0 :         sendAddrInfo, recvAddrInfo, isAlltoAllZCopyMode, mainStream);
      34            0 : }
      35              : 
      36              : // 单算子Prepare入口
      37            0 : HcclResult AlltoAllVStagedPairwise::Prepare(DeviceMem &sendMem, DeviceMem &recvMem, DeviceMem &scratchInputMem,
      38              :     DeviceMem &scratchOutputMem, StageAlltoAllVAddrInfo &sendAddrInfo, StageAlltoAllVAddrInfo &recvAddrInfo,
      39              :     bool isAlltoAllZCopyMode, Stream &mainStream)
      40              : {
      41            0 :     CHK_RET(AlltoAllVStagedBase::Prepare(sendMem, recvMem, sendAddrInfo, recvAddrInfo,
      42              :         isAlltoAllZCopyMode, mainStream));
      43            0 :     if (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE &&
      44            0 :         !isAlltoAllZCopyMode_) {
      45            0 :         CHK_PRT_RET((scratchInputMem.size() != scratchOutputMem.size()),
      46              :             HCCL_ERROR(
      47              :                 "[AlltoAllVStagedPairwise][Prepare]scratchInputMem and scratchOutputMem should be the same size, "
      48              :                 "ScratchInputMem[%llu] ScratchOutputMem[%llu]", scratchInputMem.size(), scratchOutputMem.size()),
      49              :                 HCCL_E_MEMORY);
      50              : 
      51            0 :         CHK_PRT_RET(scratchInputMem.size() == 0,
      52              :             HCCL_ERROR("[AlltoAllVStagedPairwise][Prepare] invilad scratchMemSize[%llu]", scratchInputMem.size()),
      53              :             HCCL_E_PARA);
      54            0 :         scratchInputMem_ = scratchInputMem;
      55            0 :         scratchOutputMem_ = scratchOutputMem;
      56            0 :         scratchMemSize_ = scratchInputMem.size();
      57              :     }
      58              : 
      59            0 :     HCCL_DEBUG("[AlltoAllVStagedPairwise][Prepare] finished");
      60            0 :     return HCCL_SUCCESS;
      61              : }
      62              : 
      63            0 : HcclResult AlltoAllVStagedPairwise::RunAsync(const u32 rank, const u32 rankSize, const std::vector<LINK> &links)
      64              : {
      65            0 :     HCCL_INFO("[AlltoAllVStagedPairwise][RunAsync]: rank[%u] transportSize[%llu]", rank, links.size());
      66            0 :     CHK_SMART_PTR_NULL(dispatcher_);
      67            0 :     CHK_PTR_NULL(mainStreamPtr_);
      68              : 
      69            0 :     CHK_PRT_RET(rankSize == 0, HCCL_ERROR("[AlltoAllVStagedPairwise][Prepare] invilad rankSize[%u]", rankSize),
      70              :         HCCL_E_PARA);
      71              : 
      72            0 :     CHK_PRT_RET(rankSize != links.size(),
      73              :         HCCL_ERROR("[AlltoAllVStagedPairwise][RunAsync]: rankSize[%u] and transport size[%llu] do not match", rankSize,
      74              :         links.size()),
      75              :         HCCL_E_PARA);
      76              : 
      77            0 :     bool sizeEqual = (sendAddrInfo_.size() == recvAddrInfo_.size() && sendAddrInfo_.size() == rankSize);
      78            0 :     CHK_PRT_RET(!sizeEqual,
      79              :         HCCL_ERROR("[AlltoAllVStagedPairwise][RunAsync] invilad params: "\
      80              :         "sendAddrInfo size[%u] recvAddrInfo size[%u] rankSize[%u]",
      81              :         sendAddrInfo_.size(), recvAddrInfo_.size(), rankSize),
      82              :         HCCL_E_PARA);
      83              : 
      84            0 :     CHK_RET(LocalCopy(rank));
      85              : 
      86            0 :     if (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE &&
      87            0 :         !isAlltoAllZCopyMode_) { // 单算子 && BCopy模式
      88            0 :         CHK_RET(RunBCopyAlltoAll(rank, rankSize, links));
      89              :     } else {
      90            0 :         CHK_RET(RunZCopyAlltoAll(rank, rankSize, links));
      91              :     }
      92              : 
      93            0 :     return HCCL_SUCCESS;
      94              : }
      95              : 
      96            0 : HcclResult AlltoAllVStagedPairwise::RunZCopyAlltoAll(const u32 rank, const u32 rankSize, const std::vector<LINK> &links)
      97              : {
      98            0 :     for (u32 i = 1; i < rankSize; i++) {
      99            0 :         u32 prevRank = (rank + rankSize - i) % rankSize;
     100            0 :         u32 nextRank = (rank + i) % rankSize;
     101            0 :         std::shared_ptr<Transport> prevTransport = links[prevRank];
     102            0 :         std::shared_ptr<Transport> nextTransport = links[nextRank];
     103              : 
     104            0 :         CHK_SMART_PTR_NULL(prevTransport);
     105            0 :         CHK_SMART_PTR_NULL(nextTransport);
     106              : 
     107            0 :         HCCL_DEBUG("[AlltoAllVStagedPairwise][RunZCopyAlltoAll]: prevRank[%u] nextRank[%u], step[%u]", prevRank,
     108              :             nextRank, i);
     109              : 
     110            0 :         CHK_RET(prevTransport->TxAck(*mainStreamPtr_)); // transport sync record
     111            0 :         CHK_RET(nextTransport->RxAck(*mainStreamPtr_)); // transport sync wait
     112              : 
     113            0 :         u32 sendDataNum = sendAddrInfo_[nextRank].size();
     114            0 :         vector<TxMemoryInfo> txMems(sendDataNum);
     115            0 :         u32 index = 0;
     116            0 :         for (auto &addrInfo : sendAddrInfo_[nextRank]) {
     117            0 :             txMems[index].dstMemType = UserMemType::OUTPUT_MEM;
     118            0 :             txMems[index].dstOffset = addrInfo.remoteOffset;
     119            0 :             txMems[index].src = static_cast<u8 *>(sendMem_.ptr()) + addrInfo.localOffset;
     120            0 :             txMems[index].len = addrInfo.localLength;
     121            0 :             index++;
     122              :         }
     123              : 
     124            0 :         u32 recvDataNum = recvAddrInfo_[prevRank].size();
     125            0 :         vector<RxMemoryInfo> rxMems(recvDataNum);
     126            0 :         index = 0;
     127            0 :         for (auto &addrInfo : recvAddrInfo_[prevRank]) {
     128            0 :             rxMems[index].srcMemType = UserMemType::INPUT_MEM;
     129            0 :             rxMems[index].srcOffset = addrInfo.remoteOffset;
     130            0 :             rxMems[index].dst = static_cast<u8 *>(recvMem_.ptr()) + addrInfo.localOffset;
     131            0 :             rxMems[index].len = addrInfo.localLength;
     132            0 :             index++;
     133              :         }
     134            0 :         CHK_RET(nextTransport->TxAsync(txMems, *mainStreamPtr_)); // send payload + data notify
     135            0 :         CHK_RET(prevTransport->RxAsync(rxMems, *mainStreamPtr_)); // wait data notify
     136            0 :         CHK_RET(ExecuteBarrier(prevTransport, nextTransport));
     137            0 :     }
     138              : 
     139            0 :     return HCCL_SUCCESS;
     140              : }
     141              : 
     142            0 : HcclResult AlltoAllVStagedPairwise::RunBCopyAlltoAll(const u32 rank, const u32 rankSize,
     143              :     const std::vector<LINK> &links)
     144              : {
     145            0 :     for (u32 i = 1; i < rankSize; ++i) {
     146            0 :         u32 prevRank = (rank + rankSize - i) % rankSize;
     147            0 :         u32 nextRank = (rank + i) % rankSize;
     148            0 :         std::shared_ptr<Transport> prevTransport = links[prevRank];
     149            0 :         std::shared_ptr<Transport> nextTransport = links[nextRank];
     150              : 
     151            0 :         CHK_SMART_PTR_NULL(prevTransport);
     152            0 :         CHK_SMART_PTR_NULL(nextTransport);
     153              : 
     154            0 :         HCCL_DEBUG("[AlltoAllVStagedPairwise][RunBCopyAlltoAll]: prevRank[%u] nextRank[%u], step[%u]", prevRank,
     155              :             nextRank, i);
     156              : 
     157              :         // 计算本轮收发次数
     158            0 :         u64 sendTimes = 0;
     159            0 :         u64 recvTimes = 0;
     160              : 
     161            0 :         CalcSendRecvTimes(sendTimes, recvTimes, prevRank, nextRank);
     162            0 :         HCCL_DEBUG("sendTimes[%llu] recvTimes[%llu]", sendTimes, recvTimes);
     163              : 
     164            0 :         std::vector<std::list<OneSendRecvAddrInfo>> sendPolicies(sendTimes);
     165            0 :         std::vector<std::list<OneSendRecvAddrInfo>> recvPolicies(recvTimes);
     166            0 :         LoadPolicies(nextRank, sendAddrInfo_, sendPolicies);
     167            0 :         CHK_RET(CheckPolicies(sendTimes, sendPolicies));
     168              : 
     169            0 :         LoadPolicies(prevRank, recvAddrInfo_, recvPolicies);
     170            0 :         CHK_RET(CheckPolicies(recvTimes, recvPolicies));
     171              : 
     172            0 :         u64 curSendTime = 0;
     173            0 :         u64 curRecvTime = 0;
     174              : 
     175            0 :         while (curSendTime < sendTimes || curRecvTime < recvTimes) {
     176            0 :             CHK_RET(SendRecv(curSendTime, sendPolicies, curRecvTime, recvPolicies, prevTransport, nextTransport));
     177            0 :             curSendTime = curSendTime < sendTimes ? curSendTime + 1 : curSendTime;
     178            0 :             curRecvTime = curRecvTime < recvTimes ? curRecvTime + 1 : curRecvTime;
     179              :         }
     180            0 :     }
     181            0 :     return HCCL_SUCCESS;
     182              : }
     183              : 
     184            0 : void AlltoAllVStagedPairwise::CalcSendRecvTimes(u64 &sendTimes, u64 &recvTimes, const u32 prevRank, const u32 nextRank)
     185              : {
     186            0 :     u64 sendBytes = 0;
     187            0 :     u64 recvBytes = 0;
     188            0 :     for (auto &addrInfo : sendAddrInfo_[nextRank]) {
     189            0 :         sendBytes += addrInfo.localLength;
     190              :     }
     191            0 :     for (auto &addrInfo : recvAddrInfo_[prevRank]) {
     192            0 :         recvBytes += addrInfo.localLength;
     193              :     }
     194            0 :     sendTimes = (sendBytes / scratchMemSize_) + ((sendBytes % scratchMemSize_) == 0 ? 0 : 1);
     195            0 :     recvTimes = (recvBytes / scratchMemSize_) + ((recvBytes % scratchMemSize_) == 0 ? 0 : 1);
     196            0 : }
     197              : 
     198            0 : void AlltoAllVStagedPairwise::LoadPolicies(const u32 rank, StageAlltoAllVAddrInfo &addrInfos,
     199              :     std::vector<std::list<OneSendRecvAddrInfo>> &policies)
     200              : {
     201            0 :     std::list<OneSendRecvAddrInfo> tempPolicies;
     202            0 :     u64 curSendTime = 0;
     203            0 :     u64 curCCLBufSize = scratchMemSize_;
     204              :     // 当CCLbuf剩余空间不够发送、接收一整个task时,对task做拆分
     205              :     OneSendRecvAddrInfo curLastInfo;
     206            0 :     for (auto &addrInfo : addrInfos[rank]) {
     207              :         // 若当前task收发数据量为0,直接看下一个
     208            0 :         if (addrInfo.localLength == 0) {
     209            0 :             continue;
     210              :         }
     211            0 :         u64 curBytes = addrInfo.localLength;
     212            0 :         if (curBytes <= curCCLBufSize) {
     213            0 :             tempPolicies.push_back(addrInfo);
     214            0 :             curCCLBufSize -= curBytes;
     215            0 :             if (curCCLBufSize == 0) {
     216            0 :                 curCCLBufSize = scratchMemSize_;
     217            0 :                 policies[curSendTime] = tempPolicies;
     218            0 :                 ++curSendTime;
     219            0 :                 tempPolicies.clear();
     220              :             }
     221              :         } else {
     222            0 :             OneSendRecvAddrInfo tmpInfo = addrInfo;
     223            0 :             u64 tmpBytes = curBytes;
     224            0 :             while (tmpBytes > curCCLBufSize) {
     225            0 :                 SplitSendRecvAddrInfo(curLastInfo, tmpInfo, curCCLBufSize);
     226            0 :                 tempPolicies.push_back(curLastInfo);
     227            0 :                 curCCLBufSize = scratchMemSize_;
     228            0 :                 policies[curSendTime] = tempPolicies;
     229            0 :                 ++curSendTime;
     230            0 :                 tempPolicies.clear();
     231            0 :                 tmpBytes = tmpInfo.localLength;
     232              :             }
     233            0 :             if (tmpBytes != 0) {
     234            0 :                 tempPolicies.push_back(tmpInfo);
     235            0 :                 curCCLBufSize -= tmpBytes;
     236              :             }
     237              :         }
     238              :     }
     239            0 :     if (curCCLBufSize != scratchMemSize_) {
     240            0 :         policies[curSendTime] = tempPolicies;
     241            0 :         ++curSendTime;
     242              :     }
     243            0 : }
     244              : 
     245            0 : HcclResult AlltoAllVStagedPairwise::CheckPolicies(const u64 times,
     246              :     const std::vector<std::list<OneSendRecvAddrInfo>> &policies) const
     247              : {
     248            0 :     CHK_PRT_RET(times != policies.size(),
     249              :         HCCL_ERROR(
     250              :             "[AlltoAllVStagedPairwise][CheckPolicies] invilad params: times[%llu] policies size[%u]", times,
     251              :             policies.size()), HCCL_E_PARA);
     252              : 
     253            0 :     for (u32 i = 0; i < times; ++i) {
     254            0 :         u64 sum = 0;
     255            0 :         for (auto &addrInfo : policies[i]) {
     256            0 :             sum += addrInfo.localLength;
     257              :         }
     258            0 :         CHK_PRT_RET(sum > scratchMemSize_,
     259              :             HCCL_ERROR(
     260              :                 "[AlltoAllVStagedPairwise][CheckPolicies] invilad params: curTime[%u] sum[%llu] scratchMemSize_[%u]", i,
     261              :                 sum, scratchMemSize_), HCCL_E_PARA);
     262              :     }
     263            0 :     return HCCL_SUCCESS;
     264              : }
     265              : 
     266            0 : HcclResult AlltoAllVStagedPairwise::SendRecv(const u64 curSendTime,
     267              :     const std::vector<std::list<OneSendRecvAddrInfo>> &sendPolicies, const u64 curRecvTime,
     268              :     const std::vector<std::list<OneSendRecvAddrInfo>> &recvPolicies, std::shared_ptr<Transport> prevTransport,
     269              :     std::shared_ptr<Transport> nextTransport)
     270              : {
     271            0 :     bool hasSend = curSendTime < sendPolicies.size();
     272            0 :     bool hasRecv = curRecvTime < recvPolicies.size();
     273            0 :     if (hasRecv) {
     274            0 :         CHK_RET(prevTransport->TxAck(*mainStreamPtr_)); // transport sync record
     275              :     }
     276            0 :     if (hasSend) {
     277            0 :         CHK_RET(nextTransport->RxAck(*mainStreamPtr_)); // transport sync wait
     278              :     }
     279            0 :     if (hasSend) {
     280              :         // 1、把对应内存块从sendbuf copy到CCLInputBuf
     281            0 :         u64 curCCLInputBufOffset = 0;
     282            0 :         for (auto &addrInfo : sendPolicies[curSendTime]) {
     283            0 :             DeviceMem dstMem = scratchInputMem_.range(curCCLInputBufOffset, addrInfo.localLength);
     284            0 :             DeviceMem srcMem = sendMem_.range(addrInfo.localOffset, addrInfo.localLength);
     285            0 :             CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dstMem, srcMem, *mainStreamPtr_));
     286            0 :             curCCLInputBufOffset += addrInfo.localLength;
     287            0 :         }
     288              :         // 2、send CCLInputBuf to CCLOutPutBuf + record
     289            0 :         CHK_RET(nextTransport->TxAsync(UserMemType::OUTPUT_MEM, 0, scratchInputMem_.ptr(),
     290              :             curCCLInputBufOffset, *mainStreamPtr_));
     291              :     }
     292              : 
     293            0 :     if (hasRecv) {
     294              :         // 3、recv CCLOutPutBuf from CCLInputBuf
     295            0 :         u64 recvBytes = 0;
     296            0 :         for (auto &addrInfo : recvPolicies[curRecvTime]) {
     297            0 :             recvBytes += addrInfo.localLength;
     298              :         }
     299              :         // wait
     300            0 :         CHK_RET(prevTransport->RxAsync(UserMemType::INPUT_MEM, 0, scratchOutputMem_.ptr(), recvBytes, *mainStreamPtr_));
     301              :         // 4、把对应内存块从CCLOutputBuf copy到recvBuf
     302            0 :         u64 curCCLOutputBufOffset = 0;
     303            0 :         for (auto &addrInfo : recvPolicies[curRecvTime]) {
     304            0 :             DeviceMem srcMem = scratchOutputMem_.range(curCCLOutputBufOffset, addrInfo.localLength);
     305            0 :             DeviceMem dstMem = recvMem_.range(addrInfo.localOffset, addrInfo.localLength);
     306            0 :             CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dstMem, srcMem, *mainStreamPtr_));
     307            0 :             curCCLOutputBufOffset += addrInfo.localLength;
     308            0 :         }
     309              :     }
     310              : 
     311            0 :     CHK_RET(ExecuteBarrier(hasSend, hasRecv, prevTransport, nextTransport));
     312              : 
     313            0 :     return HCCL_SUCCESS;
     314              : }
     315              : 
     316            0 : void AlltoAllVStagedPairwise::SplitSendRecvAddrInfo(OneSendRecvAddrInfo &curLastInfo, OneSendRecvAddrInfo &addrInfo,
     317              :     const u64 &curCCLBufSize) const
     318              : {
     319              :     // 单算子收发暂不使用remote offset、len,考虑演进性,remote的数据也进行更新
     320            0 :     curLastInfo = addrInfo;
     321            0 :     curLastInfo.localLength = curCCLBufSize;
     322            0 :     curLastInfo.remoteLength = curCCLBufSize;
     323              : 
     324              :     // 切分后剩余部分,可能大于CCLbuf size,需要循环处理
     325            0 :     addrInfo.localOffset += curCCLBufSize;
     326            0 :     addrInfo.localLength -= curCCLBufSize;
     327            0 :     addrInfo.remoteOffset += curCCLBufSize;
     328            0 :     addrInfo.remoteLength -= curCCLBufSize;
     329            0 : }
     330              : 
     331            0 : HcclResult AlltoAllVStagedPairwise::ExecuteBarrier(std::shared_ptr<Transport> preLink,
     332              :     std::shared_ptr<Transport> aftLink)
     333              : {
     334              :     // 同步与preLink保证数据收发已结束
     335            0 :     CHK_RET(preLink->TxAck(*mainStreamPtr_)); // record
     336              : 
     337            0 :     CHK_RET(aftLink->RxAck(*mainStreamPtr_)); // wait
     338              : 
     339              :     // 同步与aftLink保证数据收发已结束
     340            0 :     CHK_RET(aftLink->TxDataSignal(*mainStreamPtr_)); // record
     341              : 
     342            0 :     CHK_RET(preLink->RxDataSignal(*mainStreamPtr_)); // wait
     343              : 
     344            0 :     CHK_RET(preLink->RxWaitDone(*mainStreamPtr_));
     345            0 :     CHK_RET(aftLink->TxWaitDone(*mainStreamPtr_));
     346              : 
     347            0 :     return HCCL_SUCCESS;
     348              : }
     349              : 
     350            0 : HcclResult AlltoAllVStagedPairwise::ExecuteBarrier(bool hasSend, bool hasRecv,
     351              :     std::shared_ptr<Transport> preLink, std::shared_ptr<Transport> aftLink)
     352              : {
     353              :     // 同步与preLink保证数据收发已结束
     354            0 :     if (hasRecv) {
     355            0 :         CHK_RET(preLink->TxAck(*mainStreamPtr_)); // record
     356              :     }
     357            0 :     if (hasSend) {
     358            0 :         CHK_RET(aftLink->RxAck(*mainStreamPtr_)); // wait
     359              :     }
     360              : 
     361              :     // 同步与aftLink保证数据收发已结束
     362            0 :     if (hasSend) {
     363            0 :         CHK_RET(aftLink->TxDataSignal(*mainStreamPtr_)); // record
     364              :     }
     365            0 :     if (hasRecv) {
     366            0 :         CHK_RET(preLink->RxDataSignal(*mainStreamPtr_)); // wait
     367              :     }
     368              : 
     369            0 :     if (hasRecv) {
     370            0 :         CHK_RET(preLink->RxWaitDone(*mainStreamPtr_));
     371              :     }
     372              : 
     373            0 :     if (hasSend) {
     374            0 :         CHK_RET(aftLink->TxWaitDone(*mainStreamPtr_));
     375              :     }
     376              : 
     377            0 :     return HCCL_SUCCESS;
     378              : }
     379              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_ALL_2_ALL_V_STAGED_PAIRWISE, AlltoAllVStagedPairwise);
     380              : } // namespace hccl
        

Generated by: LCOV version 2.0-1