LCOV - code coverage report
Current view: top level - legacy/ascend910/framework/device/aicpu_kfc/algorithm - aicpu_allgather.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 94.4 % 180 170
Test Date: 2026-08-04 10:52:23 Functions: 100.0 % 6 6

            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 "aicpu_allgather.h"
      12              : #include "common/aicpu_hccl_common.h"
      13              : 
      14              : bool AicpuAllgather::isMCFirstCall = true;
      15              : 
      16           32 : HcclResult AicpuAllgather::RunAlgorithm(HcclReduceOp opType, void *sendBuffer, void *recvBuffer, u64 dataCount,
      17              :     HcclDataType dataType, u64 strideLen, AivAicpuOpParam *nextTask)
      18              : {
      19           32 :     CHK_PTR_NULL(ctx_);
      20           32 :     switch (ctx_->commAlg) {
      21           24 :         case CommAlgType::COMM_ALG_FULL_MESH: {
      22           24 :             if (ctx_->commLen < ctx_->windowSize / AC_DEFAULT_WINDOW_DIM) {
      23           22 :                 if (nextTask == nullptr ||
      24            6 :                     DataUnitSize(nextTask->hcclDataType) * nextTask->count > ctx_->windowSize / AC_DEFAULT_WINDOW_DIM) {
      25           10 :                     return RunAllGathervMC(opType, sendBuffer, recvBuffer, dataCount, dataType, strideLen, nullptr);
      26              :                 } else {
      27            6 :                     return RunAllGathervMC(opType, sendBuffer, recvBuffer, dataCount, dataType, strideLen, nextTask);
      28              :                 }
      29              :             }
      30            8 :             return RunAllGatherv(opType, sendBuffer, recvBuffer, dataCount, dataType, strideLen);
      31              :         }
      32            8 :         case CommAlgType::COMM_ALG_DOUBLE_RING: {
      33            8 :             return RunDoubleRingAllGather(opType, reinterpret_cast<u64>(sendBuffer), reinterpret_cast<u64>(recvBuffer),
      34            8 :                 dataCount, dataType);
      35              :         }
      36            0 :         default: {
      37            0 :             HCCL_ERROR("CommAlg %d is not supported.", ctx_->commAlg);
      38            0 :             return HCCL_E_NOT_SUPPORT;
      39              :         }
      40              :     }
      41              : }
      42              : 
      43            8 : HcclResult AicpuAllgather::RunAllGatherv(HcclReduceOp opType, void *sendBuffer, void *recvBuffer, u64 dataCount,
      44              :     HcclDataType dataType, u64 strideCnt)
      45              : {
      46            8 :     CHK_PTR_NULL(ctx_);
      47              : 
      48              :     // dataCount 为 gather前的数据量
      49            8 :     u64 windowSize = ctx_->windowSize;
      50            8 :     u32 unitSize = ctx_->unitSize;
      51            8 :     u64 maxCountPerLoop = windowSize / unitSize; // 中转内存单次最多能够接受的output count
      52              : 
      53            8 :     u8 *curInputPtr = static_cast<u8 *>(sendBuffer);
      54            8 :     u8 *curOutputPtr = static_cast<u8 *>(recvBuffer);
      55            8 :     u64 inputOffset = 0;
      56            8 :     u64 outputOffset = 0;
      57            8 :     u64 countLeft = dataCount;
      58              : 
      59            8 :     u64 displs[AC_MAX_RANK_NUM] = {0};
      60           72 :     for (u32 i = 0; i < ctx_->rankNum; i++) {
      61           64 :         displs[i] = i * strideCnt * ctx_->unitSize;
      62              :     }
      63              : 
      64            8 :     u32 loopIdx = 0;
      65           16 :     while (countLeft > 0) {
      66            8 :         curInputPtr += inputOffset;
      67            8 :         curOutputPtr += outputOffset;
      68            8 :         u64 curCount = (countLeft > maxCountPerLoop) ? maxCountPerLoop : countLeft;
      69            8 :         u64 curSize = curCount * unitSize; // 单位 byte
      70              : 
      71            8 :         HCCL_DEBUG("RunAllGatherv: loop %u, curInputPtr[%p], curOutputPtr[%p], curCount[%llu], curSize[%llu]",
      72              :             loopIdx++, curInputPtr, curOutputPtr, curCount, curSize);
      73              : 
      74              :         // 1. 片内数据拷贝 snd->win
      75            8 :         CHK_RET(TaskOrchestrator::SelfCpySnd2Win(curInputPtr, curSize, 0, 0, HCCL_REDUCE_RESERVED, dataType));
      76              :         // 2. 前同步
      77            8 :         CHK_RET(TaskOrchestrator::DoPreSync());
      78              : 
      79              :         // 缺省情况allgather时op_type没用,融合时aic设置op_type为1时表示不需要本卡数据。
      80            8 :         if (opType != HCCL_REDUCE_PROD) {
      81            0 :             CHK_RET(TaskOrchestrator::SelfCpyWin2Rcv(curOutputPtr, curSize, 0, displs[ctx_->rankId],
      82              :                 HCCL_REDUCE_RESERVED, dataType));
      83              :         }
      84              : 
      85              :         // 3. 跨片SDMA,其他win->当前rcv buff
      86            8 :         CHK_RET(
      87              :             TaskOrchestrator::IpcCpyWin2Rcv(curOutputPtr, curSize, nullptr, displs, HCCL_REDUCE_RESERVED, dataType));
      88              : 
      89              :         // 4. 后同步
      90            8 :         CHK_RET(TaskOrchestrator::DoPostSync());
      91              : 
      92            8 :         CHK_RET(TaskOrchestrator::LaunchTasks());
      93              : 
      94            8 :         countLeft -= curCount;
      95            8 :         inputOffset = curSize;
      96            8 :         outputOffset = curSize;
      97              :     }
      98            8 :     return HCCL_SUCCESS;
      99              : }
     100              : 
     101           22 : u64 AicpuAllgather::GetWindowOffset(u32 curTurnCnt, u64 curSize, u64 strideCnt, u64 recvBuffer)
     102              : {
     103              :     (void) recvBuffer;
     104           22 :     u64 windowOffset = 0;
     105           22 :     u64 bufferFlag = static_cast<uint64_t>(curTurnCnt % AC_DEFAULT_WINDOW_DIM);
     106           22 :     u64 recvOffset = (static_cast<uint64_t>(ctx_->rankId) * strideCnt * static_cast<uint64_t>(ctx_->unitSize)) % HCCL_COPY_ALIGN;
     107           22 :     u64 windowOffsetTmp = bufferFlag * (ctx_->windowSize / AC_DEFAULT_WINDOW_DIM / HCCL_COPY_ALIGN + 1) *
     108              :         HCCL_COPY_ALIGN + recvOffset;
     109           22 :     if ((bufferFlag == 0 && (recvOffset + curSize) < ctx_->windowSize / AC_DEFAULT_WINDOW_DIM) ||
     110           13 :         (bufferFlag == 1 && (windowOffsetTmp + curSize) < ctx_->windowSize)) {
     111           22 :         windowOffset = windowOffsetTmp;
     112              :     } else {
     113            0 :         windowOffset = bufferFlag * (ctx_->windowSize / AC_DEFAULT_WINDOW_DIM);
     114              :     }
     115           22 :     return windowOffset;
     116              : }
     117              : 
     118           16 : HcclResult AicpuAllgather::RunAllGathervMC(HcclReduceOp opType, void *sendBuffer, void *recvBuffer, u64 dataCount,
     119              :     HcclDataType dataType, u64 strideCnt, AivAicpuOpParam *nextTask)
     120              : {
     121           16 :     u64 displs[AC_MAX_RANK_NUM] = {0};
     122          144 :     for (u32 i = 0; i < ctx_->rankNum; i++) {
     123          128 :         displs[i] = i * strideCnt * ctx_->unitSize;
     124              :     }
     125              : 
     126           16 :     u64 curSize = ctx_->unitSize * dataCount;
     127           16 :     u64 windowOffset = 0;
     128           16 :     if (curSize < ctx_->windowSize / AC_DEFAULT_WINDOW_DIM) {
     129           16 :         windowOffset = GetWindowOffset(ctx_->curTurnCnt, curSize, strideCnt, reinterpret_cast<uint64_t>(recvBuffer));
     130              :     }
     131           16 :     HCCL_INFO("current task: windowSize[%llu], windowOffset[%llu], dataCount[%llu], "
     132              :         "curSize[%llu], strideCnt[%llu], gatherOut [%#llx]",
     133              :         ctx_->windowSize, windowOffset, dataCount, curSize, strideCnt, ctx_->gatherOut);
     134              : 
     135              :     // 1. 片内数据拷贝 snd->win
     136           16 :     if (isMCFirstCall) {
     137           10 :         CHK_RET(TaskOrchestrator::SelfCpySnd2Win(sendBuffer, curSize, 0, windowOffset, HCCL_REDUCE_RESERVED, dataType));
     138           10 :         isMCFirstCall = false;
     139              :     }
     140              : 
     141              :     // 2. 前同步
     142           16 :     CHK_RET(TaskOrchestrator::DoPreSync());
     143              : 
     144              :     // 缺省情况allgather时op_type没用,融合时aic设置op_type为1时表示不需要本卡数据。
     145           16 :     if (opType != HCCL_REDUCE_PROD) {
     146            0 :         CHK_RET(TaskOrchestrator::SelfCpyWin2Rcv(recvBuffer, curSize, windowOffset, displs[ctx_->rankId],
     147              :             HCCL_REDUCE_RESERVED, dataType));
     148              :     }
     149              : 
     150              :     // 3. 跨片SDMA,其他win->当前rcv buff
     151           16 :     u64 winOffsets[AC_MAX_RANK_NUM] = {0};
     152          144 :     for (u32 i = 0; i < ctx_->rankNum; i++) {
     153          128 :         winOffsets[i] = (ctx_->curTurnCnt % AC_DEFAULT_WINDOW_DIM) *
     154          128 :             (ctx_->windowSize / AC_DEFAULT_WINDOW_DIM / HCCL_COPY_ALIGN + 1) * HCCL_COPY_ALIGN +
     155          128 :             (i * strideCnt * ctx_->unitSize) % HCCL_COPY_ALIGN;
     156              :     }
     157           16 :     CHK_RET(TaskOrchestrator::IpcCpyWin2Rcv(recvBuffer, curSize, winOffsets, displs, HCCL_REDUCE_RESERVED, dataType));
     158              : 
     159           16 :     if (nextTask != nullptr) {
     160              :         // 1. 片内数据拷贝 snd->win
     161            6 :         u64 nextSize = DataUnitSize(nextTask->hcclDataType) * nextTask->count;
     162            6 :         u64 nextWindowOffset = 0;
     163            6 :         if (curSize < ctx_->windowSize / AC_DEFAULT_WINDOW_DIM) {
     164            6 :             nextWindowOffset = GetWindowOffset(ctx_->curTurnCnt + 1, nextSize, strideCnt, nextTask->recvBuffer);
     165              :         }
     166              : 
     167            6 :         HCCL_INFO("curTurnCnt[%u], windowSize[%llu], windowOffset[%llu], dataCount[%llu], nextSize[%llu]",
     168              :             ctx_->curTurnCnt, ctx_->windowSize, nextWindowOffset, nextTask->count, nextSize);
     169              : 
     170            6 :         CHK_RET(TaskOrchestrator::SelfCpySnd2Win(reinterpret_cast<void *>(nextTask->sendBuffer), nextSize, 0,
     171              :             nextWindowOffset, HCCL_REDUCE_RESERVED, nextTask->hcclDataType));
     172              :     } else {
     173           10 :         isMCFirstCall = true;
     174              :     }
     175              : 
     176              :     // 4. 后同步
     177           16 :     CHK_RET(TaskOrchestrator::DoPostSync());
     178              : 
     179           16 :     CHK_RET(TaskOrchestrator::LaunchTasks());
     180              : 
     181           16 :     return HCCL_SUCCESS;
     182              : }
     183              : 
     184          112 : HcclResult AicpuAllgather::GenRingTask(HcclReduceOp opType, u64 sndAddr, u64 rcvAddr, u64 gatherSize,
     185              :     HcclDataType dataType, uint32_t streamId, bool isClockwise, uint32_t step, bool isWindowLast) const
     186              : {
     187          112 :     const u64 winIn = ctx_->rankInfo[rankId_].window + (isClockwise ? 0U : ctx_->windowSize / RING_NUM);
     188          112 :     const u64 winOut = ctx_->rankInfo[rankId_].windowOut + (isClockwise ? 0U : ctx_->windowSize / RING_NUM);
     189          112 :     const uint32_t preRankId = isClockwise ? (rankId_ + rankNum_ - 1U) % rankNum_ : (rankId_ + 1U) % rankNum_;
     190          112 :     const uint32_t postRankId = isClockwise ? (rankId_ + 1U) % rankNum_ : (rankId_ + rankNum_ - 1U) % rankNum_;
     191          112 :     const u64 preWinIn = ctx_->rankInfo[preRankId].window + (isClockwise ? 0U : ctx_->windowSize / RING_NUM);
     192          112 :     const u64 preWinOut = ctx_->rankInfo[preRankId].windowOut + (isClockwise ? 0U : ctx_->windowSize / RING_NUM);
     193          112 :     const bool evenStep = (step % 2U == 0U); // 2: 环上winIn winOut轮流接收, 奇数轮in->out, 偶数轮out->in
     194              : 
     195          112 :     HcclResult ret = HCCL_SUCCESS;
     196          112 :     if (step == 1U) { // 首轮send->winIn
     197           16 :         ret = AicpuDispatcher::CopyData(streamId, sndAddr, winIn, gatherSize, dataType, HCCL_REDUCE_RESERVED, rankId_);
     198           16 :         CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u send to clock winIn failed", turn_, step), ret);
     199              :     }
     200              :     // 片间同步 notify后卡 wait前卡
     201          112 :     ret = AicpuDispatcher::SignalRecord(streamId, postRankId, AicpuDispatcher::IPC, AicpuDispatcher::PRE_SYNC);
     202          112 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u notify post rank failed", turn_, step), ret);
     203          112 :     ret = AicpuDispatcher::SignalWait(streamId, preRankId, AicpuDispatcher::IPC, AicpuDispatcher::PRE_SYNC);
     204          112 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u wait pre rank failed", turn_, step), ret);
     205              : 
     206              :     // 片间memcpy 前卡window->recv
     207          112 :     auto recvBufAddr = rcvAddr + (isClockwise ? (rankId_ + rankNum_ - step) % rankNum_ : (rankId_ + step) % rankNum_) *
     208          112 :         ctx_->totalCnt * unitSize_;
     209          112 :     ret = AicpuDispatcher::CopyData(streamId, evenStep ? preWinOut : preWinIn, recvBufAddr, gatherSize,
     210              :         dataType, HCCL_REDUCE_RESERVED, preRankId);
     211          112 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u cpy pre window failed", turn_, step), ret);
     212              : 
     213          112 :     if (isClockwise) {
     214           56 :         if (!((step == rankNum_ - 1U) && isWindowLast)) {
     215           48 :             CHK_RET(AicpuDispatcher::SignalWait(streamId, (rankId_ + 1U) % rankNum_, AicpuDispatcher::NO_IPC,
     216              :                 AicpuDispatcher::POST_SYNC));
     217              :         }
     218              :         // ccore notify
     219           56 :         if ((step < rankNum_ - 1U) && isWindowLast) {
     220           48 :             ret = AicpuDispatcher::AddCcoreNotify(streamId, turn_ * (rankNum_ - 1U) + step);
     221           48 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u add ccore notify failed", turn_, step), ret);
     222              :         }
     223              :     } else {
     224           56 :         if (!((step == rankNum_ - 1U) && isWindowLast)) {
     225           48 :             CHK_RET(AicpuDispatcher::SignalRecord(streamId, (rankId_ + 1U) % rankNum_, AicpuDispatcher::NO_IPC,
     226              :                 AicpuDispatcher::POST_SYNC));
     227              :         }
     228              :     }
     229              :     // recv->windowout
     230          112 :     if (step < rankNum_ - 1U){
     231           96 :         ret = AicpuDispatcher::CopyData(streamId, recvBufAddr, evenStep ? winIn : winOut, gatherSize, dataType,
     232           96 :             HCCL_REDUCE_RESERVED, rankId_);
     233           96 :         CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u cpy pre window failed", turn_, step), ret);
     234              :     }
     235              : 
     236              :     // 片间同步 notify前卡 wait后卡
     237          112 :     ret = AicpuDispatcher::SignalRecord(streamId, preRankId, AicpuDispatcher::IPC, AicpuDispatcher::POST_SYNC);
     238          112 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u notify pre rank failed", turn_, step), ret);
     239          112 :     ret = AicpuDispatcher::SignalWait(streamId, postRankId, AicpuDispatcher::IPC, AicpuDispatcher::POST_SYNC);
     240          112 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u wait post rank failed", turn_, step), ret);
     241          112 :     return HCCL_SUCCESS;
     242              : }
     243              : 
     244            8 : HcclResult AicpuAllgather::RunDoubleRingAllGather(HcclReduceOp opType, u64 sendBuffer, u64 recvBuffer,
     245              :     u64 dataCount, HcclDataType dataType) const
     246              : {
     247            8 :     const u64 gatherSize = dataCount * unitSize_;
     248            8 :     if (gatherSize > ctx_->windowSize / RING_NUM) {
     249            0 :         HCCL_INFO("Tile gather size %lu max less than window size %lu/RING_NUM", gatherSize, ctx_->windowSize);
     250              :     }
     251            8 :     const u64 rankDataSize = ctx_->totalCnt * unitSize_;
     252              :     thread_local static u64 sndAddr[RING_NUM] = { 0UL };
     253              :     thread_local static u64 rcvAddr[RING_NUM] = { 0UL };
     254            8 :     if (turn_ == 0U) { // 首个tile时初始化snd rcv地址
     255            1 :         sndAddr[0] = sendBuffer;
     256            1 :         sndAddr[1] = sendBuffer + rankDataSize;
     257            1 :         rcvAddr[0] = recvBuffer;
     258            1 :         rcvAddr[1] = recvBuffer + rankDataSize;
     259              :     }
     260              : 
     261            8 :     HCCL_INFO("DR AllGather snd addr %p %p, rcv addr %p %p, size %lu", sndAddr[0], sndAddr[1], rcvAddr[0], rcvAddr[1],
     262              :         gatherSize);
     263            8 :     uint32_t mainStream = rankId_;
     264            8 :     uint32_t subStream = (rankId_ + 1U) % rankNum_;
     265            8 :     HcclResult ret = HCCL_SUCCESS;
     266              : 
     267            8 :     u64 maxCountPerLoop = ctx_->windowSize / RING_NUM / unitSize_; // 中转内存单次最多能够接受的output count
     268            8 :     u64 countLeft = dataCount;
     269            8 :     bool isWindowFirst = true;
     270            8 :     bool isWindowLast = false;
     271              :     // windowSize循环
     272            8 :     u32 loopIdx = 0;
     273           16 :     while (countLeft > 0) {
     274            8 :         u64 curCount = (countLeft > maxCountPerLoop) ? maxCountPerLoop : countLeft;
     275            8 :         u64 curSize = curCount * unitSize_; // 单位 byte
     276              : 
     277            8 :         HCCL_DEBUG("DR AllGather: loop %u, snd addr[%u %u], rcv addr[%u %u], curCount[%llu], curSize[%llu]",
     278              :             loopIdx++, sndAddr[0], sndAddr[1], rcvAddr[0], rcvAddr[1], curCount, curSize);
     279              : 
     280            8 :         sndAddr[1] -= curSize;
     281            8 :         rcvAddr[1] -= curSize; // 逆时针输出在执行前向上偏移
     282              : 
     283            8 :         isWindowLast = ((countLeft - curCount) == 0);
     284              : 
     285              :         // 顺、逆时针各平移ranknum-1次
     286           64 :         for (uint32_t step = 1U; step <= rankNum_ - 1U; step++) {
     287           56 :             if (isWindowFirst) {
     288              :                 // ccore wait
     289           56 :                 u64 waitAddr = ctx_->workSpaceAddr + ctx_->notifyOff + offsetof(AivAicpuOpParam, sendCnt);
     290           56 :                 ret = AicpuDispatcher::AddCcoreWait(mainStream, waitAddr, turn_ * (rankNum_ - 1U) + step,
     291           56 :                     (turn_ + 1U >= ctx_->totalTurnCnt) && (step == rankNum_ - 1U));
     292           56 :                 CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u add ccore wait failed", turn_, step), ret);
     293              :             }
     294              : 
     295              :             // 主->从
     296           56 :             CHK_RET(
     297              :                 AicpuDispatcher::SignalRecord(mainStream, subStream, AicpuDispatcher::NO_IPC, AicpuDispatcher::PRE_SYNC));
     298           56 :             CHK_RET(AicpuDispatcher::SignalWait(subStream, subStream, AicpuDispatcher::NO_IPC, AicpuDispatcher::PRE_SYNC));
     299              : 
     300              :             // 顺时针环
     301           56 :             CHK_RET(GenRingTask(opType, sndAddr[0], rcvAddr[0], curSize, dataType, mainStream, true, step, isWindowLast));
     302              : 
     303              :             // 逆时针环
     304           56 :             CHK_RET(GenRingTask(opType, sndAddr[1], rcvAddr[1], curSize, dataType, subStream, false, step, isWindowLast));
     305              : 
     306              :             // 缺省情况allgather时op_type没用,融合时aic设置op_type为1时表示不需要本卡数据。
     307           56 :             if ((step == rankNum_ - 1U) && isWindowLast) { // 拷贝全量本卡直接从send->recv
     308            8 :                 if (opType != HCCL_REDUCE_PROD) {
     309            0 :                     ret = AicpuDispatcher::CopyData(mainStream, sendBuffer, recvBuffer + rankId_ * rankDataSize, rankDataSize,
     310            0 :                         dataType, HCCL_REDUCE_RESERVED, rankId_);
     311            0 :                     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u send to recv winIn failed", turn_, step), ret);
     312              :                 }
     313              : 
     314              :                 // 从->主
     315            8 :                 CHK_RET(
     316              :                     AicpuDispatcher::SignalRecord(subStream, subStream, AicpuDispatcher::NO_IPC, AicpuDispatcher::POST_SYNC));
     317            8 :                 CHK_RET(
     318              :                     AicpuDispatcher::SignalWait(mainStream, subStream, AicpuDispatcher::NO_IPC, AicpuDispatcher::POST_SYNC));
     319              : 
     320            8 :                 ret = TaskOrchestrator::AddBarrier(mainStream, rankId_, rankNum_);
     321            8 :                 CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u add barrier failed.", turn_, step), ret);
     322              : 
     323              :                 // ccore notify 非step7由GenRingTask处理AddCcoreNotify
     324            8 :                 ret = AicpuDispatcher::AddCcoreNotify(mainStream, turn_ * (rankNum_ - 1U) + step);
     325            8 :                 CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Turn %u step %u add ccore notify failed", turn_, step), ret);
     326              :             }
     327              :         }
     328            8 :         isWindowFirst = false;
     329            8 :         countLeft -= curCount;
     330            8 :         sndAddr[0] += curSize;
     331            8 :         rcvAddr[0] += curSize; // 顺时针输出在执行后向下偏移
     332              :     }
     333              : 
     334            8 :     ret = TaskOrchestrator::LaunchTasks();
     335            8 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("Launch tasks failed"), ret);
     336            8 :     return HCCL_SUCCESS;
     337              : }
        

Generated by: LCOV version 2.0-1