LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_alltoall - allltoall_pipeline_mesh_pairwise_ccl_enough.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 176 0
Test Date: 2026-08-18 17:47:01 Functions: 0.0 % 16 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 "allltoall_pipeline_mesh_pairwise_ccl_enough.h"
      12              : #include "alg_template_register.h"
      13              : 
      14              : namespace hccl {
      15              : 
      16              : static const u32 INTRA_STREAM_INFO_SENDLEN_INDEX = 0;            // intraStreamInfo 中 sendLen 的下标
      17              : static const u32 INTRA_STREAM_INFO_RECVLEN_INDEX = 1;            // intraStreamInfo 中 recvLen 的下标
      18              : static const u32 INTRA_STREAM_INFO_RECV_REMOTE_OFFSET_INDEX = 2; // intraStreamInfo 中 recvRemoteOffset 的下标
      19              : static const u32 INTRA_STREAM_INFO_RECV_LOCAL_OFFSET_INDEX = 3;  // intraStreamInfo 中 recvLocalOffset 的下标
      20              : 
      21            0 : AlltoallPipelineMeshPairwiseCCLEnough::AlltoallPipelineMeshPairwiseCCLEnough(const HcclDispatcher dispatcher)
      22            0 :     : AlltoallPipelineBase(dispatcher)
      23            0 : {}
      24              : 
      25            0 : AlltoallPipelineMeshPairwiseCCLEnough::~AlltoallPipelineMeshPairwiseCCLEnough() {}
      26              : 
      27            0 : u32 AlltoallPipelineMeshPairwiseCCLEnough::CalcInterNumSteps() { return interRankSize_ - 1; }
      28              : 
      29              : // 适配新CollExecutor接口
      30            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::Prepare(
      31              :     u32 userRank, A2aPipelineMemory A2aPipelineMemory, const SubCommInfo& level0CommInfo,
      32              :     const SubCommInfo& level1CommInfo, Stream& mainStream, std::vector<Stream>& subStream,
      33              :     std::vector<std::shared_ptr<LocalNotify>>& notifyMain, std::vector<std::shared_ptr<LocalNotify>>& notifySub,
      34              :     std::vector<SendRecvInfo>& allMeshAggregationSendRecvInfo, HcclWorkflowMode workMode)
      35              : {
      36            0 :     AlltoallPipelineBase::Prepare(
      37              :         userRank, A2aPipelineMemory, level0CommInfo, level1CommInfo, mainStream, subStream, notifyMain, notifySub,
      38              :         allMeshAggregationSendRecvInfo, workMode);
      39            0 :     GetIntraScratchOffset();
      40            0 :     CHK_RET(DeviceMemMapping());
      41            0 :     return HCCL_SUCCESS;
      42              : }
      43              : 
      44              : // 统一计算每步 mesh 内收发时从各卡 scratch 读取的 offset 和 length
      45            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::GetIntraScratchOffset()
      46              : {
      47            0 :     for (u32 i = 0; i < intraRankSize_; i++) {
      48            0 :         intraScratchOffsetMap_[i] = std::vector<u64>();
      49            0 :         intraScratchLengMap_[i] = std::vector<u64>();
      50            0 :         u64 startOffset = 0;
      51            0 :         for (u32 remoteRank = i; remoteRank < groupRankSize_; remoteRank += intraRankSize_) {
      52            0 :             if (remoteRank == userRank_) {
      53            0 :                 localScratchOffset_ = startOffset;
      54              :             }
      55            0 :             const std::vector<u64>& remoteSendOffset = (*allMeshAggregationSendRecvInfo_)[remoteRank].sendOffset;
      56            0 :             const std::vector<u64>& remoteSendLength = (*allMeshAggregationSendRecvInfo_)[remoteRank].sendLength;
      57            0 :             intraScratchOffsetMap_[i].push_back(
      58            0 :                 startOffset + (remoteSendOffset[userRank_] - remoteSendOffset[meshRankStart_]));
      59              :             startOffset
      60            0 :                 += (remoteSendOffset[meshRankEnd_] + remoteSendLength[meshRankEnd_] - remoteSendOffset[meshRankStart_]);
      61            0 :             intraScratchLengMap_[i].push_back(remoteSendLength[userRank_]);
      62              :         }
      63              :     }
      64            0 :     return HCCL_SUCCESS;
      65              : }
      66              : 
      67            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::DeviceMemMapping()
      68              : {
      69            0 :     if (workMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
      70            0 :         interTransportSend_ = cclIn_;
      71            0 :         interTransportRecv_ = cclOut_;
      72            0 :         intraTransportSend_ = cclOut_;
      73              :     } else {
      74            0 :         interTransportSend_ = inputMem_;
      75            0 :         interTransportRecv_ = scratchMem_;
      76            0 :         intraTransportSend_ = scratchMem_;
      77              :     }
      78            0 :     for (u32 intraRank = 0; intraRank < intraRankSize_; intraRank++) {
      79            0 :         if (intraRank == intraRankId_) {
      80            0 :             continue;
      81              :         }
      82            0 :         LINK& intraNeighboorTransport = intraLinks_[intraRank];
      83            0 :         void* remDMAMemPtr = nullptr;
      84            0 :         CHK_RET(intraNeighboorTransport->GetRemoteMem(UserMemType::INPUT_MEM, &remDMAMemPtr));
      85              :         DeviceMem remoteAlltoallScratch = DeviceMem::create(
      86              :             static_cast<u8*>(remDMAMemPtr),
      87            0 :             workMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE ? cclIn_.size() : scratchMem_.size());
      88            0 :         intraNeighBoorMemory_[intraRank] = {remoteAlltoallScratch};
      89            0 :     }
      90            0 :     return HCCL_SUCCESS;
      91            0 : }
      92              : 
      93            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::PrepareInterData(u32 step)
      94              : {
      95              :     // 准备 mesh 间发送信息
      96            0 :     nextInterSendData_.clear();
      97            0 :     u32 interSendRankStart = ((interRankId_ + 1 + step) % interRankSize_) * intraRankSize_;
      98            0 :     u32 interSendRankEnd = interSendRankStart + intraRankSize_ - 1;
      99            0 :     u64 startMemOffset = localSendRecvInfo_.sendOffset[interSendRankStart];
     100            0 :     u64 meshSendLength = localSendRecvInfo_.sendOffset[interSendRankEnd]
     101            0 :                          + localSendRecvInfo_.sendLength[interSendRankEnd] - startMemOffset;
     102            0 :     u64 sendDestOffset = 0;
     103            0 :     for (u32 relatedRank = intraRankId_; relatedRank < userRank_; relatedRank += intraRankSize_) {
     104            0 :         const SendRecvInfo& info = (*allMeshAggregationSendRecvInfo_)[relatedRank];
     105              :         sendDestOffset
     106            0 :             += (info.sendOffset[interSendRankEnd] + info.sendLength[interSendRankEnd]
     107            0 :                 - info.sendOffset[interSendRankStart]);
     108              :     }
     109            0 :     DeviceMem srcMem = inputMem_.range(startMemOffset, meshSendLength);
     110            0 :     DeviceMem dstMem = interTransportSend_.range(startMemOffset, meshSendLength);
     111            0 :     HCCL_DEBUG(
     112              :         "[AlltoallPipelineMeshPairwiseCCLEnough][PrepareInterSendData] userRank %u, interRank %u, "
     113              :         "intraRank %u move from userInput offset %llu length %llu to interTransportSend, send to remote offset "
     114              :         "%llu",
     115              :         userRank_, interRankId_, intraRankId_, startMemOffset, meshSendLength, sendDestOffset);
     116              : 
     117            0 :     HCCL_DEBUG("user size %u, inter size %u, intra size %u", groupRankSize_, interRankSize_, intraRankSize_);
     118            0 :     if (workMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
     119            0 :         CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dstMem, srcMem, mainStream_));
     120              :     }
     121            0 :     nextInterSendData_.emplace_back(
     122            0 :         TxMemoryInfo{UserMemType::OUTPUT_MEM, sendDestOffset, dstMem.ptr(), meshSendLength});
     123              : 
     124              :     // 准备 mesh 间接收信息
     125            0 :     nextInterRecvData_.clear();
     126            0 :     u32 recvBlockStart = (((interRankId_ + interRankSize_ - 1u - step) % interRankSize_) * intraRankSize_);
     127            0 :     u64 recvLocalOffset = 0;
     128            0 :     for (u32 relatedRank = intraRankId_; relatedRank < recvBlockStart; relatedRank += intraRankSize_) {
     129            0 :         const SendRecvInfo& info = (*allMeshAggregationSendRecvInfo_)[relatedRank];
     130              :         recvLocalOffset
     131            0 :             += (info.sendOffset[meshRankEnd_] + info.sendLength[meshRankEnd_] - info.sendOffset[meshRankStart_]);
     132              :     }
     133            0 :     const SendRecvInfo& recvRankInfo = (*allMeshAggregationSendRecvInfo_)[recvBlockStart + intraRankId_];
     134            0 :     u64 recvRemoteOffset = recvRankInfo.sendOffset[meshRankStart_];
     135              :     u64 recvLength
     136            0 :         = (recvRankInfo.sendOffset[meshRankEnd_] + recvRankInfo.sendLength[meshRankEnd_]
     137            0 :            - recvRankInfo.sendOffset[meshRankStart_]);
     138            0 :     nextInterRecvData_.emplace_back(RxMemoryInfo{
     139            0 :         UserMemType::INPUT_MEM, recvRemoteOffset, interTransportRecv_.range(recvLocalOffset, recvLength).ptr(),
     140              :         recvLength});
     141            0 :     return HCCL_SUCCESS;
     142            0 : }
     143              : 
     144              : // 将原先在userInput,且需要发到本mesh内其他卡的数据搬到CCL
     145            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::PrepareIntraData()
     146              : {
     147            0 :     u64 startMemOffset = localSendRecvInfo_.sendOffset[meshRankStart_];
     148              :     u64 meshSendLength
     149            0 :         = localSendRecvInfo_.sendOffset[meshRankEnd_] + localSendRecvInfo_.sendLength[meshRankEnd_] - startMemOffset;
     150            0 :     u64 intraSendOffset = 0;
     151            0 :     for (u32 relatedRank = intraRankId_; relatedRank < meshRankStart_; relatedRank += intraRankSize_) {
     152            0 :         const SendRecvInfo& info = (*allMeshAggregationSendRecvInfo_)[relatedRank];
     153              :         intraSendOffset
     154            0 :             += (info.sendOffset[meshRankEnd_] + info.sendLength[meshRankEnd_] - info.sendOffset[meshRankStart_]);
     155              :     }
     156            0 :     DeviceMem srcMem = inputMem_.range(startMemOffset, meshSendLength);
     157            0 :     DeviceMem dstMem = intraTransportSend_.range(intraSendOffset, meshSendLength);
     158            0 :     if (workMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
     159            0 :         CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dstMem, srcMem, mainStream_));
     160              :     }
     161            0 :     HCCL_DEBUG(
     162              :         "[AlltoallPipelineMeshPairwiseCCLEnough][PrepareIntraData] userRank %u, interRank %u, intraRank %u "
     163              :         "copy from userInput offset %llu length %llu to intraTransportSend offset %llu",
     164              :         userRank_, interRankId_, intraRankId_, startMemOffset, meshSendLength, intraSendOffset);
     165            0 :     return HCCL_SUCCESS;
     166            0 : }
     167              : 
     168            0 : void AlltoallPipelineMeshPairwiseCCLEnough::UpdateIntraStreamInfo(u32 step)
     169              : {
     170            0 :     intraStreamInfo_.clear();
     171            0 :     u32 localMeshIndex = (interRankId_ + interRankSize_ - step) % interRankSize_;
     172            0 :     u32 firstDataBlockIndex = (meshRankStart_ + groupRankSize_ - step * intraRankSize_) % groupRankSize_;
     173              :     const std::vector<u64>& sendLengths
     174            0 :         = (*allMeshAggregationSendRecvInfo_)[firstDataBlockIndex + intraRankId_].sendLength;
     175            0 :     const std::vector<u64>& recvLengths = localSendRecvInfo_.recvLength;
     176            0 :     const std::vector<u64>& recvOffsets = localSendRecvInfo_.recvOffset;
     177            0 :     HCCL_DEBUG(
     178              :         "[AlltoallPipelineMeshPairwiseCCLEnough][UpdateIntraStreamInfo] userRank %u, "
     179              :         "interRank %u, intraRank %u, step %u",
     180              :         userRank_, interRankId_, intraRankId_, step);
     181            0 :     for (u32 intraRank = 0; intraRank < intraRankSize_; intraRank++) {
     182            0 :         u64 sendLen = sendLengths[meshRankStart_ + intraRank];
     183            0 :         u64 recvLen = recvLengths[firstDataBlockIndex + intraRank];
     184            0 :         u64 recvRemoteOffset = intraScratchOffsetMap_[intraRank][localMeshIndex];
     185            0 :         u64 recvLocalOffset = recvOffsets[firstDataBlockIndex + intraRank];
     186            0 :         if (intraRank != intraRankId_) {
     187            0 :             intraStreamInfo_[intraRank] = {sendLen, recvLen, recvRemoteOffset, recvLocalOffset};
     188            0 :             HCCL_DEBUG(
     189              :                 "[AlltoallPipelineMeshPairwiseCCLEnough][UpdateIntraStreamInfo] userRank %u, interRank %u, "
     190              :                 "intraRank %u, sdma stream %u need send %llu and read length %llu from remote offset %llu "
     191              :                 "to local offset %llu",
     192              :                 userRank_, interRankId_, intraRankId_, intraRank, sendLen, recvLen, recvRemoteOffset, recvLocalOffset);
     193              :         }
     194              :     }
     195            0 : }
     196              : 
     197            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::SendRecvDataIntraMesh()
     198              : {
     199            0 :     HCCL_DEBUG(
     200              :         "[AlltoallPipelineMeshPairwiseCCLEnough][SendRecvDataIntraMesh] userRank %u, "
     201              :         "interRank %u, intraRank %u, sdma stream %s wait main stream",
     202              :         userRank_, interRankId_, intraRankId_, GetStreamIndexString().c_str());
     203            0 :     for (auto& intraInfo : intraStreamInfo_) {
     204            0 :         u32 streamIndex = intraInfo.first;
     205            0 :         u64 recvLen = intraInfo.second[INTRA_STREAM_INFO_RECVLEN_INDEX];
     206            0 :         Stream& currStream = subStream_[streamIndex];
     207            0 :         LINK& readTransport = intraLinks_[streamIndex];
     208            0 :         CHK_RET(readTransport->TxAck(currStream));
     209            0 :         CHK_RET(readTransport->RxAck(currStream));
     210            0 :         u64 recvRemoteOffset = intraInfo.second[INTRA_STREAM_INFO_RECV_REMOTE_OFFSET_INDEX];
     211            0 :         u64 recvLocalOffset = intraInfo.second[INTRA_STREAM_INFO_RECV_LOCAL_OFFSET_INDEX];
     212            0 :         DeviceMem src = intraNeighBoorMemory_[streamIndex][0].range(recvRemoteOffset, recvLen);
     213            0 :         DeviceMem dst = outputMem_.range(recvLocalOffset, recvLen);
     214            0 :         CHK_RET(HcclD2DMemcpyAsync(
     215              :             dispatcher_, dst, src, currStream, readTransport->GetRemoteRank(), readTransport->GetLinkType()));
     216            0 :         CHK_RET(readTransport->TxDataSignal(currStream));
     217            0 :         HCCL_DEBUG(
     218              :             "[AlltoallPipelineMeshPairwiseCCLEnough][SendRecvDataIntraMesh] userRank %u, interRank %u, "
     219              :             "intraRank %u, sdma stream %llu read data from remote offset %llu len %llu to local %llu",
     220              :             userRank_, interRankId_, intraRankId_, streamIndex, recvRemoteOffset, recvLen, recvLocalOffset);
     221            0 :         CHK_RET(readTransport->RxDataSignal(currStream));
     222            0 :     }
     223            0 :     HCCL_DEBUG(
     224              :         "[AlltoallPipelineMeshPairwiseCCLEnough][SendRecvDataIntraMesh] userRank %u, interRank %u, "
     225              :         "intraRank %u, sdma stream %s notify main stream",
     226              :         userRank_, interRankId_, intraRankId_, GetStreamIndexString().c_str());
     227            0 :     return HCCL_SUCCESS;
     228              : }
     229              : 
     230            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::SendRecvDataInterMesh(u32 step)
     231              : {
     232            0 :     Stream& interStream = subStream_[intraRankId_];
     233            0 :     LINK& interRecvTransport = interLinks_[(interRankId_ + interRankSize_ - 1 - step) % interRankSize_];
     234            0 :     LINK& interSendTransport = interLinks_[(interRankId_ + 1 + step) % interRankSize_];
     235            0 :     CHK_RET(interRecvTransport->TxAck(interStream));
     236            0 :     CHK_RET(interSendTransport->RxAck(interStream));
     237            0 :     CHK_RET(interSendTransport->TxAsync(nextInterSendData_, interStream));
     238            0 :     CHK_RET(interRecvTransport->RxAsync(nextInterRecvData_, interStream));
     239            0 :     CHK_RET(interRecvTransport->PostFinAck(interStream));
     240            0 :     CHK_RET(interSendTransport->WaitFinAck(interStream));
     241            0 :     CHK_RET(ExecuteBarrier(interRecvTransport, interSendTransport, interStream));
     242            0 :     return HCCL_SUCCESS;
     243              : }
     244              : 
     245            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::LocalCopyDataRecvFromInter(u32 interRankDistance)
     246              : {
     247              :     u64 scratchOffset
     248            0 :         = intraScratchOffsetMap_[intraRankId_][(interRankId_ + interRankSize_ - interRankDistance) % interRankSize_];
     249              :     u64 recvLen = localSendRecvInfo_
     250            0 :                       .recvLength[(userRank_ + groupRankSize_ - interRankDistance * intraRankSize_) % groupRankSize_];
     251              :     u64 userOutOffset
     252              :         = localSendRecvInfo_
     253            0 :               .recvOffset[(userRank_ + groupRankSize_ - interRankDistance * intraRankSize_) % groupRankSize_];
     254            0 :     DeviceMem src = interTransportRecv_.range(scratchOffset, recvLen);
     255            0 :     DeviceMem dst = outputMem_.range(userOutOffset, recvLen);
     256            0 :     HCCL_DEBUG(
     257              :         "[AlltoallPipelineMeshPairwiseCCLEnough][LocalCopyDataRecvFromInter]local move from "
     258              :         "interTransportRecv_ offset %llu length %llu to outputMem_ %llu",
     259              :         scratchOffset, recvLen, userOutOffset);
     260            0 :     CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dst, src, mainStream_));
     261            0 :     return HCCL_SUCCESS;
     262            0 : }
     263              : 
     264            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::PreProcess()
     265              : {
     266              :     // server 间收发时间较长,先搬 server 间收发所需数据然后马上让server间开始收发
     267            0 :     CHK_RET(PrepareInterData(0));
     268            0 :     CHK_RET(NotifyInterStreamStart());
     269              :     // 之后将 server 内所需数据准备好之后唤醒server内从流收发
     270            0 :     UpdateIntraStreamInfo(0);
     271            0 :     CHK_RET(PrepareIntraData());
     272            0 :     CHK_RET(NotifyIntraStreamStart());
     273            0 :     CHK_RET(SendRecvDataIntraMesh());
     274            0 :     return HCCL_SUCCESS;
     275              : }
     276              : 
     277            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::PipelineSend(u32 step, bool isLastStep)
     278              : {
     279            0 :     CHK_RET(SendRecvDataInterMesh(step));
     280            0 :     CHK_RET(PrepareInterData(step + 1u));
     281            0 :     CHK_RET(WaitInterStreamFinish());
     282            0 :     CHK_RET(WaitIntraStreamFinish());
     283            0 :     CHK_RET(ExecEmptyTask(inputMem_, outputMem_, mainStream_, dispatcher_));
     284            0 :     if (!isLastStep) {
     285            0 :         CHK_RET(NotifyInterStreamStart());
     286              :     }
     287            0 :     UpdateIntraStreamInfo(step + 1u);
     288            0 :     CHK_RET(NotifyIntraStreamStart());
     289            0 :     CHK_RET(SendRecvDataIntraMesh());
     290            0 :     CHK_RET(LocalCopyDataRecvFromInter(step + 1u));
     291            0 :     return HCCL_SUCCESS;
     292              : }
     293              : 
     294            0 : HcclResult AlltoallPipelineMeshPairwiseCCLEnough::PostProcess()
     295              : {
     296              :     // 最后的收尾工作
     297            0 :     CHK_RET(LocalCopyDataRecvFromInter(0));
     298            0 :     CHK_RET(WaitIntraStreamFinish());
     299            0 :     return HCCL_SUCCESS;
     300              : }
     301              : REGISTER_TEMPLATE(
     302              :     TemplateType::TEMPLATE_ALL_2_ALL_PIPELINE_MESH_PAIRWISE_CCL_ENOUGH, AlltoallPipelineMeshPairwiseCCLEnough);
     303              : } // namespace hccl
        

Generated by: LCOV version 2.0-1