LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_all_reduce - all_reduce_mesh_opbase.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 22.6 % 159 36
Test Date: 2026-08-18 17:47:01 Functions: 38.5 % 13 5

            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 "alg_template_register.h"
      12              : #include "all_reduce_mesh_opbase.h"
      13              : 
      14              : namespace hccl {
      15            3 : AllReduceMeshDirect::AllReduceMeshDirect(const HcclDispatcher dispatcher) : AlgTemplateBase(dispatcher) {}
      16              : 
      17            6 : AllReduceMeshDirect::~AllReduceMeshDirect() {}
      18              : 
      19            3 : HcclResult AllReduceMeshDirect::Prepare(
      20              :     u64 reduceAttrBitMap, std::vector<Stream>& meshStreams, std::vector<std::shared_ptr<LocalNotify>>& meshSignal,
      21              :     std::vector<std::shared_ptr<LocalNotify>>& meshSignalAux, u32 interRank, u32 interRankSize, u32 userRank,
      22              :     HcomCollOpInfo* opInfo)
      23              : {
      24            3 :     reduceAttr_ = reduceAttrBitMap;
      25            3 :     localRank_ = interRank;
      26            3 :     localRankSize_ = interRankSize;
      27            3 :     userRank_ = userRank;
      28            3 :     meshStreams_ = meshStreams;
      29            3 :     meshSignal_ = &meshSignal;
      30            3 :     meshSignalAux_ = &meshSignalAux;
      31            3 :     opInfo_ = opInfo;
      32            3 :     return HCCL_SUCCESS;
      33              : }
      34              : 
      35            0 : HcclResult AllReduceMeshDirect::MainRecordSub()
      36              : {
      37            0 :     for (u32 signalIndex = 0; signalIndex < meshSignalAux_->size(); signalIndex++) {
      38            0 :         CHK_RET(LocalNotify::Post(stream_, dispatcher_, (*meshSignalAux_)[signalIndex], profilerInput_.stage));
      39              :     }
      40            0 :     return HCCL_SUCCESS;
      41              : }
      42              : 
      43            0 : HcclResult AllReduceMeshDirect::SubWaitMain()
      44              : {
      45            0 :     for (u32 streamIndex = 0; streamIndex < meshSignalAux_->size(); streamIndex++) {
      46            0 :         CHK_RET(LocalNotify::Wait(
      47              :             meshStreams_[streamIndex], dispatcher_, (*meshSignalAux_)[streamIndex], profilerInput_.stage));
      48              :     }
      49            0 :     return HCCL_SUCCESS;
      50              : }
      51              : 
      52            0 : HcclResult AllReduceMeshDirect::MainWaitSub()
      53              : {
      54            0 :     for (u32 signalIndex = 0; signalIndex < meshSignal_->size(); signalIndex++) {
      55            0 :         CHK_RET(LocalNotify::Wait(stream_, dispatcher_, (*meshSignal_)[signalIndex], profilerInput_.stage));
      56              :     }
      57            0 :     return HCCL_SUCCESS;
      58              : }
      59              : 
      60            0 : HcclResult AllReduceMeshDirect::SubRecordMain()
      61              : {
      62            0 :     for (u32 streamIndex = 0; streamIndex < meshSignal_->size(); streamIndex++) {
      63            0 :         CHK_RET(LocalNotify::Post(
      64              :             meshStreams_[streamIndex], dispatcher_, (*meshSignal_)[streamIndex], profilerInput_.stage));
      65              :     }
      66            0 :     return HCCL_SUCCESS;
      67              : }
      68              : 
      69              : // 将数据均分,最小单位是128
      70            3 : HcclResult AllReduceMeshDirect::PrepareSlice(u64 dataCount, u32 unitSize, u32 sliceNum, std::vector<Slice>& dataSlice)
      71              : {
      72            3 :     Slice temp;
      73            3 :     u64 totalSize = dataCount * unitSize;
      74            3 :     dataSlice.clear();
      75            3 :     dataSlice.reserve(sliceNum);
      76            3 :     if (sliceNum == 0) {
      77            0 :         HCCL_ERROR("[Prepare][SliceData]data slice prepare, sliceNum is 0");
      78            0 :         return HCCL_E_PARA;
      79              :     }
      80            3 :     u64 sizePerSlice = (totalSize + sliceNum - 1) / sliceNum; /* 1是为了向上取整 */
      81            3 :     sizePerSlice = RoundUpWithDivisor(sizePerSlice, HCCL_MIN_SLICE_ALIGN_910B);
      82            3 :     u64 residueSize = totalSize;
      83            3 :     u32 i = 0;
      84            6 :     while (residueSize > 0) {
      85            3 :         u64 sliceSize = sizePerSlice < residueSize ? sizePerSlice : residueSize;
      86            3 :         temp.size = sliceSize;
      87            3 :         temp.offset = totalSize - residueSize;
      88            3 :         i++;
      89            3 :         if (sliceSize <= 0) {
      90            0 :             HCCL_ERROR("[Prepare][SliceData]data_slice_prepare sliceSize[%llu]", sliceSize);
      91            0 :             return HCCL_E_PARA;
      92              :         }
      93            3 :         residueSize -= sliceSize;
      94            3 :         dataSlice.push_back(temp);
      95              :     }
      96           24 :     while (i < sliceNum) {
      97           21 :         temp.size = 0;
      98           21 :         temp.offset = totalSize;
      99           21 :         i++;
     100           21 :         dataSlice.push_back(temp);
     101              :     }
     102            3 :     return HCCL_SUCCESS;
     103              : }
     104              : 
     105            0 : HcclResult AllReduceMeshDirect::PrepareAllreduceSliceData()
     106              : {
     107            0 :     return PrepareSlice(count_, DataUnitSize(dataType_), localRankSize_, slices_);
     108              : }
     109              : 
     110              : // ringallreduce算法的函数入口
     111            0 : HcclResult AllReduceMeshDirect::RunAsync(const u32 rank, const u32 rankSize, const std::vector<LINK>& links)
     112              : {
     113            0 :     HcclResult ret = HCCL_SUCCESS;
     114            0 :     CHK_SMART_PTR_NULL(dispatcher_);
     115            0 :     CHK_PTR_NULL(stream_.ptr());
     116            0 :     HCCL_INFO(
     117              :         "AllReduceMeshDirect run: rank[%u] ranksize[%u] inputMem[%p] outputMem[%p] count[%llu]", rank, rankSize,
     118              :         inputMem_.ptr(), outputMem_.ptr(), count_);
     119              : 
     120            0 :     if (links.size() < rankSize) {
     121            0 :         HCCL_ERROR(
     122              :             "[AllReduceMeshDirect][RunAsync]rank[%u] linksize[%llu] is less than rankSize[%u]", rank, links.size(),
     123              :             rankSize);
     124            0 :         return HCCL_E_INTERNAL;
     125              :     }
     126              : 
     127              :     // 如果ranksize为1, inline reduce和普通跨片reduce操作一致,从input->output
     128            0 :     if (rankSize == 1) {
     129            0 :         if (opInfo_->inputAddr != opInfo_->outputAddr) {
     130            0 :             DeviceMem userMemIn = DeviceMem::create(opInfo_->inputAddr, count_ * DataUnitSize(dataType_));
     131            0 :             DeviceMem userMemOut = DeviceMem::create(opInfo_->outputAddr, count_ * DataUnitSize(dataType_));
     132            0 :             ret = HcclD2DMemcpyAsync(dispatcher_, userMemOut, userMemIn, stream_);
     133            0 :             CHK_PRT_RET(
     134              :                 ret != HCCL_SUCCESS, HCCL_ERROR("[AllReduceRing][RunAsync]rank[%u] memcpy async failed", rank), ret);
     135            0 :         }
     136            0 :         return ret;
     137              :     }
     138              : 
     139            0 :     ret = PrepareAllreduceSliceData();
     140            0 :     CHK_PRT_RET(
     141              :         ret != HCCL_SUCCESS,
     142              :         HCCL_ERROR(
     143              :             "[AllReduceRing][RunAsync]rank[%u] count[%llu] failed in PrepareSliceData "
     144              :             "step",
     145              :             rank, count_),
     146              :         ret);
     147              : 
     148            0 :     ret = RunReduceScatter(rank, rankSize, links);
     149            0 :     CHK_PRT_RET(
     150              :         ret != HCCL_SUCCESS,
     151              :         HCCL_ERROR(
     152              :             "[AllReduceRing][RunAsync]rank[%u] count[%llu] failed in reducescater "
     153              :             "step",
     154              :             rank, count_),
     155              :         ret);
     156              : 
     157            0 :     ret = RunAllGather(rank, rankSize, links);
     158            0 :     CHK_PRT_RET(
     159              :         ret != HCCL_SUCCESS,
     160              :         HCCL_ERROR(
     161              :             "[AllReduceRing][RunAsync]rank[%u] count[%llu] failed in AllGather "
     162              :             "step",
     163              :             rank, count_),
     164              :         ret);
     165              : 
     166            0 :     HCCL_INFO("AllReduceMeshDirect finished: rank[%u] ranksize[%u].", rank, rankSize);
     167            0 :     return HCCL_SUCCESS;
     168              : }
     169              : 
     170            0 : HcclResult AllReduceMeshDirect::RunReduceScatter(u32 rank, u32 rankSize, const std::vector<LINK>& links)
     171              : {
     172            0 :     HCCL_INFO(
     173              :         "ReduceScatterMeshAtomicOpbase run: rank[%u] totalrank[%u] inputMem[%p] outputMem[%p] count[%llu].", rank,
     174              :         rankSize, inputMem_.ptr(), outputMem_.ptr(), count_);
     175              : 
     176              :     // 数据准备
     177            0 :     u32 unitSize = DataUnitSize(dataType_);
     178              : 
     179            0 :     DeviceMem userMemIn = DeviceMem::create(opInfo_->inputAddr, count_ * unitSize);
     180            0 :     DeviceMem commMemOut = DeviceMem::create(outputMem_.ptr(), outputMem_.size());
     181              : 
     182            0 :     DeviceMem src;
     183            0 :     DeviceMem dst;
     184              : 
     185            0 :     src = DeviceMem::create(static_cast<char*>(opInfo_->inputAddr) + slices_[rank].offset, slices_[rank].size);
     186            0 :     dst = commMemOut.range(0, slices_[rank].size);
     187            0 :     CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dst, src, stream_));
     188              : 
     189            0 :     CHK_RET(MainRecordSub());
     190            0 :     CHK_RET(SubWaitMain());
     191              : 
     192            0 :     for (u32 round = 1; round < rankSize; round++) {
     193            0 :         u32 dstRank = (round + rank) % rankSize;
     194            0 :         Stream& subStream = meshStreams_[round - 1];
     195            0 :         CHK_RET(links[dstRank]->TxAck(subStream));
     196            0 :         CHK_RET(links[dstRank]->RxAck(subStream));
     197              :     }
     198              : 
     199            0 :     CHK_RET(SubRecordMain());
     200            0 :     CHK_RET(MainWaitSub());
     201            0 :     DeviceMem srcTmp = DeviceMem::create(inputMem_.ptr(), 0);
     202            0 :     DeviceMem dstTmp = DeviceMem::create(outputMem_.ptr(), 0);
     203            0 :     CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dstTmp, srcTmp, stream_));
     204            0 :     CHK_RET(SubWaitMain());
     205            0 :     CHK_RET(MainRecordSub());
     206              : 
     207            0 :     for (u32 round = 1; round < rankSize; round++) {
     208            0 :         u32 dstRank = (round + rank) % rankSize;
     209            0 :         Stream& subStream = meshStreams_[round - 1];
     210              : 
     211            0 :         void* remMemPtr = nullptr;
     212            0 :         CHK_RET(links[dstRank]->GetRemoteMem(UserMemType::OUTPUT_MEM, &remMemPtr));
     213              : 
     214            0 :         dst = DeviceMem::create(static_cast<char*>(remMemPtr), slices_[dstRank].size);
     215            0 :         src = userMemIn.range(slices_[dstRank].offset, slices_[dstRank].size);
     216            0 :         CHK_RET(HcclReduceAsync(
     217              :             dispatcher_, static_cast<void*>(src.ptr()), slices_[dstRank].size / unitSize, dataType_, reductionOp_,
     218              :             subStream, static_cast<void*>(dst.ptr()), links[dstRank]->GetRemoteRank(), links[dstRank]->GetLinkType(),
     219              :             INLINE_REDUCE_BIT));
     220              : 
     221            0 :         CHK_RET(links[dstRank]->TxDataSignal(subStream));
     222            0 :         CHK_RET(links[dstRank]->RxDataSignal(subStream));
     223              :     }
     224              : 
     225            0 :     CHK_RET(SubRecordMain());
     226            0 :     CHK_RET(MainWaitSub());
     227            0 :     return HCCL_SUCCESS;
     228            0 : }
     229              : 
     230            0 : HcclResult AllReduceMeshDirect::RunAllGather(u32 rank, u32 rankSize, const std::vector<LINK>& links)
     231              : {
     232            0 :     HCCL_INFO(
     233              :         "AllGatherMesh run: rank[%u] totalrank[%u] inputMem[%p] outputMem[%p] count[%llu].", rank, rankSize,
     234              :         inputMem_.ptr(), outputMem_.ptr(), count_);
     235            0 :     u32 unitSize = DataUnitSize(dataType_);
     236              : 
     237            0 :     DeviceMem userMemOut = DeviceMem::create(opInfo_->outputAddr, count_ * unitSize);
     238            0 :     DeviceMem commMemOut = DeviceMem::create(outputMem_.ptr(), outputMem_.size());
     239              : 
     240            0 :     DeviceMem src;
     241            0 :     DeviceMem dst;
     242              : 
     243            0 :     src = commMemOut.range(0, slices_[rank].size);
     244            0 :     dst = userMemOut.range(slices_[rank].offset, slices_[rank].size);
     245            0 :     CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dst, src, stream_));
     246              : 
     247            0 :     CHK_RET(MainRecordSub());
     248            0 :     CHK_RET(SubWaitMain());
     249              : 
     250            0 :     for (u32 round = 1; round < rankSize; round++) {
     251            0 :         u32 dstRank = BackwardRank(rank, rankSize, round);
     252            0 :         Stream& subStream = meshStreams_[round - 1];
     253            0 :         CHK_RET(links[dstRank]->TxAck(subStream));
     254            0 :         CHK_RET(links[dstRank]->RxAck(subStream));
     255              :     }
     256              : 
     257            0 :     CHK_RET(SubRecordMain());
     258            0 :     CHK_RET(MainWaitSub());
     259            0 :     DeviceMem srcTmp = DeviceMem::create(inputMem_.ptr(), 0);
     260            0 :     DeviceMem dstTmp = DeviceMem::create(outputMem_.ptr(), 0);
     261            0 :     CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dstTmp, srcTmp, stream_));
     262            0 :     CHK_RET(SubWaitMain());
     263            0 :     CHK_RET(MainRecordSub());
     264              : 
     265            0 :     for (u32 round = 1; round < rankSize; round++) {
     266            0 :         u32 dstRank = BackwardRank(rank, rankSize, round);
     267            0 :         Stream& subStream = meshStreams_[round - 1];
     268            0 :         void* remMemPtr = nullptr;
     269            0 :         CHK_RET(links[dstRank]->GetRemoteMem(UserMemType::OUTPUT_MEM, &remMemPtr));
     270            0 :         src = DeviceMem::create(static_cast<char*>(remMemPtr), slices_[dstRank].size);
     271            0 :         dst = userMemOut.range(slices_[dstRank].offset, slices_[dstRank].size);
     272            0 :         CHK_RET(HcclD2DMemcpyAsync(
     273              :             dispatcher_, dst, src, subStream, links[dstRank]->GetRemoteRank(), links[dstRank]->GetLinkType()));
     274            0 :         CHK_RET(links[dstRank]->TxDataSignal(subStream));
     275            0 :         CHK_RET(links[dstRank]->RxDataSignal(subStream));
     276              :     }
     277              : 
     278            0 :     CHK_RET(SubRecordMain());
     279            0 :     CHK_RET(MainWaitSub());
     280              : 
     281            0 :     HCCL_INFO("AllGatherMesh finished: rank[%u]", rank);
     282            0 :     return HCCL_SUCCESS;
     283            0 : }
     284              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_ALL_REDUCE_MESH_DIRECT, AllReduceMeshDirect);
     285              : } // namespace hccl
        

Generated by: LCOV version 2.0-1