LCOV - code coverage report
Current view: top level - legacy/ascend910/platform/task - dispatcher_aicpu.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 48.7 % 789 384
Test Date: 2026-08-18 17:47:01 Functions: 77.4 % 31 24

            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 <memory>
      12              : #include "hccl_common.h"
      13              : #include "stream_pub.h"
      14              : #include "aicpu/aicpu_hccl_sqcqv1.h"
      15              : #include "aicpu/aicpu_hccl_sqcqv2.h"
      16              : #include "config_plf_log.h"
      17              : #include "dlhal_function.h"
      18              : #include "adapter_hal_pub.h"
      19              : #include "dispatcher_aicpu.h"
      20              : 
      21              : namespace hccl {
      22              : constexpr uint64_t NANOSECOND_TO_SECOND = 1000000000U;
      23              : constexpr uint16_t TURN_LEFT_SHIFT_BIT = 16;
      24              : constexpr uint32_t HCCL_PER_LAUNCH_SQE_CNT = 128U; // 每编排N个SQE,做一次launchtask
      25              : 
      26              : #ifdef __cplusplus
      27              : extern "C" {
      28              : #endif // __cplusplus
      29              : HcclResult
      30           11 : HcclDispatcherAicpuInit(HcclDispatcher* dispatcher, const u32 devPhyId, uint32_t hcclQos, DispatcherType type)
      31              : {
      32           11 :     CHK_PTR_NULL(dispatcher);
      33           11 :     DispatcherPub* pDispatcher = nullptr;
      34           11 :     if (type == DispatcherType::DISPATCHER_AICPU) {
      35           11 :         pDispatcher = new (std::nothrow) DispatcherAiCpu(devPhyId);
      36           11 :         pDispatcher->SetHcclQos(hcclQos);
      37           11 :         pDispatcher->SetMpamid(0);
      38           11 :         HCCL_INFO("HcclDispatcherAicpuInit hcclQos = %u", pDispatcher->GetHcclQos());
      39              :     } else {
      40            0 :         HCCL_ERROR("[HcclCommAicpu][HcclDispatcherInit] Not support the dispatcher type[%d]", type);
      41            0 :         return HCCL_E_NOT_SUPPORT;
      42              :     }
      43           11 :     CHK_PTR_NULL(pDispatcher);
      44           11 :     HcclResult ret = pDispatcher->Init();
      45           11 :     if (ret != HCCL_SUCCESS) {
      46            0 :         HCCL_ERROR("[HcclCommAicpu][HcclDispatcherInit] Dispatcher init failed, type[%d]", type);
      47            0 :         delete pDispatcher;
      48            0 :         pDispatcher = nullptr;
      49            0 :         return ret;
      50              :     }
      51           11 :     *dispatcher = pDispatcher;
      52           11 :     return HCCL_SUCCESS;
      53              : }
      54              : #ifdef __cplusplus
      55              : }
      56              : #endif // __cplusplus
      57              : 
      58          450 : DispatcherAiCpu::DispatcherAiCpu(const u32 devPhyId) // deprecated
      59          450 :     : DispatcherPub(INVALID_INT)
      60              : {
      61          450 :     aicpuInfo_.devId = devPhyId;
      62          450 : }
      63              : 
      64          900 : DispatcherAiCpu::~DispatcherAiCpu() {}
      65              : 
      66          449 : HcclResult DispatcherAiCpu::Init()
      67              : {
      68          449 :     CHK_RET(DlHalFunction::GetInstance().DlHalFunctionInit());
      69          449 :     CHK_RET(hrtHalGetDeviceType(aicpuInfo_.devId, aicpuInfo_.devType));
      70          449 :     CHK_RET(hrtHalGetDeviceInfo(
      71              :         aicpuInfo_.devId, MODULE_TYPE_SYSTEM, INFO_TYPE_PHY_CHIP_ID, reinterpret_cast<int64_t*>(&aicpuInfo_.chipId)));
      72              : 
      73          449 :     if (aicpuInfo_.devType == DevType::DEV_TYPE_310P1 || aicpuInfo_.devType == DevType::DEV_TYPE_310P3) {
      74            0 :         addOneNotifyWaitSqe_ = AddOneNotifyWaitSqeV2;
      75            0 :         addOneRecordSqe_ = AddOneRecordSqeV2;
      76            0 :         addOneWriteValueRecordSqe_ = AddOneWriteValueRecordSqeV2;
      77            0 :         addOneMemcpySqe_ = AddOneMemcpySqeV2;
      78            0 :         addOneEventResetSqe_ = AddOneEventResetSqeV2;
      79            0 :         addOneEventRecordSqe_ = AddOneEventRecordSqeV2;
      80            0 :         addOneEventWaitSqe_ = AddOneEventWaitSqeV2;
      81              :     } else {
      82          449 :         addOneNotifyWaitSqe_ = AddOneNotifyWaitSqeV1;
      83          449 :         addOneRecordSqe_ = AddOneRecordSqeV1;
      84          449 :         addOneWriteValueRecordSqe_ = AddOneWriteValueRecordSqeV1;
      85          449 :         addOneMemcpySqe_ = AddOneMemcpySqeV1;
      86          449 :         addOneEventResetSqe_ = AddOneEventResetSqeV1;
      87          449 :         addOneEventRecordSqe_ = AddOneEventRecordSqeV1;
      88          449 :         addOneEventWaitSqe_ = AddOneEventWaitSqeV1;
      89          449 :         addOneRdmaDbSendSqe_ = AddOneRdmaDbSendSqeV1;
      90          449 :         addOneFlipPlaceHolderSqe_ = AddOneFlipPlaceHolderSqeV1;
      91          449 :         addOneCacheMemcpyPlaceHolderSqe_ = AddOneCacheMemcpyPlaceHolderSqeV1;
      92          449 :         addOneCacheNotifyWaitPlaceholderSqe_ = AddOneCacheNotifyWaitPlaceholderSqeV1;
      93          449 :         addOneCacheNotifyRecordPlaceholderSqe_ = AddOneCacheNotifyRecordPlaceholderSqeV1;
      94          449 :         addOneCacheWriteValuePlaceholderSqe_ = AddOneCacheWriteValuePlaceholderSqeV1;
      95          449 :         addOneCacheMemcpyRecordPlaceholderSqe_ = AddOneCacheMemcpyRecordPlaceholderSqeV1;
      96          449 :         CHK_PTR_NULL(addOneRdmaDbSendSqe_);
      97          449 :         CHK_PTR_NULL(addOneFlipPlaceHolderSqe_);
      98          449 :         CHK_PTR_NULL(addOneCacheMemcpyPlaceHolderSqe_);
      99          449 :         CHK_PTR_NULL(addOneCacheNotifyWaitPlaceholderSqe_);
     100          449 :         CHK_PTR_NULL(addOneCacheNotifyRecordPlaceholderSqe_);
     101          449 :         CHK_PTR_NULL(addOneCacheWriteValuePlaceholderSqe_);
     102          449 :         CHK_PTR_NULL(addOneCacheMemcpyRecordPlaceholderSqe_);
     103              :     }
     104              : 
     105          449 :     CHK_PTR_NULL(addOneNotifyWaitSqe_);
     106          449 :     CHK_PTR_NULL(addOneRecordSqe_);
     107          449 :     CHK_PTR_NULL(addOneWriteValueRecordSqe_);
     108          449 :     CHK_PTR_NULL(addOneMemcpySqe_);
     109          449 :     CHK_PTR_NULL(addOneEventResetSqe_);
     110          449 :     CHK_PTR_NULL(addOneEventRecordSqe_);
     111          449 :     CHK_PTR_NULL(addOneEventWaitSqe_);
     112              : 
     113          449 :     CHK_RET(GetNotifyMaxWaitTime());
     114          449 :     notifySize_ = (aicpuInfo_.devType == DevType::DEV_TYPE_910B || aicpuInfo_.devType == DevType::DEV_TYPE_910_93) ?
     115              :                       4 :
     116              :                       8; // 和hrtGetNotifySize接口保持一致,910B和910_93的notify寄存器大小为4,其他芯片为8
     117          449 :     InitTimeOutConfig();
     118          449 :     HCCL_INFO(
     119              :         "%s success, devId:%u, devType:%d, chipId:%lld", __func__, aicpuInfo_.devId, aicpuInfo_.devType,
     120              :         aicpuInfo_.chipId);
     121          449 :     return HCCL_SUCCESS;
     122              : }
     123              : 
     124            1 : HcclResult DispatcherAiCpu::WaitValue(hccl::Stream& stream, u64 waitAddr, u64 valueAddr, bool reset)
     125              : {
     126            1 :     u32 turnNum = *(reinterpret_cast<u32*>(static_cast<uintptr_t>(valueAddr)));
     127            1 :     HCCL_DEBUG("[DispatcherAiCpu][WaitValue] turnNum %u", turnNum);
     128            1 :     uint8_t* sqeBuffer = nullptr;
     129            1 :     uint8_t* sqeTypeAddr = nullptr;
     130            1 :     uint8_t* sqeDfxInfoAddr = nullptr;
     131            1 :     uint16_t taskId = 0U;
     132            1 :     CHK_RET(stream.GetNextSqeBufferAddr(sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     133              :     const HcclComStreamInfo* streamInfo;
     134            1 :     CHK_RET(stream.GetStreamInfo(streamInfo));
     135            1 :     AddOneWaitStartSqe(
     136            1 :         streamInfo->actualStreamId, taskId, waitAddr, valueAddr, reset,
     137              :         reinterpret_cast<rtStarsCcoreWaitStartSqe_t*>(sqeBuffer), sqeTypeAddr);
     138            1 :     HcclSqeContext* sqeCtx = stream.GetSqeContextPtr();
     139            1 :     if (sqeCtx == nullptr) {
     140            0 :         HCCL_ERROR("[DispatcherAiCpu][WaitValue] AddCcoreWait sqeCtx is nullptr");
     141            0 :         return HCCL_E_INTERNAL;
     142              :     }
     143            1 :     sqeCtx->buffer.addInfo[taskId % hccl::HCCL_SQE_MAX_CNT]
     144            1 :         = ((turnNum << TURN_LEFT_SHIFT_BIT) + static_cast<uint32_t>(reset));
     145            1 :     return HCCL_SUCCESS;
     146              : }
     147              : 
     148            1 : HcclResult DispatcherAiCpu::WriteValue(hccl::Stream& stream, u64 writeAddr, u64 valueAddr)
     149              : {
     150            1 :     u32 turnNum = *(reinterpret_cast<u32*>(static_cast<uintptr_t>(valueAddr)));
     151            1 :     HCCL_DEBUG("[DispatcherAiCpu][WriteValue] turnNum %u", turnNum);
     152            1 :     uint8_t* sqeBuffer = nullptr;
     153            1 :     uint8_t* sqeTypeAddr = nullptr;
     154            1 :     uint8_t* sqeDfxInfoAddr = nullptr;
     155            1 :     uint16_t taskId = 0U;
     156            1 :     CHK_RET(stream.GetNextSqeBufferAddr(sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     157              :     const HcclComStreamInfo* streamInfo;
     158            1 :     CHK_RET(stream.GetStreamInfo(streamInfo));
     159            1 :     AddOneWriteValueStartSqe(
     160            1 :         streamInfo->actualStreamId, taskId, writeAddr, valueAddr,
     161              :         reinterpret_cast<rtStarsCcoreWriteValueSqe_t*>(sqeBuffer), sqeTypeAddr);
     162            1 :     HcclSqeContext* sqeCtx = stream.GetSqeContextPtr();
     163            1 :     if (sqeCtx == nullptr) {
     164            0 :         HCCL_ERROR("[DispatcherAiCpu][WriteValue] AddCcoreNotify sqeCtx is nullptr");
     165            0 :         return HCCL_E_INTERNAL;
     166              :     }
     167            1 :     sqeCtx->buffer.addInfo[taskId % hccl::HCCL_SQE_MAX_CNT] = turnNum;
     168            1 :     return HCCL_SUCCESS;
     169              : }
     170              : 
     171            2 : HcclResult DispatcherAiCpu::SignalRecord(
     172              :     [[maybe_unused]] HcclRtNotify signal, hccl::Stream& stream, u32 userRank, [[maybe_unused]] u64 offset,
     173              :     [[maybe_unused]] s32 stage, bool inchip, u64 signalAddr, u32 notifyId)
     174              : {
     175            2 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
     176            2 :     uint8_t* sqeBuffer = nullptr;
     177            2 :     uint8_t* sqeTypeAddr = nullptr;
     178            2 :     uint8_t* sqeDfxInfoAddr = nullptr;
     179            2 :     uint16_t taskId = 0U;
     180            2 :     CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     181            2 :     AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
     182            2 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
     183            2 :     dfxInfo->remoteRank = userRank;
     184            2 :     dfxInfo->notifyId = notifyId;
     185              : 
     186              :     // 检查是否需要生成cache-write placeholder
     187            2 :     if (isPlaceholder_) {
     188              :         // 只有使能alltoallv类算子的aicpu cache才需要cache-write placeholder
     189            0 :         CHK_PRT_RET(
     190              :             !(needAddSqe_ && isAlltoallv_),
     191              :             HCCL_ERROR(
     192              :                 "[DispatcherAiCpu][SignalRecord] isPlaceholder_[%u]"
     193              :                 "needAddSqe_[%u] isAlltoallv_[%u]",
     194              :                 isPlaceholder_, needAddSqe_, isAlltoallv_),
     195              :             HCCL_E_INTERNAL);
     196              : 
     197              :         // 只有p2p的SignalRecord才需要cache-write placeholder
     198              :         // 不需要为inchip场景下LocalNotify::Post的SignalRecord调用addOneCacheNotifyRecordPlaceholderSqe_生成cache-notify
     199              :         // placeholder
     200            0 :         CHK_PRT_RET(
     201              :             inchip,
     202              :             HCCL_ERROR("[DispatcherAiCpu][SignalRecord] isPlaceholder_[%u], inchip[%u]", isPlaceholder_, inchip),
     203              :             HCCL_E_INTERNAL);
     204              : 
     205            0 :         addOneCacheWriteValuePlaceholderSqe_(streamInfo.actualStreamId, taskId, signalAddr, sqeBuffer, sqeTypeAddr);
     206            0 :         HCCL_INFO("%s generate cache-write placeholder for signal record", __func__);
     207              :     } else { // 正常生成SQE
     208            2 :         if (inchip) {
     209            1 :             addOneRecordSqe_(streamInfo.actualStreamId, taskId, notifyId, sqeBuffer, sqeTypeAddr);
     210              :         } else {
     211            1 :             addOneWriteValueRecordSqe_(streamInfo.actualStreamId, taskId, signalAddr, sqeBuffer, sqeTypeAddr);
     212              :         }
     213              :     }
     214              : 
     215            2 :     PLF_CONFIG_INFO(
     216              :         PLF_TASK, "%s para: streamId[%d] remoteRank[%u] inchip[%d] devType[%d] notifyId[%u]", __func__,
     217              :         streamInfo.actualStreamId, userRank, inchip, aicpuInfo_.devType, notifyId);
     218            2 :     return HCCL_SUCCESS;
     219              : }
     220              : 
     221            1 : HcclResult DispatcherAiCpu::SignalRecord(
     222              :     hccl::DeviceMem& dst, hccl::DeviceMem& src, hccl::Stream& stream, u32 remoteUserRank, hccl::LinkType inLinkType,
     223              :     u32 notifyId)
     224              : {
     225              :     // 参数有效性检查
     226            1 :     CHK_PRT_RET(src.size() == 0, HCCL_INFO("%s src size is 0, not need copy", __func__), HCCL_SUCCESS);
     227            1 :     CHK_PRT_RET(src == dst, HCCL_INFO("%s src and dst is same, not need copy", __func__), HCCL_SUCCESS);
     228            1 :     CHK_PRT_RET(
     229              :         dst.size() < src.size(),
     230              :         HCCL_ERROR(
     231              :             "%s The size of dst is smaller than that of src. dst addr:%p, dst size:%llu, src addr:%p, "
     232              :             "src size:%llu",
     233              :             __func__, dst.ptr(), dst.size(), src.ptr(), src.size()),
     234              :         HCCL_E_PARA);
     235            1 :     CHK_PRT_RET(
     236              :         src.size() != notifySize_,
     237              :         HCCL_ERROR(
     238              :             "%s src size[%llu] should be %llu in devType[%d]", __func__, src.size(), notifySize_, aicpuInfo_.devType),
     239              :         HCCL_E_PARA);
     240              : 
     241            1 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
     242            1 :     uint8_t* sqeBuffer = nullptr;
     243            1 :     uint8_t* sqeTypeAddr = nullptr;
     244            1 :     uint8_t* sqeDfxInfoAddr = nullptr;
     245            1 :     uint16_t taskId = 0U;
     246            1 :     aclrtReduceKind rtReduceOp = RK_MAP_TABLE[HCCL_REDUCE_RESERVED];
     247            1 :     uint8_t linkType = static_cast<uint8_t>(inLinkType);
     248              : 
     249            1 :     CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     250            1 :     AicpuDfxInfo* const dfxInfo = reinterpret_cast<AicpuDfxInfo* const>(sqeDfxInfoAddr);
     251            1 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
     252            1 :     dfxInfo->remoteRank = remoteUserRank;
     253            1 :     dfxInfo->notifyId = notifyId;
     254              : 
     255              :     // 检查是否需要生成cache-memcpy-record placeholder
     256            1 :     if (isPlaceholder_) {
     257              :         // 只有使能alltoallv类算子的aicpu cache才需要cache-memcpy-record placeholder
     258            0 :         CHK_PRT_RET(
     259              :             !(needAddSqe_ && isAlltoallv_),
     260              :             HCCL_ERROR(
     261              :                 "[DispatcherAiCpu][SignalRecord] isPlaceholder_[%u]"
     262              :                 "needAddSqe_[%u] isAlltoallv_[%u]",
     263              :                 isPlaceholder_, needAddSqe_, isAlltoallv_),
     264              :             HCCL_E_INTERNAL);
     265              : 
     266            0 :         addOneCacheMemcpyRecordPlaceholderSqe_(
     267            0 :             streamInfo.actualStreamId, taskId, src.ptr(), src.size(), ACL_FLOAT, rtReduceOp, dst.ptr(), 0,
     268              :             aicpuInfo_.ssid, aicpuInfo_.devId, aicpuInfo_.overflowAddr, linkType, sqeBuffer, sqeTypeAddr,
     269              :             SDMA_QOS_DEFAULT);
     270            0 :         HCCL_INFO("%s generate cache-memcpy-record placeholder for signal record", __func__);
     271              :     } else { // 正常生成memcpy record SQE
     272            3 :         addOneMemcpySqe_(
     273            1 :             streamInfo.actualStreamId, taskId, src.ptr(), src.size(), ACL_FLOAT, rtReduceOp, dst.ptr(), 0,
     274              :             aicpuInfo_.ssid, aicpuInfo_.devId, aicpuInfo_.overflowAddr, linkType, sqeBuffer, sqeTypeAddr,
     275              :             SDMA_QOS_DEFAULT);
     276              :     }
     277              : 
     278            1 :     PLF_CONFIG_INFO(
     279              :         PLF_TASK,
     280              :         "%s para: linkType[%u] srcPtr[%p] srcSize[%llu] dstPtr[%p] taskId[%u] streamId[%u] remoteRank[%u] notifyId[%u] "
     281              :         "hcclQos[%u]",
     282              :         __func__, linkType, src.ptr(), src.size(), dst.ptr(), taskId, streamInfo.actualStreamId, remoteUserRank,
     283              :         notifyId, SDMA_QOS_DEFAULT);
     284            1 :     return HCCL_SUCCESS;
     285              : }
     286              : 
     287            3 : HcclResult DispatcherAiCpu::SignalWait(
     288              :     [[maybe_unused]] HcclRtNotify signal, Stream& stream, u32 userRank, u32 remoteUserRank, [[maybe_unused]] s32 stage,
     289              :     bool inchip, u32 notifyId, u32 timeOut)
     290              : {
     291            3 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
     292            3 :     uint8_t* sqeBuffer = nullptr;
     293            3 :     uint8_t* sqeTypeAddr = nullptr;
     294            3 :     uint8_t* sqeDfxInfoAddr = nullptr;
     295            3 :     uint16_t taskId = 0U;
     296            3 :     CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     297            3 :     AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
     298            3 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
     299            3 :     dfxInfo->remoteRank = remoteUserRank;
     300            3 :     dfxInfo->notifyId = notifyId;
     301              : 
     302            3 :     dfxTimeOutConfig_.sqeTimeOutTimeOut = timeOut < notifyMaxWaitTime_ ? timeOut : dfxTimeOutConfig_.sqeTimeOutTimeOut;
     303              :     // 检查是否需要生成cache-notify placeholder
     304            3 :     if (isPlaceholder_) {
     305              :         // 只有使能alltoallv类算子的aicpu cache才需要cache-notify placeholder
     306            0 :         CHK_PRT_RET(
     307              :             !(needAddSqe_ && isAlltoallv_),
     308              :             HCCL_ERROR(
     309              :                 "[DispatcherAiCpu][SignalWait] isPlaceholder_[%u]"
     310              :                 "needAddSqe_[%u] isAlltoallv_[%u]",
     311              :                 isPlaceholder_, needAddSqe_, isAlltoallv_),
     312              :             HCCL_E_INTERNAL);
     313              : 
     314              :         // 只有A3下才会使能alltoallv aicpu cache并需要cache-notify placeholder
     315            0 :         CHK_PRT_RET(
     316              :             !(inchip
     317              :               || (aicpuInfo_.devType != DevType::DEV_TYPE_310P1 && aicpuInfo_.devType != DevType::DEV_TYPE_310P3)),
     318              :             HCCL_ERROR(
     319              :                 "[DispatcherAiCpu][SignalWait] isPlaceholder_[%u] inchip[%u] devType[%u]", isPlaceholder_, inchip,
     320              :                 aicpuInfo_.devType),
     321              :             HCCL_E_INTERNAL);
     322              : 
     323            0 :         addOneCacheNotifyWaitPlaceholderSqe_(
     324            0 :             streamInfo.actualStreamId, taskId, notifyId, sqeBuffer, sqeTypeAddr, dfxTimeOutConfig_);
     325            0 :         HCCL_INFO("%s generate cache-notify placeholder for signal wait", __func__);
     326              :     } else { // 正常生成SQE
     327            3 :         if (inchip
     328            2 :             || (aicpuInfo_.devType != DevType::DEV_TYPE_310P1 && aicpuInfo_.devType != DevType::DEV_TYPE_310P3)) {
     329            3 :             addOneNotifyWaitSqe_(
     330            3 :                 streamInfo.actualStreamId, taskId, notifyId, sqeBuffer, sqeTypeAddr, dfxTimeOutConfig_);
     331              :         } else {
     332            0 :             u32 notifyRevisedOffset = 15U; // eventid偏移15位后为1
     333            0 :             u32 notifyGetEventId = 0x3FFU; // 取低15位
     334            0 :             if ((notifyId >> notifyRevisedOffset) != 0) {
     335            0 :                 addOneEventWaitSqe_(
     336            0 :                     streamInfo.actualStreamId, (notifyId & notifyGetEventId), taskId, sqeBuffer, sqeTypeAddr);
     337              : 
     338            0 :                 uint8_t* sqeBuffer1 = nullptr;
     339            0 :                 uint8_t* sqeTypeAddr1 = nullptr;
     340            0 :                 uint8_t* sqeDfxInfoAddr1 = nullptr;
     341            0 :                 CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer1, sqeTypeAddr1, sqeDfxInfoAddr1, taskId));
     342            0 :                 AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr1;
     343            0 :                 dfxInfo->opRingBufferIdx = opRingBufferIdx_;
     344            0 :                 dfxInfo->remoteRank = INVALID_VALUE_RANKID;
     345              : 
     346            0 :                 u64 addr = 0;
     347            0 :                 addOneEventResetSqe_(
     348            0 :                     streamInfo.actualStreamId, (notifyId & notifyGetEventId), taskId, aicpuInfo_.devId, 0, addr,
     349              :                     sqeBuffer1, sqeTypeAddr1);
     350              :             } else {
     351            0 :                 HCCL_WARNING("%s SignalWait id is not event, please check %d", __func__, notifyId);
     352              :             }
     353              :         }
     354              :     }
     355              : 
     356            3 :     PLF_CONFIG_INFO(
     357              :         PLF_TASK,
     358              :         "%s para: streamId[%u] userRank[%u] remoteRank[%u] inchip[%d] devType[%d] notifyId[%u] sqeTimeOutTimeOut[%llu]",
     359              :         __func__, streamInfo.actualStreamId, userRank, remoteUserRank, inchip, aicpuInfo_.devType, notifyId,
     360              :         dfxTimeOutConfig_.sqeTimeOutTimeOut);
     361            3 :     return HCCL_SUCCESS;
     362              : }
     363              : 
     364            3 : HcclResult DispatcherAiCpu::MemcpyAsync(
     365              :     hccl::DeviceMem& dst, const hccl::DeviceMem& src, hccl::Stream& stream, u32 remoteUserRank,
     366              :     hccl::LinkType inLinkType)
     367              : {
     368              :     // 检查是否需要生成cache-memcpy placeholder
     369            3 :     if (isPlaceholder_) {
     370              :         // 只有零长拷贝才需要cache-memcpy placeholder
     371            0 :         CHK_PRT_RET(
     372              :             src.size() != 0,
     373              :             HCCL_ERROR("[DispatcherAiCpu][MemcpyAsync] isPlaceholder_[%u] src.size[%llu]", isPlaceholder_, src.size()),
     374              :             HCCL_E_INTERNAL);
     375              : 
     376              :         // 只有使能alltoallv类算子的aicpu cache才需要cache-memcpy placeholder
     377            0 :         CHK_PRT_RET(
     378              :             !(needAddSqe_ && isAlltoallv_),
     379              :             HCCL_ERROR(
     380              :                 "[DispatcherAiCpu][MemcpyAsync] isPlaceholder_[%u]"
     381              :                 "needAddSqe_[%u] isAlltoallv_[%u]",
     382              :                 isPlaceholder_, needAddSqe_, isAlltoallv_),
     383              :             HCCL_E_INTERNAL);
     384              : 
     385              :         // 准备SQE, sqeType, dfxInfo
     386            0 :         uint8_t* sqeBuffer = nullptr;
     387            0 :         uint8_t* sqeTypeAddr = nullptr;
     388            0 :         uint8_t* sqeDfxInfoAddr = nullptr;
     389            0 :         uint16_t taskId = 0U;
     390            0 :         CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     391              : 
     392              :         // 生成cache-memcpy placeholder SQE, 并设置sqeType
     393            0 :         CHK_PTR_NULL(addOneCacheMemcpyPlaceHolderSqe_);
     394            0 :         const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
     395            0 :         addOneCacheMemcpyPlaceHolderSqe_(
     396            0 :             streamInfo.actualStreamId, taskId, src.ptr(), dst.ptr(), static_cast<uint8_t>(inLinkType), sqeBuffer,
     397              :             sqeTypeAddr, hcclQos_);
     398              : 
     399              :         // 设置dfxInfo
     400            0 :         AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
     401            0 :         dfxInfo->opRingBufferIdx = opRingBufferIdx_;
     402            0 :         dfxInfo->remoteRank = remoteUserRank;
     403            0 :         dfxInfo->notifyId = INVALID_VALUE_RANKID;
     404              : 
     405            0 :         HCCL_INFO("%s capture zero-len memcpy for alltoallv, generate cache-memcpy placeholder sqe", __func__);
     406              : 
     407            0 :         return HCCL_SUCCESS;
     408              :     }
     409              : 
     410              :     // 参数有效性检查
     411            3 :     if (src.size() == 0) {
     412            0 :         HCCL_INFO("%s src memory size is 0, not need copy.", __func__);
     413            0 :         return HCCL_SUCCESS;
     414              :     }
     415              : 
     416            3 :     if (src == dst) {
     417            3 :         HCCL_INFO("%s src memory and dst memory is same, not need copy.", __func__);
     418            3 :         return HCCL_SUCCESS;
     419              :     }
     420              : 
     421            0 :     if (dst.size() < src.size()) {
     422            0 :         HCCL_ERROR(
     423              :             "%s The size of dst is smaller than that of src. dst addr[%p], dst size[%llu], "
     424              :             "src addr[%p], src size[%llu]",
     425              :             __func__, dst.ptr(), dst.size(), src.ptr(), src.size());
     426            0 :         return HCCL_E_PTR;
     427              :     }
     428            0 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
     429              : 
     430              :     // 将数据按4GB切分循环处理
     431            0 :     uint64_t spiltLoop = 0;
     432            0 :     uint64_t addrOffset = 0;
     433            0 :     uint64_t countSplit = 0;
     434            0 :     uint64_t countSize = src.size();
     435            0 :     uint8_t* sqeBuffer = nullptr;
     436            0 :     uint8_t* sqeTypeAddr = nullptr;
     437            0 :     uint8_t* sqeDfxInfoAddr = nullptr;
     438            0 :     uint16_t taskId = 0U;
     439            0 :     HcclReduceOp redOp = HCCL_REDUCE_RESERVED;
     440            0 :     aclrtReduceKind rtReduceOp = RK_MAP_TABLE[redOp];
     441              : 
     442            0 :     if (countSize > HCCL_SDMA_MAX_COUNT_4GB) {
     443            0 :         spiltLoop = (countSize % HCCL_SDMA_MAX_COUNT_4GB) ? (countSize / HCCL_SDMA_MAX_COUNT_4GB) :
     444            0 :                                                             ((countSize / HCCL_SDMA_MAX_COUNT_4GB) - 1);
     445            0 :         HCCL_INFO(
     446              :             "%s MemcpyAsync SDMA task countSize is bigger than 4GB"
     447              :             " and do segmentation splitloop[%llu]",
     448              :             __func__, spiltLoop);
     449              :     }
     450            0 :     uint8_t linkType = static_cast<uint8_t>(inLinkType);
     451            0 :     for (uint64_t index = 0; index <= spiltLoop; index++) {
     452            0 :         addrOffset = index * HCCL_SDMA_MAX_COUNT_4GB;
     453            0 :         countSplit = (index == spiltLoop) ? (countSize - index * HCCL_SDMA_MAX_COUNT_4GB) : (HCCL_SDMA_MAX_COUNT_4GB);
     454            0 :         void* srcSplit = static_cast<void*>(static_cast<char*>(const_cast<void*>(src.ptr())) + addrOffset);
     455            0 :         void* dstSplit = static_cast<void*>(static_cast<char*>(dst.ptr()) + addrOffset);
     456              : 
     457            0 :         CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     458            0 :         AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
     459            0 :         dfxInfo->opRingBufferIdx = opRingBufferIdx_;
     460            0 :         dfxInfo->remoteRank = remoteUserRank;
     461            0 :         dfxInfo->notifyId = INVALID_VALUE_RANKID;
     462            0 :         addOneMemcpySqe_(
     463            0 :             streamInfo.actualStreamId, taskId, srcSplit, countSplit, ACL_FLOAT, rtReduceOp, dstSplit, 0,
     464              :             aicpuInfo_.ssid, aicpuInfo_.devId, aicpuInfo_.overflowAddr, linkType, sqeBuffer, sqeTypeAddr, hcclQos_);
     465              : 
     466            0 :         PLF_CONFIG_INFO(
     467              :             PLF_TASK,
     468              :             "%s para: linkType[%u] srcSplit[%p] dstSplit[%p] countSplit[%llu] taskId[%u] streamId[%u] remoteRank[%u]",
     469              :             __func__, linkType, srcSplit, dstSplit, countSplit, taskId, streamInfo.actualStreamId, remoteUserRank);
     470              :     }
     471            0 :     return HCCL_SUCCESS;
     472              : }
     473              : 
     474            0 : HcclResult DispatcherAiCpu::ClearLaunchContext()
     475              : {
     476            0 :     HCCL_INFO("[DispatcherAiCpu][ClearLaunchContext] clear launch context");
     477              : 
     478            0 :     key_ = OpUnfoldKey();
     479            0 :     cachePtr_ = nullptr;
     480            0 :     userInputMemRanges_.clear();
     481            0 :     userOutputMemRanges_.clear();
     482            0 :     isAlltoallv_ = false;
     483            0 :     alltoallvMetadataPtr_ = nullptr;
     484            0 :     needAddSqe_ = false;
     485              : 
     486            0 :     return HCCL_SUCCESS;
     487              : }
     488              : 
     489            0 : HcclResult DispatcherAiCpu::SetLaunchContext(
     490              :     const OpUnfoldKey& key, OpUnfoldCache* cachePtr, const std::vector<OpUnfoldMemRange>& userInputMemRanges,
     491              :     const std::vector<OpUnfoldMemRange>& userOutputMemRanges, const bool isAlltoallv,
     492              :     const AlltoallvMetadata* alltoallvMetadataPtr)
     493              : {
     494            0 :     CHK_PTR_NULL(cachePtr);
     495              : 
     496            0 :     HCCL_INFO("[DispatcherAiCpu][SetLaunchContext] set launch context for key %s", key.GetKeyString().c_str());
     497              : 
     498            0 :     if (isAlltoallv) {
     499            0 :         CHK_PTR_NULL(alltoallvMetadataPtr);
     500            0 :         CHK_RET(alltoallvMetadataPtr->Check(false));
     501              :     }
     502              : 
     503            0 :     key_ = key;
     504            0 :     cachePtr_ = cachePtr;
     505            0 :     userInputMemRanges_ = userInputMemRanges;
     506            0 :     userOutputMemRanges_ = userOutputMemRanges;
     507            0 :     isAlltoallv_ = isAlltoallv;
     508            0 :     alltoallvMetadataPtr_ = alltoallvMetadataPtr;
     509            0 :     needAddSqe_ = true;
     510              : 
     511            0 :     return HCCL_SUCCESS;
     512              : }
     513              : 
     514            0 : HcclResult DispatcherAiCpu::LaunchNewTask(
     515              :     OpUnfoldCacheEntry* entryPtr, const std::vector<OpUnfoldMemRange>& userInputMemRanges,
     516              :     const std::vector<OpUnfoldMemRange>& userOutputMemRanges, Stream& mainStream, std::vector<Stream>& slaveStreams,
     517              :     const bool profL1Enable, const bool isAlltoallv, const AlltoallvMetadata& alltoallvMetadata,
     518              :     const AlltoallvSendRecvInfo& alltoallvSendRecvInfo)
     519              : {
     520              :     // 校验入参
     521            0 :     CHK_PTR_NULL(entryPtr);
     522            0 :     if (isAlltoallv) { // 注意: LaunchNewTask是在缓存命中时调用, 此时无launch context,
     523              :                        // 所以不能直接通过key_.opType来判断是否为alltoallv算子, 需要框架侧传入
     524            0 :         CHK_RET(alltoallvMetadata.Check(true));
     525            0 :         CHK_RET(alltoallvSendRecvInfo.Check());
     526              :     }
     527              : 
     528              :     // 准备SQE刷新需要的变量
     529            0 :     size_t sqeCount = 0;
     530            0 :     uint8_t* sqeArray = nullptr;
     531            0 :     uint8_t* sqeTypeArray = nullptr;
     532            0 :     AicpuDfxInfo* sqeDfxInfoArray = nullptr;
     533            0 :     Stream* streamPtr = nullptr;
     534            0 :     std::vector<FlipInfo> flipInfos;      // taskid==0且flipnum!=0的SQE索引, 即它们前面需要添加placeholder
     535            0 :     std::vector<uint64_t> profTimestamps; // 只有当profiling L1 enable时, 才需要记录各SQE的刷新时间
     536              : 
     537              :     // 准备placeholder需要的变量
     538              :     uint8_t placeholderSqe[HCCL_SQE_SIZE]; // placeholder SQE
     539              :     uint8_t placeholderSqeType;            // placeholder SQE type
     540            0 :     AicpuDfxInfo placeholderSqeDfxInfo;    // placeholder DfxInfo
     541            0 :     placeholderSqeDfxInfo.opRingBufferIdx = opRingBufferIdx_;
     542            0 :     placeholderSqeDfxInfo.remoteRank = INVALID_VALUE_RANKID;
     543            0 :     placeholderSqeDfxInfo.notifyId = INVALID_VALUE_RANKID;
     544            0 :     constexpr uint16_t flipPlaceholderTaskId = 0; // FlipPlaceholder的taskId一定为0
     545              : 
     546              :     // 下发多段SQE数组,SQE刷新与下发异步执行
     547            0 :     size_t sqeArrayCount = 0;
     548            0 :     CHK_RET(entryPtr->GetSqeArrayCount(sqeArrayCount));
     549            0 :     HCCL_INFO(
     550              :         "[DispatcherAiCpu][LaunchNewTask] launch new task for sqeArrayCount[%u] in the cache entry at 0x%016llx",
     551              :         sqeArrayCount, entryPtr);
     552            0 :     for (size_t arrayIdx = 0; arrayIdx < sqeArrayCount; ++arrayIdx) {
     553              :         // 刷新并获得对应信息 (之前下发到RTSQ的SQE正在异步被消费)
     554            0 :         CHK_RET(entryPtr->UpdateAndGetSqeArray(
     555              :             arrayIdx, userInputMemRanges, userOutputMemRanges, mainStream, slaveStreams, opRingBufferIdx_, sqeCount,
     556              :             &sqeArray, &sqeTypeArray, &sqeDfxInfoArray, &streamPtr, flipInfos, profL1Enable, profTimestamps,
     557              :             isAlltoallv, alltoallvMetadata, alltoallvSendRecvInfo));
     558              : 
     559              :         // Profiling timestamp的个数应该等于缓存的SQE个数 + flip placeholder个数
     560            0 :         CHK_PRT_RET(
     561              :             (!profL1Enable) && (profTimestamps.size() != 0),
     562              :             HCCL_ERROR(
     563              :                 "[DispatcherAiCpu][LaunchNewTask] profL1Enable[%u] profTimestamps.size[%u]", profL1Enable,
     564              :                 profTimestamps.size()),
     565              :             HCCL_E_INTERNAL);
     566            0 :         CHK_PRT_RET(
     567              :             profL1Enable && (profTimestamps.size() != (sqeCount + flipInfos.size())),
     568              :             HCCL_ERROR(
     569              :                 "[DispatcherAiCpu][LaunchNewTask] profL1Enable[%u] profTimestamps.size[%u] sqeCount[%u] "
     570              :                 "flipInfos.size[%u]",
     571              :                 profL1Enable, profTimestamps.size(), sqeCount, flipInfos.size()),
     572              :             HCCL_E_INTERNAL);
     573              : 
     574              :         // 打印缓存并下发的SQE内容for debug
     575              :         // 设置HCCL_DEBUG_CONFIG="task", 或者设置ASCEND_GLOBAL_LOG_LEVEL=0
     576            0 :         int32_t streamId = streamPtr->GetHcclStreamInfo().actualStreamId;
     577            0 :         if ((UNLIKELY(GetExternalInputDebugConfig() & PLF_TASK)) || UNLIKELY(HcclCheckLogLevel(HCCL_LOG_DEBUG))) {
     578            0 :             PLF_CONFIG_DEBUG(
     579              :                 PLF_TASK,
     580              :                 "[DispatcherAicpu][LaunchNewTask] dump content of %uth cached SQE array with %u cached SQEs and stream "
     581              :                 "id %u",
     582              :                 arrayIdx, sqeCount, streamId);
     583            0 :             for (size_t sqeIdx = 0; sqeIdx < sqeCount; ++sqeIdx) {
     584            0 :                 uint8_t* sqePtr = sqeArray + sqeIdx * HCCL_SQE_SIZE;
     585            0 :                 const uint8_t sqeType = sqeTypeArray[sqeIdx];
     586            0 :                 PLF_CONFIG_DEBUG(PLF_TASK, "[DispatcherAicpu][LaunchNewTask] %uth cached SQE", sqeIdx);
     587            0 :                 CHK_RET(OpUnfoldCache::DumpSqeContent(sqePtr, sqeType));
     588              : 
     589            0 :                 const AicpuDfxInfo& dfxinfo = sqeDfxInfoArray[sqeIdx];
     590            0 :                 PLF_CONFIG_DEBUG(
     591              :                     PLF_TASK,
     592              :                     "[DispatcherAicpu][LaunchNewTask] AicpuDfxInfo: remoteRank[%u] opRingBufferIdx[%u] notifyId[%u]",
     593              :                     dfxinfo.remoteRank, dfxinfo.opRingBufferIdx, dfxinfo.notifyId);
     594              :             }
     595              :         }
     596              : 
     597            0 :         HCCL_INFO("[DispatcherAiCpu][LaunchNewTask] arrayIdx[%u] flipInfos.size[%u]", arrayIdx, flipInfos.size());
     598              : 
     599              :         // 分段下发
     600            0 :         size_t sqeStartIdx = 0;           // 要拷贝的SQE在sqeArray中的起始索引
     601            0 :         size_t profTimestampStartIdx = 0; // 要拷贝的profiling timestamp在profTimestamps中的起始索引
     602            0 :         for (size_t i = 0; i < flipInfos.size(); ++i) {
     603              :             // Copy [sqeStartIdx, curZeroTaskidSqeIdx) + placeholder into RTSQ
     604            0 :             const size_t curZeroTaskidSqeIdx = flipInfos[i].first;
     605            0 :             const size_t curSqeCount = curZeroTaskidSqeIdx - sqeStartIdx + 1;
     606            0 :             CHK_PRT_RET(
     607              :                 curZeroTaskidSqeIdx < sqeStartIdx,
     608              :                 HCCL_ERROR(
     609              :                     "[DispatcherAiCpu][LaunchNewTask] curZeroTaskidSqeIdx[%u] < sqeStartIdx[%u]", curZeroTaskidSqeIdx,
     610              :                     sqeStartIdx),
     611              :                 HCCL_E_INTERNAL);
     612              : 
     613              :             // Wait RTSQ for curSqeCount SQE (including placeholder) space
     614            0 :             HCCL_INFO("[DispatcherAiCpu][LaunchNewTask] wait rtsq for %u sqe space", curSqeCount);
     615            0 :             CHK_RET(WaitRtsq(*streamPtr, curSqeCount, true));
     616              : 
     617              :             // 下发sqeArray[sqeStartIdx, curZeroTaskidSqeIdx)到RTSQ中 (excluding placeholder)
     618            0 :             if (curZeroTaskidSqeIdx > sqeStartIdx) { // 需要下发的cached SQE数量 > 0
     619            0 :                 HCCL_INFO(
     620              :                     "[DispatcherAiCpu][LaunchNewTask] launch %uth sqeArray[%u:%u)", arrayIdx, sqeStartIdx,
     621              :                     curZeroTaskidSqeIdx);
     622            0 :                 CHK_RET(MemcpyRtsq(
     623              :                     *streamPtr, curSqeCount - 1, sqeArray + sqeStartIdx * HCCL_SQE_SIZE, sqeTypeArray + sqeStartIdx,
     624              :                     sqeDfxInfoArray + sqeStartIdx, profL1Enable, profTimestamps, profTimestampStartIdx));
     625            0 :                 if (profL1Enable) {
     626            0 :                     profTimestampStartIdx += (curSqeCount - 1); // Cached SQEs
     627              :                 }
     628              :             }
     629              : 
     630              :             // 根据具体SQE下发信息更新placeholder
     631              :             // 参考AddFlipTask, 设置placeholder SQE (streamId和stream相关, flipNum和SQE下发相关)
     632              :             // 注意: 由于flipPlaceholder DfxInfo在当前算子下不变, 提前设置, 后续只需要刷新placeholder即可
     633            0 :             const uint16_t curFlipNum = flipInfos[i].second;
     634            0 :             CHK_PRT_RET(
     635              :                 curFlipNum == 0,
     636              :                 HCCL_ERROR(
     637              :                     "[DispatcherAiCpu][LaunchNewTask] invalid flipNum[%u]: flipInfoIdx[%u] arrayIdx[%u] "
     638              :                     "zeroTaskidSqeIdx[%u] streamId[%u]",
     639              :                     curFlipNum, i, arrayIdx, curZeroTaskidSqeIdx, streamId),
     640              :                 HCCL_E_INTERNAL);
     641            0 :             CHK_PTR_NULL(addOneFlipPlaceHolderSqe_);
     642            0 :             addOneFlipPlaceHolderSqe_(streamId, curFlipNum, flipPlaceholderTaskId, placeholderSqe, &placeholderSqeType);
     643            0 :             HCCL_INFO(
     644              :                 "[DispatcherAiCpu][LaunchNewTask] flip placeholder SQE with flipnum[%u] and streamid[%u]", curFlipNum,
     645              :                 streamId);
     646              : 
     647              :             // 下发placeholder SQE
     648            0 :             HCCL_INFO(
     649              :                 "[DispatcherAiCpu][LaunchNewTask] launch placeholder SQE after %uth sqeArray[%u:%u)", arrayIdx,
     650              :                 sqeStartIdx, curZeroTaskidSqeIdx);
     651            0 :             CHK_RET(MemcpyRtsq(
     652              :                 *streamPtr, 1, placeholderSqe, &placeholderSqeType, &placeholderSqeDfxInfo, profL1Enable,
     653              :                 profTimestamps, profTimestampStartIdx));
     654            0 :             if (profL1Enable) {
     655            0 :                 profTimestampStartIdx += 1; // Flip placeholder
     656              :             }
     657              : 
     658            0 :             sqeStartIdx = curZeroTaskidSqeIdx;
     659              :         }
     660              : 
     661              :         // 按需下发剩余SQE
     662            0 :         if (sqeStartIdx < sqeCount) {
     663              :             // Copy [sqeStartIdx, sqeCount - 1] into RTSQ
     664            0 :             const size_t remainSqeCount = sqeCount - sqeStartIdx;
     665              : 
     666              :             // Wait RTSQ for remainSqeCount SQE space
     667            0 :             HCCL_INFO("[DispatcherAiCpu][LaunchNewTask] wait rtsq for %u sqe space", remainSqeCount);
     668            0 :             CHK_RET(WaitRtsq(*streamPtr, remainSqeCount, true));
     669              : 
     670              :             // 下发sqeArray[sqeStartIdx, sqeCount - 1]到RTSQ中
     671            0 :             HCCL_INFO(
     672              :                 "[DispatcherAiCpu][LaunchNewTask] launch %uth sqeArray[%u:%u]", arrayIdx, sqeStartIdx, sqeCount - 1);
     673            0 :             CHK_RET(MemcpyRtsq(
     674              :                 *streamPtr, remainSqeCount, sqeArray + sqeStartIdx * HCCL_SQE_SIZE, sqeTypeArray + sqeStartIdx,
     675              :                 sqeDfxInfoArray + sqeStartIdx, profL1Enable, profTimestamps, profTimestampStartIdx));
     676            0 :             if (profL1Enable) {
     677            0 :                 profTimestampStartIdx += remainSqeCount; // Remaining cached SQEs
     678              :             }
     679              :         }
     680              : 
     681              :         // 为下一段SQE数组的刷新清理变量
     682            0 :         sqeCount = 0;
     683            0 :         sqeArray = nullptr;
     684            0 :         sqeTypeArray = nullptr;
     685            0 :         sqeDfxInfoArray = nullptr;
     686            0 :         streamPtr = nullptr;
     687            0 :         flipInfos.clear();
     688              :     }
     689              : 
     690              :     // 下发完当前cache entry中所有SQE数组后, 更新input/output memory ranges, 与SQE中in-place update的addr-related
     691              :     // fields保持一直
     692            0 :     CHK_RET(entryPtr->SetInputOutputMemRanges(userInputMemRanges, userOutputMemRanges));
     693              : 
     694            0 :     return HCCL_SUCCESS;
     695            0 : }
     696              : 
     697           11 : HcclResult DispatcherAiCpu::LaunchTask(Stream& stream, bool isBlockLaunch)
     698              : {
     699           11 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
     700           11 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
     701           11 :     CHK_PTR_NULL(sqeContext);
     702           11 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
     703           11 :     CHK_PTR_NULL(sqeContextBuffer);
     704           11 :     const auto cnt = sqeContextBuffer->sqeCnt;
     705           11 :     if (cnt == 0) {
     706            6 :         CHK_PRT_CONT(
     707              :             isBlockLaunch, HCCL_DEBUG("no sqe, streamId:%d, sqId:%u", streamInfo.actualStreamId, streamInfo.sqId));
     708            6 :         return HCCL_SUCCESS;
     709            5 :     } else if (cnt > streamInfo.sqDepth) {
     710            1 :         HCCL_ERROR("LaunchTask fail, cnt:%u should be less than sqDepth:%u", cnt, streamInfo.sqDepth);
     711            1 :         return HCCL_E_PTR;
     712              :     }
     713              : 
     714            4 :     auto& head = sqeContextBuffer->sqHead;
     715            4 :     auto& tail = sqeContextBuffer->sqTail;
     716            4 :     u32 newTail = (tail + cnt) % streamInfo.sqDepth;
     717              :     // 仅在阻塞下发场景打印,避免非阻塞场景调用时刷屏
     718            4 :     CHK_PRT_CONT(
     719              :         isBlockLaunch,
     720              :         HCCL_INFO(
     721              :             "Before send sqid:%d cnt:%u head:%u curtail:%u newTail:%u", streamInfo.sqId, cnt, head, tail, newTail));
     722              : 
     723            4 :     u64 startUsec = GetCurAicpuTimestamp();
     724            4 :     u64 lastUsec = startUsec;
     725      3176930 :     while (((tail < head ? streamInfo.sqDepth : 0U) + tail - head + cnt >= streamInfo.sqDepth)
     726      3176930 :            && (tail != head)) { // 判断剩余sqe空间是否足够下发
     727              :         // 需要放在while循环进来后第一个执行
     728      3176928 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
     729              : 
     730              :         // 非阻塞下发场景,rtsq队列空间不足时直接返回
     731      3176928 :         if (isBlockLaunch == false) {
     732            0 :             return HCCL_SUCCESS;
     733              :         }
     734              : 
     735              :         // 当前流无法下发,把其他流都launch一遍,避免等待的其他流没有launch
     736      4779992 :         for (auto it = streamMap_.begin(); it != streamMap_.end(); ++it) {
     737      1603064 :             if (it->first != streamInfo.actualStreamId) {
     738            1 :                 if (it->second.IsInvalid()) { // 跳过已销毁的stream (streamMap_只增不删, 原stream销毁后副本通过shared
     739              :                                               // invalid标志感知)
     740            0 :                     HCCL_WARNING(
     741              :                         "[DispatcherAiCpu][LaunchTask] skip invalid stream in streamMap, streamId:%d", it->first);
     742            0 :                     continue;
     743              :                 }
     744            1 :                 CHK_RET(LaunchTask(it->second, false));
     745              :             }
     746              :         }
     747      3176928 :         u64 curUsec = GetCurAicpuTimestamp();
     748      3176928 :         if (dfxTimeOutConfig_.sqFullWaitTimeOut != 0
     749      3176927 :             && (curUsec - startUsec > NANOSECOND_TO_SECOND * dfxTimeOutConfig_.sqFullWaitTimeOut)) {
     750            2 :             HCCL_ERROR(
     751              :                 "Rtsq full, timeout %lus. curhead:%u, sqId:%d", dfxTimeOutConfig_.sqFullWaitTimeOut, head,
     752              :                 streamInfo.sqId);
     753            2 :             return HCCL_E_AGAIN;
     754              :         }
     755              : 
     756              :         // 等待下发阶段,每隔30s打印一次状态
     757      3176926 :         if (curUsec - lastUsec > NANOSECOND_TO_SECOND * dfx::kPrintSqInterval) {
     758            0 :             lastUsec = curUsec;
     759            0 :             HCCL_RUN_INFO(
     760              :                 "[LaunchTask][WaitLaunchWhileLoop]Current state. sqid:%d, head:%u, tail:%u, cnt:%u", streamInfo.sqId,
     761              :                 head, tail, cnt);
     762              :         }
     763              : 
     764              :         // 下发过程中出现cqe异常
     765      3176926 :         if (checkOpExecStatusCallback_ != nullptr) {
     766            0 :             HcclResult opExecStatus = checkOpExecStatusCallback_();
     767            0 :             CHK_PRT_RET(
     768              :                 opExecStatus != HCCL_SUCCESS,
     769              :                 HCCL_ERROR("hccl aicpu stop launch for task exception or stop command, ret:%d", opExecStatus),
     770              :                 opExecStatus);
     771              :         }
     772              :     }
     773              : 
     774            2 :     uint32_t left = streamInfo.sqDepth - tail; // sqeAddr 剩余空间
     775            2 :     const auto tailSqeIdx = sqeContextBuffer->tailSqeIdx;
     776            2 :     HCCL_INFO("cpy sqe, left:%u, tailSqeId:%u, cnt:%u, streamId:%u", left, tailSqeIdx, cnt, stream.id());
     777            2 :     if (cnt <= left) { // 剩余buffer放得下新增sqe
     778            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     779              :             reinterpret_cast<uint8_t*>(streamInfo.sqBaseAddr) + tail * HCCL_SQE_SIZE, left * HCCL_SQE_SIZE,
     780              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE, cnt * HCCL_SQE_SIZE));
     781              : 
     782            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     783              :             sqeContextBuffer->rtsMirrorBuffer + tail * HCCL_SQE_SIZE, left * HCCL_SQE_SIZE,
     784              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE, cnt * HCCL_SQE_SIZE));
     785              : 
     786            1 :         CHK_SAFETY_FUNC_RET(
     787              :             memcpy_s(sqeContextBuffer->rtsqSqeType + tail, left, sqeContextBuffer->sqeType + (tailSqeIdx - cnt), cnt));
     788            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     789              :             sqeContextBuffer->rtsDfxInfo + tail, left * sizeof(AicpuDfxInfo),
     790              :             sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt), cnt * sizeof(AicpuDfxInfo)));
     791              :     } else {
     792            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     793              :             reinterpret_cast<uint8_t*>(streamInfo.sqBaseAddr) + tail * HCCL_SQE_SIZE, left * HCCL_SQE_SIZE,
     794              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE, left * HCCL_SQE_SIZE));
     795              : 
     796            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     797              :             reinterpret_cast<uint8_t*>(streamInfo.sqBaseAddr), streamInfo.sqDepth * HCCL_SQE_SIZE,
     798              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt + left) * HCCL_SQE_SIZE, (cnt - left) * HCCL_SQE_SIZE));
     799              : 
     800            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     801              :             sqeContextBuffer->rtsMirrorBuffer + tail * HCCL_SQE_SIZE, left * HCCL_SQE_SIZE,
     802              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE, left * HCCL_SQE_SIZE));
     803              : 
     804            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     805              :             sqeContextBuffer->rtsMirrorBuffer, streamInfo.sqDepth * HCCL_SQE_SIZE,
     806              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt + left) * HCCL_SQE_SIZE, (cnt - left) * HCCL_SQE_SIZE));
     807              : 
     808            1 :         CHK_SAFETY_FUNC_RET(
     809              :             memcpy_s(sqeContextBuffer->rtsqSqeType + tail, left, sqeContextBuffer->sqeType + (tailSqeIdx - cnt), left));
     810            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     811              :             sqeContextBuffer->rtsqSqeType + 0, streamInfo.sqDepth,
     812              :             sqeContextBuffer->sqeType + (tailSqeIdx - cnt + left), (cnt - left)));
     813            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     814              :             sqeContextBuffer->rtsDfxInfo + tail, left * sizeof(AicpuDfxInfo),
     815              :             sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt), left * sizeof(AicpuDfxInfo)));
     816            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     817              :             sqeContextBuffer->rtsDfxInfo + 0, streamInfo.sqDepth * sizeof(AicpuDfxInfo),
     818              :             sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt + left), (cnt - left) * sizeof(AicpuDfxInfo)));
     819              :     }
     820              :     // 打印算子展开下发的SQE内容for debug
     821              :     // 设置HCCL_DEBUG_CONFIG="task", 或者设置ASCEND_GLOBAL_LOG_LEVEL=0
     822            2 :     if ((UNLIKELY(GetExternalInputDebugConfig() & PLF_TASK)) || UNLIKELY(HcclCheckLogLevel(HCCL_LOG_DEBUG))) {
     823            2 :         const int32_t streamId = stream.GetHcclStreamInfo().actualStreamId;
     824            2 :         PLF_CONFIG_DEBUG(
     825              :             PLF_TASK, "[DispatcherAicpu][LaunchTask] dump content of %u dispatched SQEs with stream id %u", cnt,
     826              :             streamId);
     827              : 
     828            2 :         uint8_t* sqeArray = sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE;
     829            2 :         uint8_t* sqeTypeArray = sqeContextBuffer->sqeType + (tailSqeIdx - cnt);
     830            2 :         AicpuDfxInfo* sqeDfxInfoArray = sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt);
     831           14 :         for (size_t sqeIdx = 0; sqeIdx < cnt; ++sqeIdx) {
     832           12 :             uint8_t* sqePtr = sqeArray + sqeIdx * HCCL_SQE_SIZE;
     833           12 :             const uint8_t sqeType = sqeTypeArray[sqeIdx];
     834           12 :             if (sqeType == SqeType::FLIP_PLACEHOLDER_SQE) {
     835            0 :                 const rtStarsPlaceHolderSqe_t* placeholderSqePtr
     836            0 :                     = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqeArray + sqeIdx * HCCL_SQE_SIZE);
     837            0 :                 PLF_CONFIG_DEBUG(
     838              :                     PLF_TASK,
     839              :                     "[DispatcherAicpu][LaunchTask] %uth dispatched SQE (placeholder) header.type[%u] taskid[%u]",
     840              :                     sqeIdx, placeholderSqePtr->header.type, placeholderSqePtr->header.taskId);
     841              :             } else {
     842           12 :                 PLF_CONFIG_DEBUG(PLF_TASK, "[DispatcherAicpu][LaunchTask] %uth dispatched SQE", sqeIdx);
     843              :             }
     844              : 
     845           12 :             CHK_RET(OpUnfoldCache::DumpSqeContent(sqePtr, sqeType));
     846              : 
     847           12 :             const AicpuDfxInfo& dfxinfo = sqeDfxInfoArray[sqeIdx];
     848           12 :             PLF_CONFIG_DEBUG(
     849              :                 PLF_TASK, "[DispatcherAicpu][LaunchTask] AicpuDfxInfo: remoteRank[%u] opRingBufferIdx[%u] notifyId[%u]",
     850              :                 dfxinfo.remoteRank, dfxinfo.opRingBufferIdx, dfxinfo.notifyId);
     851              :         }
     852              :     }
     853              : 
     854              :     // 当前算子展开的SQE需要被动态缓存
     855            2 :     if (needAddSqe_) {
     856            0 :         CHK_PTR_NULL(cachePtr_);
     857              : 
     858              :         // 查找key对应的cache entry, 如果不存在 (即当前算子第一次LaunchTask), 创建新的cache entry
     859            0 :         OpUnfoldCacheEntry* entryPtr = nullptr;
     860            0 :         CHK_RET(cachePtr_->FindEntry(key_, &entryPtr));
     861            0 :         if (entryPtr == nullptr) {
     862            0 :             CHK_RET(cachePtr_->AddEntry(key_, userInputMemRanges_, userOutputMemRanges_, &entryPtr));
     863              :         }
     864            0 :         CHK_PTR_NULL(entryPtr);
     865              : 
     866              :         // 准备SQE相关信息的数组基地址
     867            0 :         uint8_t* sqeArray = sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE;
     868            0 :         uint8_t* sqeTypeArray = sqeContextBuffer->sqeType + (tailSqeIdx - cnt);
     869            0 :         AicpuDfxInfo* sqeDfxInfoArray = sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt);
     870              : 
     871              :         // 遍历sqeType找到placeholder的位置
     872            0 :         std::vector<size_t> placeholderIdxes;
     873            0 :         uint8_t* curSqeTypePtr = sqeTypeArray;
     874            0 :         for (size_t sqeTypeIdx = 0; sqeTypeIdx < cnt; ++sqeTypeIdx) {
     875            0 :             if (*curSqeTypePtr == SqeType::FLIP_PLACEHOLDER_SQE) {
     876            0 :                 placeholderIdxes.emplace_back(sqeTypeIdx);
     877              :             }
     878            0 :             ++curSqeTypePtr;
     879              :         }
     880              : 
     881              :         // 在动态缓存中分配实际需要的SQE数组
     882            0 :         const size_t cacheableSqeCount = cnt - placeholderIdxes.size();
     883            0 :         const int32_t streamId = stream.GetHcclStreamInfo().actualStreamId;
     884            0 :         size_t arrayIdx = 0;
     885            0 :         CHK_RET(entryPtr->AllocSqeArray(cacheableSqeCount, streamId, arrayIdx));
     886              : 
     887              :         // 分段拷贝SQE相关信息到cache entry中
     888            0 :         size_t cacheableSqeStartIdx = 0; // SQE start index (在动态缓存对应SQE数组中的索引)
     889            0 :         size_t bufferSqeStartIdx = 0;    // SQE start index (在SQE ring buffer中的索引)
     890            0 :         for (size_t i = 0; i < placeholderIdxes.size(); ++i) {
     891              :             // [bufferSqeStartIdx, curPlaceholderIdx) -> [cacheableSqeStartIdx, cacheableSqeStartIdx + curPlaceholderIdx
     892              :             // - bufferSqeStartIdx)
     893            0 :             const size_t curPlaceholderIdx = placeholderIdxes[i];
     894            0 :             HCCL_INFO(
     895              :                 "[DispatcherAicpu][LaunchTask] %uth placeholder copy dispatchedSqeArray[%u:%u) into "
     896              :                 "cachedSqeArrays[%u][%u:%u)",
     897              :                 i, bufferSqeStartIdx, curPlaceholderIdx, arrayIdx, cacheableSqeStartIdx,
     898              :                 cacheableSqeStartIdx + curPlaceholderIdx - bufferSqeStartIdx);
     899            0 :             if (curPlaceholderIdx <= bufferSqeStartIdx) { // NO non-placeholder dispatched SQE to admit
     900              :                 // NOTE: NO need to change cacheableSqeStartIdx
     901            0 :                 bufferSqeStartIdx = curPlaceholderIdx + 1;
     902              :             } else {
     903            0 :                 const size_t curSqeCount = curPlaceholderIdx - bufferSqeStartIdx;
     904            0 :                 CHK_RET(entryPtr->MemcpySqeArray(
     905              :                     arrayIdx, cacheableSqeStartIdx, curSqeCount, sqeArray + bufferSqeStartIdx * HCCL_SQE_SIZE,
     906              :                     sqeTypeArray + bufferSqeStartIdx, sqeDfxInfoArray + bufferSqeStartIdx, isAlltoallv_,
     907              :                     alltoallvMetadataPtr_));
     908            0 :                 cacheableSqeStartIdx += curSqeCount;
     909            0 :                 bufferSqeStartIdx = curPlaceholderIdx + 1;
     910              :             }
     911              :         }
     912              : 
     913              :         // 存在剩余SQE, 即最后一个SQE不是placeholder
     914            0 :         if (LIKELY(bufferSqeStartIdx < cnt)) {
     915              :             // [bufferSqeStartIdx, cnt - 1] -> [cacheableSqeStartIdx, cacheableSqeStartIdx + cnt - bufferSqeStartIdx)
     916            0 :             const size_t curSqeCount = cnt - bufferSqeStartIdx;
     917            0 :             CHK_RET(entryPtr->MemcpySqeArray(
     918              :                 arrayIdx, cacheableSqeStartIdx, curSqeCount, sqeArray + bufferSqeStartIdx * HCCL_SQE_SIZE,
     919              :                 sqeTypeArray + bufferSqeStartIdx, sqeDfxInfoArray + bufferSqeStartIdx, isAlltoallv_,
     920              :                 alltoallvMetadataPtr_));
     921              :         }
     922            0 :     }
     923              : 
     924            2 :     CHK_RET(ConfigSqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_TAIL, newTail));
     925            2 :     tail = newTail;
     926            2 :     PLF_CONFIG_INFO(
     927              :         PLF_TASK, "%s success, sqid:%d, sqe_num:%u, curHead:%u, curtail:%u", __func__, streamInfo.sqId, cnt, head,
     928              :         tail);
     929            2 :     sqeContextBuffer->sqeCnt = 0;
     930            2 :     return HCCL_SUCCESS;
     931              : }
     932              : 
     933            8 : HcclResult DispatcherAiCpu::LaunchTasksEx(hccl::Stream& stream, std::vector<Stream>& subStreams)
     934              : {
     935              :     /* 两阶段模式,主流待正式执行时再下 */
     936              :     /* 一阶段第一次,可以先下主流 */
     937            8 :     HcclResult ret = LaunchTask(stream, true);
     938            8 :     if (ret != HCCL_SUCCESS) {
     939            0 :         HCCL_ERROR(
     940              :             "[DispatcherAiCpu][LaunchTasksEx] "
     941              :             "launch task failed, sqid:%u, ret:%u",
     942              :             stream.sqId(), ret);
     943            0 :         return ret;
     944              :     }
     945              : 
     946            8 :     for (u32 index = 0; index < subStreams.size(); index++) {
     947            0 :         ret = LaunchTask(subStreams[index], true);
     948            0 :         if (ret != HCCL_SUCCESS) {
     949            0 :             HCCL_ERROR(
     950              :                 "[DispatcherAiCpu][LaunchTasksEx] "
     951              :                 "launch task failed, sqid:%u, ret:%u",
     952              :                 subStreams[index].sqId(), ret);
     953            0 :             return ret;
     954              :         }
     955              :     }
     956              : 
     957            8 :     return HCCL_SUCCESS;
     958              : }
     959              : 
     960            3 : HcclResult DispatcherAiCpu::LaunchAllTasks()
     961              : {
     962            5 :     for (auto it = streamMap_.begin(); it != streamMap_.end(); ++it) {
     963            6 :         if (it->second
     964            3 :                 .IsInvalid()) { // 跳过已销毁的stream (streamMap_只增不删, 原stream销毁后副本通过shared invalid标志感知)
     965            0 :             HCCL_WARNING("[DispatcherAiCpu][LaunchAllTasks] skip invalid stream in streamMap, streamId:%d", it->first);
     966            0 :             continue;
     967              :         }
     968            3 :         HcclResult ret = LaunchTask(it->second, true);
     969            3 :         if (ret != HCCL_SUCCESS) {
     970            1 :             HCCL_ERROR("DispatcherAiCpu][LaunchAllTasks] launch task failed, sqid:%u, ret:%u", it->second.sqId(), ret);
     971            1 :             return ret;
     972              :         }
     973              :     }
     974            2 :     return HCCL_SUCCESS;
     975              : }
     976              : 
     977            1 : HcclResult DispatcherAiCpu::ReduceAsync(
     978              :     const void* src, void* dst, u64 dataCount, const HcclDataType datatype, HcclReduceOp redOp, Stream& stream,
     979              :     HcclReduceType reduceType)
     980              : {
     981            1 :     return (reduceType == HcclReduceType::HCCL_INLINE_REDUCE) ?
     982            1 :                InlineReduceAsync(src, dataCount, datatype, redOp, stream, dst) :
     983            1 :                TbeReduceAsync(src, dst, dataCount, datatype, redOp, stream, dst);
     984              : }
     985              : 
     986            2 : HcclResult DispatcherAiCpu::InlineReduceAsync(
     987              :     const void* src, u64 dataCount, const HcclDataType datatype, HcclReduceOp redOp, hccl::Stream& stream, void* dst,
     988              :     u32 remoteUserRank, hccl::LinkType inLinkType)
     989              : {
     990              :     // 参数有效性检查
     991            2 :     CHK_PTR_NULL(stream.ptr());
     992            2 :     if (dataCount == 0) {
     993            0 :         HCCL_INFO("%s src memory size is 0, not need inline reduce.", __func__);
     994            0 :         return HCCL_SUCCESS;
     995              :     }
     996            2 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
     997              : 
     998            2 :     aclDataType runtimeDataType = DT_MAP_TABLE[datatype];
     999            2 :     aclrtReduceKind rtReduceOp = RK_MAP_TABLE[redOp];
    1000              : 
    1001              :     // 将数据按4GB切分循环处理
    1002            2 :     uint64_t spiltLoop = 0;
    1003            2 :     uint64_t addr_offset = 0;
    1004            2 :     uint64_t countSplit = 0;
    1005            2 :     uint64_t countSize = dataCount * SIZE_TABLE[datatype];
    1006            2 :     uint8_t* sqeBuffer = nullptr;
    1007            2 :     uint8_t* sqeTypeAddr = nullptr;
    1008            2 :     uint8_t* sqeDfxInfoAddr = nullptr;
    1009            2 :     uint16_t taskId = 0U;
    1010              : 
    1011            2 :     if (countSize > HCCL_SDMA_MAX_COUNT_4GB) {
    1012            0 :         spiltLoop = (countSize % HCCL_SDMA_MAX_COUNT_4GB) ? (countSize / HCCL_SDMA_MAX_COUNT_4GB) :
    1013            0 :                                                             ((countSize / HCCL_SDMA_MAX_COUNT_4GB) - 1);
    1014            0 :         HCCL_INFO(
    1015              :             "%s InlineReduceAsync SDMA task countSize is bigger than 4GB"
    1016              :             " and do segmentation splitloop:%llu",
    1017              :             __func__, spiltLoop);
    1018              :     }
    1019            2 :     uint8_t linkType = static_cast<uint8_t>(inLinkType);
    1020            4 :     for (uint64_t index = 0; index <= spiltLoop; index++) {
    1021            2 :         addr_offset = index * HCCL_SDMA_MAX_COUNT_4GB;
    1022            2 :         countSplit = (index == spiltLoop) ? (countSize - index * HCCL_SDMA_MAX_COUNT_4GB) : (HCCL_SDMA_MAX_COUNT_4GB);
    1023            2 :         void* srcSplit = static_cast<void*>(static_cast<char*>(const_cast<void*>(src)) + addr_offset);
    1024            2 :         void* dstSplit = static_cast<void*>(static_cast<char*>(dst) + addr_offset);
    1025              : 
    1026            2 :         CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1027            2 :         AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
    1028            2 :         dfxInfo->opRingBufferIdx = opRingBufferIdx_;
    1029            2 :         dfxInfo->remoteRank = remoteUserRank;
    1030            2 :         dfxInfo->notifyId = INVALID_VALUE_RANKID;
    1031            2 :         addOneMemcpySqe_(
    1032            2 :             streamInfo.actualStreamId, taskId, srcSplit, countSplit, runtimeDataType, rtReduceOp, dstSplit, 0,
    1033              :             aicpuInfo_.ssid, aicpuInfo_.devId, aicpuInfo_.overflowAddr, linkType, sqeBuffer, sqeTypeAddr, hcclQos_);
    1034              : 
    1035            2 :         PLF_CONFIG_INFO(
    1036              :             PLF_TASK,
    1037              :             "%s para: linkType[%u] srcSplit[%p] dstSplit[%p] countSplit[%llu] taskId[%u] streamId[%u] remoteRank[%u] "
    1038              :             "rtDatatType[%d] rtReduceOp[%d]",
    1039              :             __func__, linkType, srcSplit, dstSplit, countSplit, taskId, streamInfo.actualStreamId, remoteUserRank,
    1040              :             runtimeDataType, rtReduceOp);
    1041              :     }
    1042              : 
    1043            2 :     return HCCL_SUCCESS;
    1044              : }
    1045              : 
    1046            1 : HcclResult DispatcherAiCpu::TbeReduceAsync(
    1047              :     [[maybe_unused]] const void* src1, [[maybe_unused]] const void* src2, [[maybe_unused]] u64 count,
    1048              :     [[maybe_unused]] const HcclDataType datatype, [[maybe_unused]] HcclReduceOp redOp, [[maybe_unused]] Stream& stream,
    1049              :     [[maybe_unused]] const void* dst)
    1050              : {
    1051            1 :     HCCL_ERROR("[DispatcherAiCpu][TbeReduceAsync] aicpu do not support the tbe reduce");
    1052            1 :     return HCCL_E_NOT_SUPPORT;
    1053              : }
    1054              : 
    1055            5 : HcclResult DispatcherAiCpu::RdmaSend(u32 dbindex, u64 dbinfo, hccl::Stream& stream, RdmaTaskInfo& taskInfo)
    1056              : {
    1057            5 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1058              : 
    1059            5 :     uint8_t* sqeBuffer = nullptr;
    1060            5 :     uint8_t* sqeTypeAddr = nullptr;
    1061            5 :     uint8_t* sqeDfxInfoAddr = nullptr;
    1062            5 :     uint16_t taskId = 0U;
    1063              : 
    1064            5 :     CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1065            5 :     AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
    1066            5 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
    1067            5 :     dfxInfo->remoteRank = taskInfo.remoteRank;
    1068            5 :     dfxInfo->notifyId = INVALID_UINT; // 多个wr只敲一次doorbell的情况下,一般只会有一个notify
    1069              : 
    1070            5 :     uint32_t wrLen = 0; // 统计wr的总数据量
    1071            5 :     for (const WrInformation& wr : taskInfo.wrInfos) {
    1072            0 :         wrLen += wr.wrData.memList.len;
    1073            0 :         dfxInfo->notifyId = (wr.notifyId != INVALID_UINT) ? wr.notifyId : dfxInfo->notifyId;
    1074              :     }
    1075              : 
    1076            5 :     u64 dbAddr = CalcDbAddr(dbindex);
    1077            5 :     addOneRdmaDbSendSqe_(
    1078            5 :         streamInfo.actualStreamId, taskId, dbinfo, dbAddr, wrLen, static_cast<uint8_t>(taskInfo.rdmaType), sqeBuffer,
    1079              :         sqeTypeAddr);
    1080              : 
    1081            5 :     PLF_CONFIG_INFO(
    1082              :         PLF_TASK, "%s para: streamId[%u] taskId[%u] remoteRank[%u] RdmaType[%d] wrLen[%u] notifyId[%u]", __func__,
    1083              :         streamInfo.actualStreamId, taskId, taskInfo.remoteRank, taskInfo.rdmaType, wrLen, dfxInfo->notifyId);
    1084              : 
    1085            5 :     return HCCL_SUCCESS;
    1086              : }
    1087              : 
    1088            0 : HcclResult DispatcherAiCpu::RdmaRecord(
    1089              :     [[maybe_unused]] u32 dbindex, [[maybe_unused]] u64 dbinfo, [[maybe_unused]] const struct SendWr& wr,
    1090              :     [[maybe_unused]] hccl::Stream& stream, [[maybe_unused]] RdmaType rdmaType, [[maybe_unused]] u32 userRank,
    1091              :     [[maybe_unused]] u64 offset, [[maybe_unused]] u32 notifyId)
    1092              : {
    1093            0 :     return HCCL_SUCCESS;
    1094              : }
    1095              : 
    1096           13 : HcclResult DispatcherAiCpu::GetStreamSqeBufferAddr(
    1097              :     hccl::Stream& stream, uint8_t*& sqeBufferAddr, uint8_t*& sqeTypeAddr, uint8_t*& sqeDfxInfoAddr, uint16_t& taskId)
    1098              : {
    1099           13 :     SaveStreamInfo(stream);
    1100           13 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
    1101           13 :     CHK_PTR_NULL(sqeContext);
    1102           13 :     if (UNLIKELY(sqeContext->buffer.sqeCnt >= HCCL_PER_LAUNCH_SQE_CNT)) {
    1103            0 :         HCCL_INFO("GetStreamSqeBufferAddr tailSqeIdx[%u], try to launchTask", sqeContext->buffer.tailSqeIdx);
    1104            0 :         CHK_RET(LaunchTask(stream, true));
    1105              :     }
    1106           13 :     if (UNLIKELY(sqeContext->buffer.tailSqeIdx >= HCCL_SQE_MAX_CNT)) {
    1107            0 :         CHK_RET(LaunchTask(stream, true));
    1108              : 
    1109            0 :         if (callback_ != nullptr) {
    1110            0 :             hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1111            0 :             hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1112            0 :             callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1113            0 :         }
    1114              :     }
    1115           13 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
    1116           13 :     uint16_t flipNum = sqeContextBuffer->filpNum;
    1117           13 :     uint16_t nextTaskId = sqeContextBuffer->tailSqeTaskId;
    1118              :     // nextTaskId=0的时候下发PlaceHolder
    1119           13 :     if (UNLIKELY(nextTaskId == 0 && flipNum != 0)) {
    1120            0 :         CHK_RET(AddFlipTask(stream));
    1121              :     }
    1122           13 :     if (UNLIKELY(sqeContext->buffer.tailSqeIdx >= HCCL_SQE_MAX_CNT)) {
    1123            0 :         CHK_RET(LaunchTask(stream, true));
    1124              : 
    1125            0 :         if (callback_ != nullptr) {
    1126            0 :             hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1127            0 :             hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1128            0 :             callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1129            0 :         }
    1130              :     }
    1131           13 :     CHK_RET(stream.GetNextSqeBufferAddr(sqeBufferAddr, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1132           13 :     return HCCL_SUCCESS;
    1133              : }
    1134              : 
    1135            2 : HcclResult DispatcherAiCpu::WaitRtsq(Stream& stream, const size_t& sqeCount, const bool isBlockLaunch)
    1136              : {
    1137              :     // 注意: 目前WaitRtsq不会被递归调用, 所以isBlockLaunch永远为true; 为防止以后LaunchTask递归使用WaitRtsq,
    1138              :     // 编码时考虑isBlockLaunch为false的情况
    1139              : 
    1140              :     // 检验入参
    1141            2 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1142            2 :     if (sqeCount == 0) {
    1143            0 :         CHK_PRT_CONT(
    1144              :             isBlockLaunch, HCCL_DEBUG(
    1145              :                                "[DispatcherAiCpu][WaitRtsq] no sqe, streamId:%d, sqId:%u", streamInfo.actualStreamId,
    1146              :                                streamInfo.sqId));
    1147            0 :         return HCCL_SUCCESS;
    1148            2 :     } else if (sqeCount > streamInfo.sqDepth) {
    1149            0 :         HCCL_ERROR(
    1150              :             "[DispatcherAiCpu][WaitRtsq] sqeCount %u should be smaller than sqDepth %u]", sqeCount, streamInfo.sqDepth);
    1151            0 :         return HCCL_E_PTR;
    1152              :     }
    1153              : 
    1154              :     // Get head and tail of RTSQ ring buffer
    1155            2 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
    1156            2 :     CHK_PTR_NULL(sqeContext);
    1157            2 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
    1158            2 :     CHK_PTR_NULL(sqeContextBuffer);
    1159            2 :     uint32_t& head = sqeContextBuffer->sqHead;
    1160            2 :     uint32_t& tail = sqeContextBuffer->sqTail;
    1161              : 
    1162              :     // Dump debug information
    1163            2 :     const uint32_t newTail = (tail + sqeCount) % streamInfo.sqDepth;
    1164              :     // 仅在阻塞下发场景打印,避免非阻塞场景调用时刷屏
    1165            2 :     CHK_PRT_CONT(
    1166              :         isBlockLaunch, HCCL_INFO(
    1167              :                            "[DispatcherAicpu][WaitRtsq] sqid:%d sqeCount:%u head:%u curtail:%u newTail:%u",
    1168              :                            streamInfo.sqId, sqeCount, head, tail, newTail));
    1169              : 
    1170              :     // 轮询RTSQ直至获得足够大的剩余空间
    1171            2 :     u64 startUsec = GetCurAicpuTimestamp();
    1172            2 :     u64 lastUsec = startUsec;
    1173            3 :     while (((tail < head ? streamInfo.sqDepth : 0U) + tail - head + sqeCount >= streamInfo.sqDepth)
    1174            3 :            && (tail != head)) { // 判断RTSQ中剩余sqe空间是否足够下发
    1175              :         // 需要放在while循环进来后第一个执行 (获取最新的RTSQ head, 查看RTSQ的消费进度)
    1176            2 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
    1177              : 
    1178              :         // 非阻塞下发场景,rtsq队列空间不足时直接返回
    1179            2 :         if (isBlockLaunch == false) {
    1180            1 :             return HCCL_SUCCESS;
    1181              :         }
    1182              : 
    1183              :         // 当前流无法下发,把其他流都launch一遍,避免等待的其他流没有launch
    1184            2 :         for (auto it = streamMap_.begin(); it != streamMap_.end(); ++it) {
    1185            1 :             if (it->first != streamInfo.actualStreamId) { // 不是当前stream
    1186            1 :                 if (it->second.IsInvalid()) { // 跳过已销毁的stream (streamMap_只增不删, 原stream销毁后副本通过shared
    1187              :                                               // invalid标志感知)
    1188            0 :                     HCCL_WARNING(
    1189              :                         "[DispatcherAiCpu][WaitRtsq] skip invalid stream in streamMap, streamId:%d", it->first);
    1190            0 :                     continue;
    1191              :                 }
    1192            1 :                 CHK_RET(LaunchTask(it->second, false)); // 非阻塞launch
    1193              :             }
    1194              :         }
    1195              : 
    1196              :         // 等待超时
    1197            1 :         u64 curUsec = GetCurAicpuTimestamp();
    1198            1 :         if (dfxTimeOutConfig_.sqFullWaitTimeOut != 0
    1199            0 :             && (curUsec - startUsec > NANOSECOND_TO_SECOND * dfxTimeOutConfig_.sqFullWaitTimeOut)) {
    1200            0 :             HCCL_ERROR(
    1201              :                 "[DispatcherAicpu][WaitRtsq] Rtsq full, timeout %lus. curhead:%u, sqId:%d",
    1202              :                 dfxTimeOutConfig_.sqFullWaitTimeOut, head, streamInfo.sqId);
    1203            0 :             return HCCL_E_AGAIN;
    1204              :         }
    1205              : 
    1206              :         // 等待下发阶段,每隔30s打印一次状态
    1207            1 :         if (curUsec - lastUsec > NANOSECOND_TO_SECOND * dfx::kPrintSqInterval) {
    1208            0 :             lastUsec = curUsec;
    1209            0 :             HCCL_RUN_INFO(
    1210              :                 "[DispatcherAicpu][WaitRtsq] Current state. sqid:%d, head:%u, tail:%u, sqeCount:%u", streamInfo.sqId,
    1211              :                 head, tail, sqeCount);
    1212              :         }
    1213              : 
    1214              :         // 等待下发过程中出现cqe异常, 需要终止当前算子SQE的下发过程
    1215            1 :         if (checkOpExecStatusCallback_ != nullptr) {
    1216            0 :             HcclResult opExecStatus = checkOpExecStatusCallback_();
    1217            0 :             CHK_PRT_RET(
    1218              :                 opExecStatus != HCCL_SUCCESS,
    1219              :                 HCCL_ERROR(
    1220              :                     "[DispatcherAicpu][WaitRtsq] hccl aicpu stop launch for task exception or stop command, ret:%d",
    1221              :                     opExecStatus),
    1222              :                 opExecStatus);
    1223              :         }
    1224              :     }
    1225              : 
    1226            1 :     return HCCL_SUCCESS;
    1227              : }
    1228              : 
    1229            0 : HcclResult DispatcherAiCpu::MemcpyRtsq(
    1230              :     Stream& stream, const size_t sqeCount, const uint8_t* sqeArray, const uint8_t* sqeTypeArray,
    1231              :     const AicpuDfxInfo* sqeDfxInfoArray, const bool profL1Enable, const std::vector<uint64_t>& profTimestamps,
    1232              :     const size_t profTimestampStartIdx)
    1233              : {
    1234              :     // 检验入参
    1235            0 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1236            0 :     if (sqeCount == 0) {
    1237            0 :         HCCL_DEBUG(
    1238              :             "[DispatcherAiCpu][MemcpyRtsq] no sqe, streamId:%d, sqId:%u", streamInfo.actualStreamId, streamInfo.sqId);
    1239            0 :         return HCCL_SUCCESS;
    1240            0 :     } else if (sqeCount > streamInfo.sqDepth) {
    1241            0 :         HCCL_ERROR(
    1242              :             "[DispatcherAiCpu][MemcpyRtsq] sqeCount %u should be smaller than sqDepth %u]", sqeCount,
    1243              :             streamInfo.sqDepth);
    1244            0 :         return HCCL_E_PTR;
    1245              :     }
    1246            0 :     CHK_PTR_NULL(sqeArray);
    1247            0 :     CHK_PTR_NULL(sqeTypeArray);
    1248            0 :     CHK_PTR_NULL(sqeDfxInfoArray);
    1249            0 :     if (profL1Enable) {
    1250              :         // 会访问profTimestamps[profTimestampStartIdx, profTimestampStartIdx + sqeCount - 1]
    1251            0 :         CHK_PRT_RET(
    1252              :             profTimestamps.size() == 0, HCCL_ERROR("[DispatcherAiCpu][MemcpyRtsq] empty profTimestamps"),
    1253              :             HCCL_E_INTERNAL);
    1254            0 :         CHK_PRT_RET(
    1255              :             profTimestampStartIdx >= profTimestamps.size(),
    1256              :             HCCL_ERROR(
    1257              :                 "[DispatcherAiCpu][MemcpyRtsq] profTimestampStartIdx[%u] >= profTimestamps.size[%u]",
    1258              :                 profTimestampStartIdx, profTimestamps.size()),
    1259              :             HCCL_E_INTERNAL);
    1260            0 :         CHK_PRT_RET(
    1261              :             (profTimestampStartIdx + sqeCount - 1) >= profTimestamps.size(),
    1262              :             HCCL_ERROR(
    1263              :                 "[DispatcherAiCpu][MemcpyRtsq] profTimestampStartIdx[%u] + sqeCount[%u] - 1 >= profTimestamps.size[%u]",
    1264              :                 profTimestampStartIdx, sqeCount, profTimestamps.size()),
    1265              :             HCCL_E_INTERNAL);
    1266              :     }
    1267              : 
    1268              :     // 获得RTSQ的head和tail
    1269            0 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
    1270            0 :     CHK_PTR_NULL(sqeContext);
    1271            0 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
    1272            0 :     CHK_PTR_NULL(sqeContextBuffer);
    1273            0 :     uint32_t& head = sqeContextBuffer->sqHead;
    1274            0 :     uint32_t& tail = sqeContextBuffer->sqTail;
    1275              : 
    1276              :     // Dump debug information
    1277            0 :     const uint32_t newTail = (tail + sqeCount) % streamInfo.sqDepth;
    1278            0 :     HCCL_INFO(
    1279              :         "[DispatcherAicpu][MemcpyRtsq] before memcpy, sqid:%d sqeCount:%u head:%u curtail:%u newTail:%u",
    1280              :         streamInfo.sqId, sqeCount, head, tail, newTail);
    1281              : 
    1282              :     // 准备memcpy中目的末端基地址 (RTSQ从tail开始拷贝, [head, tail)为待执行SQE)
    1283            0 :     uint8_t* rtsqSqeTailBaseAddr = reinterpret_cast<uint8_t*>(streamInfo.sqBaseAddr) + tail * HCCL_SQE_SIZE;
    1284            0 :     uint8_t* mirrorRtsqSqeTailBaseAddr = sqeContextBuffer->rtsMirrorBuffer + tail * HCCL_SQE_SIZE;
    1285            0 :     uint8_t* rtsqSqeTypeTailBaseAddr = sqeContextBuffer->rtsqSqeType + tail;
    1286            0 :     AicpuDfxInfo* rtsqDfxInfoTailBaseAddr = sqeContextBuffer->rtsDfxInfo + tail;
    1287              : 
    1288            0 :     uint32_t tailLeft = streamInfo.sqDepth - tail; // RTSQ tail到buffer末端的剩余空间 (不包括buffer前端到head的剩余空间)
    1289            0 :     HCCL_INFO(
    1290              :         "[DispatcherAicpu][MemcpyRtsq] cpy sqe, tailLeft:%u, sqeCount:%u, streamId:%u", tailLeft, sqeCount,
    1291              :         stream.id());
    1292            0 :     if (sqeCount <= tailLeft) { // buffer末端剩余空间放得下新增sqe
    1293              :         // 向buffer末端拷贝sqeCount个SQE信息
    1294              : 
    1295              :         // 拷贝SQE内容到RTSQ
    1296            0 :         CHK_SAFETY_FUNC_RET(
    1297              :             memcpy_s(rtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, sqeCount * HCCL_SQE_SIZE));
    1298              : 
    1299              :         // 拷贝SQE内容到RTSQ mirror
    1300            0 :         CHK_SAFETY_FUNC_RET(
    1301              :             memcpy_s(mirrorRtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, sqeCount * HCCL_SQE_SIZE));
    1302              : 
    1303              :         // 拷贝SQE类型
    1304            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqSqeTypeTailBaseAddr, tailLeft, sqeTypeArray, sqeCount));
    1305              : 
    1306              :         // 拷贝SQE DfxInfo
    1307            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1308              :             rtsqDfxInfoTailBaseAddr, tailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray,
    1309              :             sqeCount * sizeof(AicpuDfxInfo)));
    1310              :     } else { // 需要buffer末端和首端的剩余空间
    1311              :         // 先向buffer末端拷贝tailLeft个SQE信息, 再向buffer首端拷贝sqeCount-tailLeft个SQE信息
    1312              : 
    1313              :         // 拷贝SQE内容到RTSQ
    1314            0 :         CHK_SAFETY_FUNC_RET(
    1315              :             memcpy_s(rtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, tailLeft * HCCL_SQE_SIZE));
    1316            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1317              :             reinterpret_cast<uint8_t*>(streamInfo.sqBaseAddr), streamInfo.sqDepth * HCCL_SQE_SIZE,
    1318              :             sqeArray + tailLeft * HCCL_SQE_SIZE, (sqeCount - tailLeft) * HCCL_SQE_SIZE));
    1319              : 
    1320              :         // 拷贝SQE内容到RTSQ mirror
    1321            0 :         CHK_SAFETY_FUNC_RET(
    1322              :             memcpy_s(mirrorRtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, tailLeft * HCCL_SQE_SIZE));
    1323            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1324              :             sqeContextBuffer->rtsMirrorBuffer, streamInfo.sqDepth * HCCL_SQE_SIZE, sqeArray + tailLeft * HCCL_SQE_SIZE,
    1325              :             (sqeCount - tailLeft) * HCCL_SQE_SIZE));
    1326              : 
    1327              :         // 拷贝SQE type
    1328            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqSqeTypeTailBaseAddr, tailLeft, sqeTypeArray, tailLeft));
    1329            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1330              :             sqeContextBuffer->rtsqSqeType, streamInfo.sqDepth, sqeTypeArray + tailLeft, (sqeCount - tailLeft)));
    1331              : 
    1332              :         // 拷贝SQE DfxInfo
    1333            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1334              :             rtsqDfxInfoTailBaseAddr, tailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray,
    1335              :             tailLeft * sizeof(AicpuDfxInfo)));
    1336            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1337              :             sqeContextBuffer->rtsDfxInfo, streamInfo.sqDepth * sizeof(AicpuDfxInfo), sqeDfxInfoArray + tailLeft,
    1338              :             (sqeCount - tailLeft) * sizeof(AicpuDfxInfo)));
    1339              :     }
    1340              : 
    1341              :     // 更新RTSQ ring buffer的tail
    1342            0 :     CHK_RET(ConfigSqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_TAIL, newTail));
    1343            0 :     tail = newTail;
    1344            0 :     PLF_CONFIG_INFO(
    1345              :         PLF_TASK, "%s success, sqid:%d, sqe_num:%u, curHead:%u, curtail:%u", __func__, streamInfo.sqId, sqeCount, head,
    1346              :         tail);
    1347              : 
    1348              :     // 上报profiling信息
    1349            0 :     if (profL1Enable) {
    1350              :         // Cache hit下SQE ring buffer中[tail-cnt, tail)为待下发SQE, 其数量一定为0 (否则更新tailSqeIdx后,
    1351              :         // 会导致待下发SQE未下发, 而已下发SQE重复下发)
    1352            0 :         CHK_PRT_RET(
    1353              :             sqeContextBuffer->sqeCnt != 0,
    1354              :             HCCL_ERROR(
    1355              :                 "[DispatcherAicpu][MemcpyRtsq] sqeContextBuffer->sqeCnt[%u] should be zero!", sqeContextBuffer->sqeCnt),
    1356              :             HCCL_E_INTERNAL);
    1357              : 
    1358              :         // 上报flip placeholder的profiling信息
    1359            0 :         if ((*sqeTypeArray) == SqeType::FLIP_PLACEHOLDER_SQE) {
    1360            0 :             CHK_PRT_RET(
    1361              :                 sqeCount != 1, HCCL_ERROR("[DispatcherAicpu][MemcpyRtsq] sqeCount[%u] should be 1!", sqeCount),
    1362              :                 HCCL_E_INTERNAL);
    1363              : 
    1364              :             // 注意: 参考AddFlipTask, 先上报flip task (提醒profiling翻转taskid), 之后再拷贝到SQE ring buffer
    1365              :             // (捕捉placeholder SQE相关的profiling信息) 注意:
    1366              :             // ProfilingManager::TaskProfilingCallBack->ReportFilpTask不会扫描SQE ring buffer,
    1367              :             // 也不会更新其中的streamToSqeIdxMap_
    1368            0 :             if (callback_ != nullptr) {
    1369            0 :                 const rtStarsPlaceHolderSqe_t* placeholderSqePtr
    1370              :                     = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqeArray);
    1371              :                 hccl::FlipTaskPara para(
    1372            0 :                     stream.id(), placeholderSqePtr->header.taskId, placeholderSqePtr->u.flip_task_info.flipNumReport);
    1373            0 :                 hccl::TaskPara taskPara(TaskType::TASK_FLIP, para);
    1374            0 :                 callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1375            0 :             }
    1376              :         }
    1377              : 
    1378              :         // 循环拷贝cached SQE到SQE ring buffer中
    1379            0 :         size_t reportSqeCount = 0;
    1380            0 :         while (reportSqeCount < sqeCount) {
    1381            0 :             CHK_PRT_RET(
    1382              :                 sqeContextBuffer->tailSqeIdx > HCCL_SQE_MAX_CNT,
    1383              :                 HCCL_ERROR(
    1384              :                     "[DispatcherAicpu][MemcpyRtsq] tailSqeIdx[%u] > HCCL_SQE_MAX_CNT[%u]", sqeContextBuffer->tailSqeIdx,
    1385              :                     HCCL_SQE_MAX_CNT),
    1386              :                 HCCL_E_INTERNAL);
    1387            0 :             const size_t sqeTailLeft = HCCL_SQE_MAX_CNT - sqeContextBuffer->tailSqeIdx;
    1388            0 :             if (sqeTailLeft > 0) {
    1389              :                 // 准备profiling上报的目的末端基地址 (SQE ring buffer从tail开始拷贝)
    1390            0 :                 uint8_t* sqeLocalBuffTailBaseAddr
    1391            0 :                     = sqeContextBuffer->localBuff + sqeContextBuffer->tailSqeIdx * HCCL_SQE_SIZE;
    1392            0 :                 uint8_t* sqeTypeTailBaseAddr = sqeContextBuffer->sqeType + sqeContextBuffer->tailSqeIdx;
    1393            0 :                 AicpuDfxInfo* dfxInfoTailBaseAddr = sqeContextBuffer->dfxInfo + sqeContextBuffer->tailSqeIdx;
    1394            0 :                 uint64_t* profTimestapTailBaseAddr = sqeContextBuffer->profTimestap + sqeContextBuffer->tailSqeIdx;
    1395              : 
    1396              :                 // 向SQE ring buffer末端拷贝SQE信息[reportSqeCount, reportSqeCount + tmpSqeCount - 1]
    1397              :                 // (只用于profiling上报, 不会下发)
    1398            0 :                 const size_t tmpSqeCount = std::min(sqeCount - reportSqeCount, sqeTailLeft);
    1399            0 :                 HCCL_INFO(
    1400              :                     "[DispatcherAicpu][MemcpyRtsq] report sqe profiling, sqeCount[%u] reportSqeCount[%u] "
    1401              :                     "tailSqeIdx[%u] sqeTailLeft[%u] tmpSqeCount[%u]",
    1402              :                     sqeCount, reportSqeCount, sqeContextBuffer->tailSqeIdx, sqeTailLeft, tmpSqeCount);
    1403              : 
    1404              :                 // 拷贝SQE内容
    1405            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(
    1406              :                     sqeLocalBuffTailBaseAddr, sqeTailLeft * HCCL_SQE_SIZE, sqeArray + reportSqeCount * HCCL_SQE_SIZE,
    1407              :                     tmpSqeCount * HCCL_SQE_SIZE));
    1408              : 
    1409              :                 // 拷贝SQE类型
    1410            0 :                 CHK_SAFETY_FUNC_RET(
    1411              :                     memcpy_s(sqeTypeTailBaseAddr, sqeTailLeft, sqeTypeArray + reportSqeCount, tmpSqeCount));
    1412              : 
    1413              :                 // 拷贝SQE DfxInfo
    1414            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(
    1415              :                     dfxInfoTailBaseAddr, sqeTailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray + reportSqeCount,
    1416              :                     tmpSqeCount * sizeof(AicpuDfxInfo)));
    1417              : 
    1418              :                 // 拷贝SQE timestamp
    1419            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(
    1420              :                     profTimestapTailBaseAddr, sqeTailLeft * sizeof(uint64_t),
    1421              :                     profTimestamps.data() + profTimestampStartIdx + reportSqeCount, tmpSqeCount * sizeof(uint64_t)));
    1422              : 
    1423              :                 // 注意: sqeContextBuffer->sqeCnt不更新, 仍然为0 (即拷贝的SQE信息为已下发待上报), 避免SQE重复下发
    1424            0 :                 sqeContextBuffer->tailSqeIdx += static_cast<uint16_t>(tmpSqeCount);
    1425            0 :                 reportSqeCount += tmpSqeCount;
    1426              :             } else {
    1427              :                 // 注意: SQE ring buffer中待下发SQE数量一定为0, 不需要调用LaunchTask将待下发变成已下发待上报,
    1428              :                 // 可以直接上报profiling将已下发待上报变成已上报 注意: 调用后,
    1429              :                 // ProfilingManager::StartReportSqeIdx为HCCL_SQE_MAX_CNT
    1430            0 :                 if (callback_ != nullptr) {
    1431            0 :                     hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1432            0 :                     hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1433            0 :                     callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1434            0 :                 }
    1435              : 
    1436              :                 // SQE ring buffer中所有SQE均为已上报 -> 清理SQE ring buffer
    1437            0 :                 HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] Sqe index to %u, need clear", HCCL_SQE_MAX_CNT);
    1438            0 :                 CHK_PRT_RET(
    1439              :                     sqeContextBuffer->sqeCnt != 0,
    1440              :                     HCCL_ERROR(
    1441              :                         "[DispatcherAicpu][MemcpyRtsq] Sqe index to %u, but sqeCnt[%u] is not 0", HCCL_SQE_MAX_CNT,
    1442              :                         sqeContextBuffer->sqeCnt),
    1443              :                     HCCL_E_INTERNAL);
    1444            0 :                 CHK_RET(stream.ClearLocalBuff()); // 会将stream.sqeContextBuffer中的sqeCnt和tailSqeIdx设置为0
    1445            0 :                 CHK_PRT_RET(
    1446              :                     sqeContextBuffer->sqeCnt != 0,
    1447              :                     HCCL_ERROR(
    1448              :                         "[DispatcherAicpu][MemcpyRtsq] sqeCnt[%u] should be 0 after clear", sqeContextBuffer->sqeCnt),
    1449              :                     HCCL_E_INTERNAL);
    1450            0 :                 CHK_PRT_RET(
    1451              :                     sqeContextBuffer->tailSqeIdx != 0,
    1452              :                     HCCL_ERROR(
    1453              :                         "[DispatcherAicpu][MemcpyRtsq] tailSqeIdx[%u] should be 0 after clear",
    1454              :                         sqeContextBuffer->tailSqeIdx),
    1455              :                     HCCL_E_INTERNAL);
    1456              : 
    1457              :                 // 参考HcclCommAicpu::ClearLocalBuff, 调用Stream::ClearLocalBuff后,
    1458              :                 // 应该调用ProfilingManager::UpdateStartReportSqeIdx手动将ProfilingManager::StartReportSqeIdx设置为0
    1459              :                 // 注意: 由于platform暂未将UpdateStartReportSqeIdx作为回调函数传入, 无法直接调用此framework函数 ->
    1460              :                 // 通过callback_ (即ProfilingManager::TaskProfilingCallBack)
    1461              :                 // 间接将ProfilingManager::StartReportSqeIdx设置为0 注意:
    1462              :                 // 由于调用前ProfilingManager::StartReportSqeIdx为HCCL_SQE_MAX_CNT, tailSqeIdx为0,
    1463              :                 // 即从startIdx=HCCL_SQE_MAX_CNT到endIdx=0, ProfilingManager不会进入profiling上报代码,
    1464              :                 // 而是只会调用UpdateStartReportSqeIdx设置StartReportSqeIdx为0
    1465            0 :                 if (callback_ != nullptr) {
    1466            0 :                     HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] re-invoke callback_ to reset StartReportSqeIdx as 0 in "
    1467              :                               "ProfilingManager");
    1468              : 
    1469            0 :                     hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1470            0 :                     hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1471            0 :                     callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1472            0 :                 }
    1473              :             }
    1474              :         }
    1475              :     }
    1476              : 
    1477            0 :     return HCCL_SUCCESS;
    1478              : }
    1479              : 
    1480            0 : HcclResult DispatcherAiCpu::AddFlipTask(Stream& stream)
    1481              : {
    1482            0 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
    1483            0 :     CHK_PTR_NULL(sqeContext);
    1484            0 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
    1485            0 :     CHK_PTR_NULL(sqeContextBuffer);
    1486            0 :     uint16_t flipNum = sqeContextBuffer->filpNum;
    1487            0 :     uint16_t taskId = sqeContextBuffer->tailSqeTaskId;
    1488              : 
    1489            0 :     if (callback_ != nullptr) {
    1490            0 :         hccl::FlipTaskPara para(stream.id(), taskId, flipNum);
    1491            0 :         hccl::TaskPara taskPara(TaskType::TASK_FLIP, para);
    1492            0 :         callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1493            0 :     }
    1494              : 
    1495            0 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1496              : 
    1497            0 :     uint8_t* sqeBufferAddr = nullptr;
    1498            0 :     uint8_t* sqeTypeAddr = nullptr;
    1499            0 :     uint8_t* sqeDfxInfoAddr = nullptr;
    1500            0 :     CHK_RET(stream.GetNextSqeBufferAddr(sqeBufferAddr, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1501              : 
    1502            0 :     AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
    1503            0 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
    1504            0 :     dfxInfo->remoteRank = INVALID_VALUE_RANKID;
    1505            0 :     dfxInfo->notifyId = INVALID_VALUE_RANKID;
    1506            0 :     addOneFlipPlaceHolderSqe_(streamInfo.actualStreamId, flipNum, taskId, sqeBufferAddr, sqeTypeAddr);
    1507              : 
    1508            0 :     PLF_CONFIG_INFO(
    1509              :         PLF_TASK, "%s para: taskId[%u] streamId[%u] flipNum[%u]", __func__, taskId, streamInfo.actualStreamId, flipNum);
    1510            0 :     return HCCL_SUCCESS;
    1511              : }
    1512              : 
    1513            0 : HcclResult DispatcherAiCpu::AddRetryPreamble(Stream& stream) { return AddFlipTask(stream); }
    1514              : 
    1515           22 : void DispatcherAiCpu::SaveStreamInfo(hccl::Stream& stream)
    1516              : {
    1517           22 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1518           22 :     auto it = streamMap_.find(streamInfo.actualStreamId);
    1519           22 :     if (it == streamMap_.end()) {
    1520           17 :         streamMap_.insert({streamInfo.actualStreamId, stream});
    1521           17 :         HCCL_INFO("[DispatcherAiCpu][SaveStreamInfo] stream id[%d]", streamInfo.actualStreamId);
    1522            5 :     } else if (it->second.IsInvalid()) {
    1523              :         // stream id复用: 旧stream已销毁(IsInvalid=true), 用新stream覆盖, 否则dispatcher会一直跳过该id
    1524            0 :         it->second = stream;
    1525            0 :         HCCL_INFO(
    1526              :             "[DispatcherAiCpu][SaveStreamInfo] refresh invalidated stream id stream id[%d]", streamInfo.actualStreamId);
    1527              :     }
    1528           44 :     return;
    1529              : }
    1530              : 
    1531            2 : HcclResult DispatcherAiCpu::StreamSync(Stream& stream)
    1532              : {
    1533            2 :     uint32_t head = 0;
    1534            2 :     uint32_t tail = 0;
    1535              :     const HcclComStreamInfo* streamInfo;
    1536            2 :     u64 startUsec = GetCurAicpuTimestamp();
    1537            2 :     u64 lastUsec = startUsec;
    1538            2 :     CHK_RET(stream.GetStreamInfo(streamInfo));
    1539              : 
    1540            2 :     CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo->sqId, DRV_SQCQ_PROP_SQ_TAIL, tail));
    1541            2 :     HCCL_INFO("StreamSync aicpu stream sqid[%d] tail[%u]", streamInfo->sqId, tail);
    1542              :     do {
    1543            2 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo->sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
    1544            2 :         u64 curUsec = GetCurAicpuTimestamp();
    1545            2 :         if (curUsec - startUsec > NANOSECOND_TO_SECOND * dfxTimeOutConfig_.sqeTimeOutTimeOut) {
    1546            1 :             HCCL_ERROR(
    1547              :                 "stream sync timeout %lus. curhead:%u, curtall:%u, sqId:%d", dfxTimeOutConfig_.sqeTimeOutTimeOut, head,
    1548              :                 tail, streamInfo->sqId);
    1549            1 :             return HCCL_E_TIMEOUT;
    1550              :         }
    1551              : 
    1552              :         // 等待下发阶段,每隔30s打印一次状态
    1553            1 :         if (curUsec - lastUsec > NANOSECOND_TO_SECOND * dfx::kPrintSqInterval) {
    1554            0 :             lastUsec = curUsec;
    1555            0 :             HCCL_RUN_INFO("[StreamSync]Current state. sqid:%d, head:%u, tail:%u", streamInfo->sqId, head, tail);
    1556              :         }
    1557            1 :     } while (head != tail);
    1558              : 
    1559            1 :     return HCCL_SUCCESS;
    1560              : }
    1561              : 
    1562            5 : u64 DispatcherAiCpu::CalcDbAddr(u32 dbindex)
    1563              : {
    1564            5 :     u64 dbAddr = 0;
    1565            5 :     if (aicpuInfo_.devType == DevType::DEV_TYPE_910_93) {
    1566              :         // 910_93 HCCS_SW 组网
    1567            2 :         constexpr u64 roceBaseAddr = 0x202000000000ULL;
    1568            2 :         constexpr u64 roceVfDbCfg0Reg = 0x230ULL;
    1569            2 :         constexpr u64 chipAddrOffset = 0x20000000000ULL;
    1570            2 :         constexpr u64 dieAddrOffset = 0x10000000000ULL;
    1571            2 :         constexpr u32 dbDieIdMask = 0x00ff0000;
    1572            2 :         constexpr u32 dbDieIdShift = 16; // 16 is dbDieIdShift
    1573            2 :         dbAddr = roceBaseAddr + roceVfDbCfg0Reg + chipAddrOffset * aicpuInfo_.chipId
    1574            2 :                  + dieAddrOffset * ((dbindex & dbDieIdMask) >> dbDieIdShift);
    1575              :     } else {
    1576            3 :         constexpr u64 roceBaseAddr = 0x2000000000ULL;
    1577            3 :         constexpr u64 roceVfDbCfg0Reg = 0x230ULL;
    1578            3 :         constexpr u64 chipAddrOffset = 0x80000000000ULL;
    1579            3 :         constexpr u64 dieAddrOffset = 0x10000000000ULL;
    1580            3 :         constexpr u32 dbDieIdMask = 0x00ff0000;
    1581            3 :         constexpr u32 dbDieIdShift = 16; // 16 is dbDieIdShift
    1582            3 :         dbAddr = roceBaseAddr + roceVfDbCfg0Reg + chipAddrOffset * aicpuInfo_.chipId
    1583            3 :                  + dieAddrOffset * ((dbindex & dbDieIdMask) >> dbDieIdShift);
    1584              :     }
    1585              : 
    1586            5 :     HCCL_DEBUG(
    1587              :         "%s dbindex:%u, devType:%u, chipId:%lld, dbAddr:%llu", __func__, dbindex, aicpuInfo_.devType, aicpuInfo_.chipId,
    1588              :         dbAddr);
    1589            5 :     return dbAddr;
    1590              : }
    1591              : 
    1592          449 : void DispatcherAiCpu::InitTimeOutConfig()
    1593              : {
    1594          449 :     dfxTimeOutConfig_.useCredit = false;
    1595          449 :     dfxTimeOutConfig_.sqeTimeOutTimeOut = GetMaxNotifyWaitTime();
    1596          449 :     dfxTimeOutConfig_.sqeCreditTimeOut = RT_STARS_NEVER_TIMEOUT_KERNEL_CREDIT;
    1597          449 :     dfxTimeOutConfig_.sqeWaitTimeOut = dfx::kKfcTimeOut;
    1598          449 :     dfxTimeOutConfig_.sqFullWaitTimeOut = dfx::kSqFullWaitTimeOut;
    1599          449 :     HCCL_INFO(
    1600              :         "[DispatcherAiCpu][InitTimeOutConfig]DFX timeout config init successfully with details: [%s]",
    1601              :         dfxTimeOutConfig_.ToString().c_str());
    1602          449 : }
    1603              : } // namespace hccl
        

Generated by: LCOV version 2.0-1