LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/impl/coll_executor/coll_reduce_scatter_v - coll_reduce_scatter_v_executor.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 135 0
Test Date: 2026-08-04 10:52:23 Functions: 0.0 % 9 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 "coll_reduce_scatter_v_executor.h"
      12              : 
      13              : namespace hccl {
      14              : 
      15            0 : CollReduceScatterVExecutor::CollReduceScatterVExecutor(const HcclDispatcher dispatcher,
      16            0 :     std::unique_ptr<TopoMatcher> &topoMatcher)
      17            0 :     : CollCommExecutor(dispatcher, topoMatcher)
      18              : {
      19            0 : }
      20              : 
      21            0 : HcclResult CollReduceScatterVExecutor::Orchestrate(OpParam& param, AlgResourceResponse& algRes)
      22              : {
      23            0 :     HcclUs startut = TIME_NOW();
      24            0 :     ParseParam(param);
      25            0 :     tag_ = param.tag;
      26            0 :     algResResp_ = &algRes;
      27            0 :     u64 count = static_cast<u64*>(param.VDataDes.counts)[topoAttr_.userRank];
      28            0 :     HcclResult ret = HCCL_SUCCESS;
      29              :     // 图模式场景下不需要Loop
      30            0 :     if (workflowMode_ != HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
      31            0 :         ExecMem execMem;
      32            0 :         execMem.count = count;
      33            0 :         execMem.inputPtr = param.inputPtr;
      34            0 :         execMem.outputPtr = param.outputPtr;
      35            0 :         execMem.inputMem = algRes.paramInputMem;
      36            0 :         execMem.outputMem = algRes.paramOutputMem;
      37            0 :         execMem.scratchMem = algRes.scratchMem;
      38            0 :         ret = KernelRun(param, execMem);
      39            0 :     } else {
      40            0 :         ret = RunLoop(param, algRes);
      41              :     }
      42            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
      43              :         HCCL_ERROR("[CollReduceScatterVExecutor][Orchestrate]errNo[0x%016llx]executor kernel run failed",
      44              :             HCCL_ERROR_CODE(ret)), ret);
      45            0 :     HCCL_INFO("tag[%s], ReduceScatterV executor orchestrate success, take time [%lld]us.",
      46              :         param.tag.c_str(), DURATION_US(TIME_NOW() - startut));
      47            0 :     return HCCL_SUCCESS;
      48              : }
      49              : 
      50            0 : HcclResult CollReduceScatterVExecutor::GetAdjInfo(AlgResourceResponse& algRes, AdjInfo& adjInfo)
      51              : {
      52              :     (void) algRes;
      53              :     (void) adjInfo;
      54            0 :     return HCCL_SUCCESS;
      55              : }
      56              : 
      57            0 : u64 CollReduceScatterVExecutor::CalcLoopMaxCount(const u32 unitSize)
      58              : {
      59              :     // 中转内存单次最多能够接受的output count,这里不除以RankSize,因为每次循环可能会减少需要参与通信的Rank
      60            0 :     u64 maxCountPerLoop = inCCLbufferSize_ / HCCL_MIN_SLICE_ALIGN
      61            0 :         * HCCL_MIN_SLICE_ALIGN / unitSize;
      62            0 :     HCCL_INFO("[CollReduceScatterVExecutor][CalcLoopMaxCount]" \
      63              :         "using default maxCountPerLoop[%llu] as CCLBuffSize / unitSize.", maxCountPerLoop);
      64            0 :     return maxCountPerLoop;
      65              : }
      66              : 
      67            0 : bool CollReduceScatterVExecutor::IsHugeData(const u64 curSize, const OpParam &param)
      68              : {
      69              :     (void) param;
      70            0 :     bool hugeData = (curSize * topoAttr_.userRankSize / HCCL_INTERNODE_MAX_DATA_RATE > RDMA_SEND_MAX_SIZE) ||
      71              :                             (curSize > SDMA_SEND_MAX_SIZE);
      72            0 :     return hugeData;
      73              : }
      74              : 
      75            0 : HcclResult CollReduceScatterVExecutor::CalcCurCountsAndCurDispls(const u64 maxTotalCount, std::vector<u64> &countsLeft,
      76              :         std::vector<u64> &displs, std::vector<u64> &curCounts, std::vector<u64> &curDispls, bool &finished)
      77              : {
      78            0 :     HCCL_DEBUG("[CollReduceScatterVExecutor][CalcCurCountsAndCurDispls]default func called.");
      79            0 :     return HCCL_SUCCESS;
      80              : }
      81              : 
      82              : 
      83            0 : HcclResult CollReduceScatterVExecutor::RunLoop(OpParam &param, AlgResourceResponse &algRes)
      84              : {
      85              :     // 每轮loop需要重新计算counts和displs
      86            0 :     const auto *countsPtr = static_cast<const u64*>(param.VDataDes.counts);
      87            0 :     auto countsLeft = std::vector<u64>(countsPtr, countsPtr + topoAttr_.userRankSize);
      88            0 :     const auto *displsPtr = static_cast<const u64*>(param.VDataDes.displs);
      89            0 :     auto displs = std::vector<u64>(displsPtr, displsPtr + topoAttr_.userRankSize);
      90              : 
      91            0 :     const HcclDataType dataType = param.VDataDes.dataType;
      92            0 :     const u32 unitSize = SIZE_TABLE[dataType];
      93            0 :     HCCL_DEBUG("[CollReduceScatterVExecutor][RunLoop]unitSize is %u", unitSize);
      94            0 :     u8 *curInputPtr = static_cast<u8 *>(param.inputPtr);
      95            0 :     u8 *curOutputPtr = static_cast<u8 *>(param.outputPtr);
      96            0 :     CHK_PTR_NULL(curInputPtr);
      97              : 
      98            0 :     if (UNLIKELY(countsLeft[topoAttr_.userRank] == 0 && curOutputPtr == nullptr)) {
      99              :         // 若本rank的output count为0,此时允许curOutputPtr传入空指针,为保证后续流程正常执行,赋值为cclout的地址
     100            0 :         curOutputPtr = static_cast<u8 *>(algRes.cclOutputMem.ptr());
     101            0 :         HCCL_DEBUG("Since the output count is 0, set curOutputPtr to ccl output[%p]", curOutputPtr);
     102              :     } else {
     103            0 :         CHK_PTR_NULL(curOutputPtr);
     104              :     }
     105              : 
     106            0 :     ReduceType reduceType = ((param.reduceType != HCCL_REDUCE_PROD) &&
     107            0 :         (dataType != HCCL_DATA_TYPE_INT64)) ?
     108              :         ReduceType::INLINE_REDUCE : ReduceType::TBE_REDUCE;
     109              : 
     110              :     // 计算MaxCountPerLoop
     111            0 :     const u64 maxCountPerLoop = CalcLoopMaxCount(unitSize);
     112              :     HcclResult ret;
     113            0 :     bool finished = false;
     114            0 :     while (!finished) {
     115              :         // 每个块尽可能平分,以均衡利用带宽
     116            0 :         auto curCounts = std::vector<u64>();
     117            0 :         auto curDispls = std::vector<u64>();
     118            0 :         CHK_RET(CalcCurCountsAndCurDispls(maxCountPerLoop, countsLeft, displs, curCounts, curDispls, finished));
     119              :         // 打印调测信息
     120            0 :         PrintCurCountAndCurDispls(curCounts, curDispls);
     121              : 
     122            0 :         OpParam curParam = param;
     123            0 :         curParam.VDataDes.counts = curCounts.data();
     124            0 :         curParam.VDataDes.displs = curDispls.data();
     125            0 :         curParam.VDataDes.dataType = dataType;
     126              : 
     127            0 :         ExecMem execMem;
     128            0 :         execMem.count = curCounts[topoAttr_.userRank];
     129            0 :         execMem.inputPtr = curInputPtr;
     130            0 :         execMem.outputPtr = curOutputPtr;
     131            0 :         execMem.inputMem = algRes.cclInputMem;
     132            0 :         execMem.outputMem = algRes.cclOutputMem;
     133            0 :         if (scratchMemFlag_) {
     134            0 :             execMem.scratchMem = algRes.scratchMem;
     135              :         } else {
     136            0 :             execMem.scratchMem = algRes.cclOutputMem; // 不需要申请则传入outputmem为scratchmem
     137              :         }
     138            0 :         ret = RunLoopInner(curParam, reduceType, execMem);
     139            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
     140              :             HCCL_ERROR("[CollReduceScatterVExecutor][RunLoopForVaringCounts]errNo[0x%016llx]kernel run error, tag[%s]",
     141              :             HCCL_ERROR_CODE(ret), curParam.tag.c_str()), ret);
     142            0 :         curOutputPtr += curCounts[topoAttr_.userRank] * unitSize;
     143              :         // ReduceScatterV curInputPtr不需要偏移,input的偏移由displs计算
     144            0 :     }
     145            0 :     return HCCL_SUCCESS;
     146            0 : }
     147              : 
     148            0 : HcclResult CollReduceScatterVExecutor::RunLoopInner(OpParam &param, const ReduceType &reduceType, ExecMem &execMem)
     149              : {
     150            0 :     u64 count = static_cast<u64*>(param.VDataDes.counts)[topoAttr_.userRank];
     151            0 :     HcclDataType dataType = param.VDataDes.dataType;
     152              : 
     153            0 :     u32 unitSize = SIZE_TABLE[dataType];
     154            0 :     u64 curSize = count * unitSize; // 单位:字节;
     155              : 
     156            0 :     if (!is310P3Common_) {
     157              :         /* 设置子图复用标志 */
     158            0 :         auto autoSelectedAlgTypeLevel1 = static_cast<u32>(algType_.algoLevel1);
     159            0 :         bool hugeData = IsHugeData(curSize, param);
     160            0 :         u8 deterministic = topoMatcher_->GetExternalInputHcclDeterministic();
     161            0 :         auto opMeta = HcclOpMetaInfo::GetOneForReduceScatterV(autoSelectedAlgTypeLevel1,
     162              :             dataType, reduceType, hugeData, false, CopyPattern::BCOPY, false, deterministic);
     163              : 
     164            0 :         CHK_RET(InitTask(dispatcher_, param.stream, opMeta.isEnableCache, opMeta.GetCacheKey()));
     165              :     }
     166              : 
     167            0 :     if (CCLMemSlice_) {
     168            0 :         auto inputCounts = 0ULL;
     169            0 :         for (auto rank = 0U; rank < topoAttr_.userRankSize; ++rank) {
     170            0 :             auto count = static_cast<u64*>(param.VDataDes.counts)[rank];
     171            0 :             inputCounts += count;
     172              :         }
     173            0 :         execMem.inputMem = execMem.inputMem.range(0, inputCounts * unitSize);
     174            0 :         execMem.outputMem = execMem.outputMem.range(0, inputCounts * unitSize);
     175            0 :         if (scratchMemFlag_) {
     176            0 :             execMem.scratchMem = execMem.scratchMem.range(0, inputCounts * unitSize);
     177              :         }
     178              :     }
     179              : 
     180            0 :     if (!DMAReduceFlag_) {
     181              :         // 如果使用in CCL buffer,需要将user buffer in中的结果拷贝到CCL buffer in
     182            0 :         auto cclOffset = 0ULL;
     183            0 :         for (u32 i = 0; i < topoAttr_.userRankSize; i++) {
     184              :             // 拷贝input上每个slice的数据到中转内存,源端每个slice的size固定为output的size
     185            0 :             const auto offset = static_cast<u64*>(param.VDataDes.displs)[i] * unitSize;
     186            0 :             const auto size = static_cast<u64*>(param.VDataDes.counts)[i] * unitSize;
     187            0 :             DeviceMem dstMem = execMem.inputMem.range(cclOffset, size);
     188            0 :             DeviceMem srcMem = DeviceMem::create(static_cast<u8 *>(param.inputPtr) + offset, size);
     189            0 :             CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dstMem, srcMem, param.stream));
     190            0 :             cclOffset += size;
     191            0 :         }
     192            0 :         HCCL_DEBUG("[CollReduceScatterVExecutor][RunLoopInner]copy from user in to ccl in.");
     193              :     }
     194              : 
     195              :     // 执行
     196            0 :     HcclResult ret = KernelRun(param, execMem);
     197            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     198              :         HCCL_ERROR("[CollReduceScatterVExecutor][RunLoopInner]errNo[0x%016llx]kernel run error, tag[%s], " \
     199              :         "inputMem ptr[%p], outputMem ptr[%p], count[%llu], dataType[%d], reduce op type[%d]",
     200              :         HCCL_ERROR_CODE(ret), param.tag.c_str(), execMem.inputMem.ptr(), execMem.outputMem.ptr(),
     201              :         execMem.count, dataType, param.reduceType),
     202              :         ret);
     203              : 
     204            0 :     if (!DMAReduceFlag_) {
     205              :         // CO->UO
     206            0 :         DeviceMem srcMem = execMem.outputMem.range(0, curSize);
     207            0 :         DeviceMem dstMem = DeviceMem::create(execMem.outputPtr, curSize);
     208            0 :         CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dstMem, srcMem, param.stream));
     209            0 :     }
     210            0 :     if (!is310P3Common_) {
     211            0 :         CHK_RET(LaunchTaskExtend(dispatcher_, param.stream, algResResp_->slaveStreams));
     212              :     }
     213            0 :     return ret;
     214              : }
     215              : 
     216            0 : void CollReduceScatterVExecutor::PrintCurCountAndCurDispls(const std::vector<u64> &curCounts,
     217              :     const std::vector<u64> &curDispls)
     218              : {
     219            0 :     if (HcclCheckLogLevel(DLOG_DEBUG)) {
     220            0 :         std::ostringstream curLoopInfo;
     221            0 :         curLoopInfo << "Counts[ ";
     222            0 :         for (auto count : curCounts) {
     223            0 :             curLoopInfo << count << " ";
     224              :         }
     225            0 :         curLoopInfo << "], displs[ ";
     226            0 :         for (auto displ : curDispls) {
     227            0 :             curLoopInfo << displ << " ";
     228              :         }
     229            0 :         curLoopInfo << "]";
     230            0 :         HCCL_DEBUG("[CollReduceScatterVExecutor][PrintCurCountAndCurDispls] Current loop info: %s",
     231              :             curLoopInfo.str().c_str());
     232            0 :     }
     233            0 : }
     234              : 
     235              : } // namespace hccl
        

Generated by: LCOV version 2.0-1