LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_reduce - reduce_ring.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 5.8 % 86 5
Test Date: 2026-08-18 17:47:01 Functions: 66.7 % 6 4

            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 "reduce_ring.h"
      13              : 
      14              : namespace hccl {
      15            1 : ReduceRing::ReduceRing(const HcclDispatcher dispatcher) : AlgTemplateBase(dispatcher) {}
      16              : 
      17            2 : ReduceRing::~ReduceRing() {}
      18              : 
      19            1 : HcclResult ReduceRing::Prepare(u64 reduceAttrBitMap, [[maybe_unused]] HcomCollOpInfo* opInfo)
      20              : {
      21            1 :     reduceAttr_ = reduceAttrBitMap;
      22            1 :     return HCCL_SUCCESS;
      23              : }
      24              : 
      25              : // reduce算法的入口函数
      26              : HcclResult
      27            0 : ReduceRing::RunAsync(const u32 rank, const u32 rankSize, const std::vector<std::shared_ptr<Transport>>& links)
      28              : {
      29            0 :     CHK_SMART_PTR_NULL(dispatcher_);
      30            0 :     CHK_PTR_NULL(stream_.ptr());
      31            0 :     bool bRetNull = (!outputMem_ || !inputMem_);
      32            0 :     CHK_PRT_RET(
      33              :         bRetNull, HCCL_ERROR("[ReduceRing][RunAsync]rank[%u] inputmem or outputmem is null", rank), HCCL_E_PARA);
      34              : 
      35            0 :     HcclResult ret = HCCL_SUCCESS;
      36            0 :     HCCL_INFO(
      37              :         "ReduceRing run: rank[%u] totalrank[%u] root[%u] inputmem[%p] output[%p] count[%llu]", rank, rankSize, root_,
      38              :         inputMem_.ptr(), outputMem_.ptr(), count_);
      39              : 
      40              :     // 如果ranksize为1, inline reduce和普通跨片reduce操作一致,从input->output
      41            0 :     if (rankSize == 1) {
      42            0 :         if (inputMem_ != outputMem_) {
      43            0 :             ret = HcclD2DMemcpyAsync(dispatcher_, outputMem_, inputMem_, stream_);
      44              :         }
      45            0 :         return ret;
      46              :     }
      47              : 
      48            0 :     HCCL_DEBUG("[ReduceRing][RunAsync]rankSize is %u", rankSize);
      49              :     // 创建reducer & sender
      50            0 :     senderInfo_.reset(new (std::nothrow) Sender(dataType_, reductionOp_, reduceAttr_));
      51            0 :     CHK_SMART_PTR_NULL(senderInfo_);
      52              : 
      53            0 :     reducerInfo_.reset(new (std::nothrow) Reducer(dataType_, reductionOp_, reduceAttr_));
      54            0 :     CHK_SMART_PTR_NULL(reducerInfo_);
      55              : 
      56              :     // 获取ring algorithm所需的通信连接
      57            0 :     u32 ringPrevRank = (rank + rankSize - 1) % rankSize;
      58            0 :     u32 ringNextRank = (rank + 1) % rankSize;
      59              : 
      60            0 :     if (links.size() < rankSize) {
      61            0 :         HCCL_ERROR("[ReduceRing][RunAsync]rank[%u] Link size is less than rank size", rank);
      62            0 :         return HCCL_E_INTERNAL;
      63              :     }
      64              : 
      65            0 :     linkLeft_ = links[ringPrevRank];
      66            0 :     CHK_SMART_PTR_NULL(linkLeft_);
      67              : 
      68            0 :     linkRight_ = links[ringNextRank];
      69            0 :     CHK_SMART_PTR_NULL(linkRight_);
      70              : 
      71            0 :     scratch_ = DeviceMem::create(inputMem_.ptr(), inputMem_.size());
      72              : 
      73            0 :     u32 dataSize = DataUnitSize(dataType_);
      74            0 :     if (dataSize == 0) {
      75            0 :         HCCL_ERROR("[ReduceRing][RunAsync]rank[%u] unit data size is zero", rank);
      76            0 :         return HCCL_E_INTERNAL;
      77              :     }
      78              : 
      79              :     // 计算以chunk_size_为最大处理单元时,能够处理的最大数据个数
      80              :     // 每轮需要操作的数据个数
      81            0 :     CHK_RET(linkLeft_->TxAck(stream_));
      82            0 :     CHK_RET(linkRight_->RxAck(stream_));
      83            0 :     u64 length = count_ * dataSize;
      84              : 
      85            0 :     if (rank == root_) {
      86              :         // root节点只接收数据
      87            0 :         DeviceMem localSrc = scratch_.range(0, length);
      88            0 :         DeviceMem dst = outputMem_.range(0, length);
      89            0 :         HCCL_DEBUG("rank [%u] recv data offset[%llu] size[%llu] reduce", rank, 0, length);
      90              : 
      91              :         // 需要从前一节点接收数据,替换reducer接口
      92            0 :         ret = reducerInfo_->run(
      93            0 :             dispatcher_, linkLeft_, baseOffset_, localSrc, dst, dst, stream_, DstMemType::RESULT_OUTPUT_MEM);
      94            0 :         CHK_PRT_RET(
      95              :             ret != HCCL_SUCCESS,
      96              :             HCCL_ERROR("[ReduceRing][RunAsync]rank[%u] reduce data offset[%llu] size[%llu]", rank, 0, length), ret);
      97              : 
      98              :         // 给前一节点发送同步
      99            0 :         CHK_RET(linkLeft_->TxAck(stream_));
     100            0 :         CHK_RET(linkLeft_->RxWaitDone(stream_));
     101            0 :     } else if (ringPrevRank == root_) {
     102              :         // 本rank的前一节点是root节点,本rank数据拷贝到下一rank,不做reduce操作
     103              :         // 需要向下一节点拷贝的数据
     104            0 :         DeviceMem localSrc = scratch_.range(0, length);
     105              : 
     106              :         // 数据拷贝和向下一节点发送
     107            0 :         HCCL_DEBUG("rank [%u] send offset[%llu] size[%llu]", rank, 0, length);
     108              : 
     109            0 :         ret = senderInfo_->run(linkRight_, baseOffset_, localSrc, stream_);
     110            0 :         CHK_PRT_RET(
     111              :             ret != HCCL_SUCCESS,
     112              :             HCCL_ERROR(
     113              :                 "[ReduceRing][RunAsync]rank[%u] send scratch offset[%llu] size[%llu] "
     114              :                 "failed",
     115              :                 rank, baseOffset_, length),
     116              :             ret);
     117              : 
     118              :         // 等待后一节点同步信号
     119            0 :         CHK_RET(linkRight_->RxAck(stream_));
     120            0 :         CHK_RET(linkRight_->TxWaitDone(stream_));
     121            0 :     } else {
     122              :         // 其余节点,先接收数据,和自身数据进行reduce操作,结果放入tx中,发送至下一节点
     123              :         // 剩余需要处理的数据大于满chunk size时,以chunksize为处理单位,否则直接处理剩余数据
     124              : 
     125              :         // 接收到的数据和scratch数据运算后,放入output
     126            0 :         DeviceMem localSrc = scratch_.range(0, length);
     127            0 :         DeviceMem dst = outputMem_.range(0, length);
     128              : 
     129              :         // 用reduce接口封装
     130            0 :         HCCL_DEBUG("rank[%u] recv data reduce offset[%llu] size[%llu]", rank, 0, length);
     131              : 
     132            0 :         ret = reducerInfo_->run(
     133            0 :             dispatcher_, linkLeft_, baseOffset_, localSrc, localSrc, dst, stream_, DstMemType::RESULT_INPUT_MEM);
     134            0 :         CHK_PRT_RET(
     135              :             ret != HCCL_SUCCESS,
     136              :             HCCL_ERROR("[ReduceRing][RunAsync]rank[%u] reducer offset[%llu] size[%llu] failed", rank, 0, length), ret);
     137              : 
     138              :         // 给前一节点发送同步
     139            0 :         CHK_RET(linkLeft_->TxAck(stream_));
     140            0 :         CHK_RET(linkLeft_->RxWaitDone(stream_));
     141              : 
     142              :         // tx数据向下一个节点发送
     143              :         // 需要再封装接口,只把数据发到tx_mem,send_only
     144            0 :         HCCL_DEBUG("rank[%u] send localSrc offset[%llu] size[%llu]", rank, 0, length);
     145              : 
     146            0 :         ret = senderInfo_->run(linkRight_, baseOffset_, localSrc, stream_);
     147            0 :         CHK_PRT_RET(
     148              :             ret != HCCL_SUCCESS,
     149              :             HCCL_ERROR("[ReduceRing][RunAsync]rank[%u] sender offset[%llu] failed", rank, baseOffset_), ret);
     150              : 
     151              :         // 等待后一节点同步信号
     152            0 :         CHK_RET(linkRight_->RxAck(stream_));
     153            0 :         CHK_RET(linkRight_->TxWaitDone(stream_));
     154            0 :     }
     155            0 :     CHK_RET(linkRight_->TxDataSignal(stream_));
     156            0 :     CHK_RET(linkLeft_->RxDataSignal(stream_));
     157            0 :     HCCL_INFO("ReduceRing finished: rank[%u]", rank);
     158            0 :     return HCCL_SUCCESS;
     159              : }
     160              : HcclResult
     161            0 : ReduceRing::GetNslbAdjInfo(const u32 rank, const u32 rankSize, const std::vector<LINK>& links, AdjInfo& nslbAdjInfo)
     162              : {
     163            0 :     if (rankSize == 1) {
     164            0 :         return HCCL_E_NOT_SUPPORT;
     165              :     }
     166            0 :     u32 ringNextRank = (rank + 1) % rankSize;
     167            0 :     LINK nslbNext = links[ringNextRank];
     168              : 
     169            0 :     NslbDpAdjInfo adjInfoStep = {};
     170            0 :     nslbAdjInfo.dstRankNum = 1;
     171            0 :     adjInfoStep.dstLocalRankId = nslbNext->GetRemoteRank();
     172            0 :     adjInfoStep.phaseId = 1;
     173            0 :     adjInfoStep.rev = 0;
     174            0 :     nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     175              : 
     176            0 :     return HCCL_SUCCESS;
     177            0 : }
     178              : 
     179              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_REDUCE_RING, ReduceRing);
     180              : } // namespace hccl
        

Generated by: LCOV version 2.0-1