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-17 10:19:35 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          446 :     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          446 :         addOneNotifyWaitSqe_ = AddOneNotifyWaitSqeV1;
      83          446 :         addOneRecordSqe_ = AddOneRecordSqeV1;
      84          446 :         addOneWriteValueRecordSqe_ = AddOneWriteValueRecordSqeV1;
      85          446 :         addOneMemcpySqe_ = AddOneMemcpySqeV1;
      86          446 :         addOneEventResetSqe_ = AddOneEventResetSqeV1;
      87          446 :         addOneEventRecordSqe_ = AddOneEventRecordSqeV1;
      88          446 :         addOneEventWaitSqe_ = AddOneEventWaitSqeV1;
      89          446 :         addOneRdmaDbSendSqe_ = AddOneRdmaDbSendSqeV1;
      90          446 :         addOneFlipPlaceHolderSqe_ = AddOneFlipPlaceHolderSqeV1;
      91          446 :         addOneCacheMemcpyPlaceHolderSqe_ = AddOneCacheMemcpyPlaceHolderSqeV1;
      92          446 :         addOneCacheNotifyWaitPlaceholderSqe_ = AddOneCacheNotifyWaitPlaceholderSqeV1;
      93          446 :         addOneCacheNotifyRecordPlaceholderSqe_ = AddOneCacheNotifyRecordPlaceholderSqeV1;
      94          446 :         addOneCacheWriteValuePlaceholderSqe_ = AddOneCacheWriteValuePlaceholderSqeV1;
      95          446 :         addOneCacheMemcpyRecordPlaceholderSqe_ = AddOneCacheMemcpyRecordPlaceholderSqeV1;
      96          446 :         CHK_PTR_NULL(addOneRdmaDbSendSqe_);
      97          446 :         CHK_PTR_NULL(addOneFlipPlaceHolderSqe_);
      98          446 :         CHK_PTR_NULL(addOneCacheMemcpyPlaceHolderSqe_);
      99          446 :         CHK_PTR_NULL(addOneCacheNotifyWaitPlaceholderSqe_);
     100          446 :         CHK_PTR_NULL(addOneCacheNotifyRecordPlaceholderSqe_);
     101          446 :         CHK_PTR_NULL(addOneCacheWriteValuePlaceholderSqe_);
     102          446 :         CHK_PTR_NULL(addOneCacheMemcpyRecordPlaceholderSqe_);
     103              :     }
     104              : 
     105          446 :     CHK_PTR_NULL(addOneNotifyWaitSqe_);
     106          446 :     CHK_PTR_NULL(addOneRecordSqe_);
     107          446 :     CHK_PTR_NULL(addOneWriteValueRecordSqe_);
     108          446 :     CHK_PTR_NULL(addOneMemcpySqe_);
     109          446 :     CHK_PTR_NULL(addOneEventResetSqe_);
     110          446 :     CHK_PTR_NULL(addOneEventRecordSqe_);
     111          446 :     CHK_PTR_NULL(addOneEventWaitSqe_);
     112              : 
     113          446 :     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              :     HcclRtNotify signal, hccl::Stream& stream, u32 userRank, u64 offset, s32 stage, bool inchip, u64 signalAddr,
     173              :     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              :     HcclRtNotify signal, Stream& stream, u32 userRank, u32 remoteUserRank, s32 stage, bool inchip, u32 notifyId,
     289              :     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      3185506 :     while (((tail < head ? streamInfo.sqDepth : 0U) + tail - head + cnt >= streamInfo.sqDepth)
     726      3185506 :            && (tail != head)) { // 判断剩余sqe空间是否足够下发
     727              :         // 需要放在while循环进来后第一个执行
     728      3185504 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
     729              : 
     730              :         // 非阻塞下发场景,rtsq队列空间不足时直接返回
     731      3185504 :         if (isBlockLaunch == false) {
     732            0 :             return HCCL_SUCCESS;
     733              :         }
     734              : 
     735              :         // 当前流无法下发,把其他流都launch一遍,避免等待的其他流没有launch
     736      4774138 :         for (auto it = streamMap_.begin(); it != streamMap_.end(); ++it) {
     737      1588634 :             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      3185504 :         u64 curUsec = GetCurAicpuTimestamp();
     748      3185504 :         if (dfxTimeOutConfig_.sqFullWaitTimeOut != 0
     749      3185503 :             && (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      3185502 :         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      3185502 :         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              :     const void* src1, const void* src2, u64 count, const HcclDataType datatype, HcclReduceOp redOp, Stream& stream,
    1048              :     const void* dst)
    1049              : {
    1050            1 :     HCCL_ERROR("[DispatcherAiCpu][TbeReduceAsync] aicpu do not support the tbe reduce");
    1051            1 :     return HCCL_E_NOT_SUPPORT;
    1052              : }
    1053              : 
    1054            5 : HcclResult DispatcherAiCpu::RdmaSend(u32 dbindex, u64 dbinfo, hccl::Stream& stream, RdmaTaskInfo& taskInfo)
    1055              : {
    1056            5 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1057              : 
    1058            5 :     uint8_t* sqeBuffer = nullptr;
    1059            5 :     uint8_t* sqeTypeAddr = nullptr;
    1060            5 :     uint8_t* sqeDfxInfoAddr = nullptr;
    1061            5 :     uint16_t taskId = 0U;
    1062              : 
    1063            5 :     CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1064            5 :     AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
    1065            5 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
    1066            5 :     dfxInfo->remoteRank = taskInfo.remoteRank;
    1067            5 :     dfxInfo->notifyId = INVALID_UINT; // 多个wr只敲一次doorbell的情况下,一般只会有一个notify
    1068              : 
    1069            5 :     uint32_t wrLen = 0; // 统计wr的总数据量
    1070            5 :     for (const WrInformation& wr : taskInfo.wrInfos) {
    1071            0 :         wrLen += wr.wrData.memList.len;
    1072            0 :         dfxInfo->notifyId = (wr.notifyId != INVALID_UINT) ? wr.notifyId : dfxInfo->notifyId;
    1073              :     }
    1074              : 
    1075            5 :     u64 dbAddr = CalcDbAddr(dbindex);
    1076            5 :     addOneRdmaDbSendSqe_(
    1077            5 :         streamInfo.actualStreamId, taskId, dbinfo, dbAddr, wrLen, static_cast<uint8_t>(taskInfo.rdmaType), sqeBuffer,
    1078              :         sqeTypeAddr);
    1079              : 
    1080            5 :     PLF_CONFIG_INFO(
    1081              :         PLF_TASK, "%s para: streamId[%u] taskId[%u] remoteRank[%u] RdmaType[%d] wrLen[%u] notifyId[%u]", __func__,
    1082              :         streamInfo.actualStreamId, taskId, taskInfo.remoteRank, taskInfo.rdmaType, wrLen, dfxInfo->notifyId);
    1083              : 
    1084            5 :     return HCCL_SUCCESS;
    1085              : }
    1086              : 
    1087            0 : HcclResult DispatcherAiCpu::RdmaRecord(
    1088              :     u32 dbindex, u64 dbinfo, const struct SendWr& wr, hccl::Stream& stream, RdmaType rdmaType, u32 userRank, u64 offset,
    1089              :     u32 notifyId)
    1090              : {
    1091            0 :     return HCCL_SUCCESS;
    1092              : }
    1093              : 
    1094           13 : HcclResult DispatcherAiCpu::GetStreamSqeBufferAddr(
    1095              :     hccl::Stream& stream, uint8_t*& sqeBufferAddr, uint8_t*& sqeTypeAddr, uint8_t*& sqeDfxInfoAddr, uint16_t& taskId)
    1096              : {
    1097           13 :     SaveStreamInfo(stream);
    1098           13 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
    1099           13 :     CHK_PTR_NULL(sqeContext);
    1100           13 :     if (UNLIKELY(sqeContext->buffer.sqeCnt >= HCCL_PER_LAUNCH_SQE_CNT)) {
    1101            0 :         HCCL_INFO("GetStreamSqeBufferAddr tailSqeIdx[%u], try to launchTask", sqeContext->buffer.tailSqeIdx);
    1102            0 :         CHK_RET(LaunchTask(stream, true));
    1103              :     }
    1104           13 :     if (UNLIKELY(sqeContext->buffer.tailSqeIdx >= HCCL_SQE_MAX_CNT)) {
    1105            0 :         CHK_RET(LaunchTask(stream, true));
    1106              : 
    1107            0 :         if (callback_ != nullptr) {
    1108            0 :             hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1109            0 :             hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1110            0 :             callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1111            0 :         }
    1112              :     }
    1113           13 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
    1114           13 :     uint16_t flipNum = sqeContextBuffer->filpNum;
    1115           13 :     uint16_t nextTaskId = sqeContextBuffer->tailSqeTaskId;
    1116              :     // nextTaskId=0的时候下发PlaceHolder
    1117           13 :     if (UNLIKELY(nextTaskId == 0 && flipNum != 0)) {
    1118            0 :         CHK_RET(AddFlipTask(stream));
    1119              :     }
    1120           13 :     if (UNLIKELY(sqeContext->buffer.tailSqeIdx >= HCCL_SQE_MAX_CNT)) {
    1121            0 :         CHK_RET(LaunchTask(stream, true));
    1122              : 
    1123            0 :         if (callback_ != nullptr) {
    1124            0 :             hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1125            0 :             hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1126            0 :             callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1127            0 :         }
    1128              :     }
    1129           13 :     CHK_RET(stream.GetNextSqeBufferAddr(sqeBufferAddr, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1130           13 :     return HCCL_SUCCESS;
    1131              : }
    1132              : 
    1133            2 : HcclResult DispatcherAiCpu::WaitRtsq(Stream& stream, const size_t& sqeCount, const bool isBlockLaunch)
    1134              : {
    1135              :     // 注意: 目前WaitRtsq不会被递归调用, 所以isBlockLaunch永远为true; 为防止以后LaunchTask递归使用WaitRtsq,
    1136              :     // 编码时考虑isBlockLaunch为false的情况
    1137              : 
    1138              :     // 检验入参
    1139            2 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1140            2 :     if (sqeCount == 0) {
    1141            0 :         CHK_PRT_CONT(
    1142              :             isBlockLaunch, HCCL_DEBUG(
    1143              :                                "[DispatcherAiCpu][WaitRtsq] no sqe, streamId:%d, sqId:%u", streamInfo.actualStreamId,
    1144              :                                streamInfo.sqId));
    1145            0 :         return HCCL_SUCCESS;
    1146            2 :     } else if (sqeCount > streamInfo.sqDepth) {
    1147            0 :         HCCL_ERROR(
    1148              :             "[DispatcherAiCpu][WaitRtsq] sqeCount %u should be smaller than sqDepth %u]", sqeCount, streamInfo.sqDepth);
    1149            0 :         return HCCL_E_PTR;
    1150              :     }
    1151              : 
    1152              :     // Get head and tail of RTSQ ring buffer
    1153            2 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
    1154            2 :     CHK_PTR_NULL(sqeContext);
    1155            2 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
    1156            2 :     CHK_PTR_NULL(sqeContextBuffer);
    1157            2 :     uint32_t& head = sqeContextBuffer->sqHead;
    1158            2 :     uint32_t& tail = sqeContextBuffer->sqTail;
    1159              : 
    1160              :     // Dump debug information
    1161            2 :     const uint32_t newTail = (tail + sqeCount) % streamInfo.sqDepth;
    1162              :     // 仅在阻塞下发场景打印,避免非阻塞场景调用时刷屏
    1163            2 :     CHK_PRT_CONT(
    1164              :         isBlockLaunch, HCCL_INFO(
    1165              :                            "[DispatcherAicpu][WaitRtsq] sqid:%d sqeCount:%u head:%u curtail:%u newTail:%u",
    1166              :                            streamInfo.sqId, sqeCount, head, tail, newTail));
    1167              : 
    1168              :     // 轮询RTSQ直至获得足够大的剩余空间
    1169            2 :     u64 startUsec = GetCurAicpuTimestamp();
    1170            2 :     u64 lastUsec = startUsec;
    1171            3 :     while (((tail < head ? streamInfo.sqDepth : 0U) + tail - head + sqeCount >= streamInfo.sqDepth)
    1172            3 :            && (tail != head)) { // 判断RTSQ中剩余sqe空间是否足够下发
    1173              :         // 需要放在while循环进来后第一个执行 (获取最新的RTSQ head, 查看RTSQ的消费进度)
    1174            2 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
    1175              : 
    1176              :         // 非阻塞下发场景,rtsq队列空间不足时直接返回
    1177            2 :         if (isBlockLaunch == false) {
    1178            1 :             return HCCL_SUCCESS;
    1179              :         }
    1180              : 
    1181              :         // 当前流无法下发,把其他流都launch一遍,避免等待的其他流没有launch
    1182            2 :         for (auto it = streamMap_.begin(); it != streamMap_.end(); ++it) {
    1183            1 :             if (it->first != streamInfo.actualStreamId) { // 不是当前stream
    1184            1 :                 if (it->second.IsInvalid()) { // 跳过已销毁的stream (streamMap_只增不删, 原stream销毁后副本通过shared
    1185              :                                               // invalid标志感知)
    1186            0 :                     HCCL_WARNING(
    1187              :                         "[DispatcherAiCpu][WaitRtsq] skip invalid stream in streamMap, streamId:%d", it->first);
    1188            0 :                     continue;
    1189              :                 }
    1190            1 :                 CHK_RET(LaunchTask(it->second, false)); // 非阻塞launch
    1191              :             }
    1192              :         }
    1193              : 
    1194              :         // 等待超时
    1195            1 :         u64 curUsec = GetCurAicpuTimestamp();
    1196            1 :         if (dfxTimeOutConfig_.sqFullWaitTimeOut != 0
    1197            0 :             && (curUsec - startUsec > NANOSECOND_TO_SECOND * dfxTimeOutConfig_.sqFullWaitTimeOut)) {
    1198            0 :             HCCL_ERROR(
    1199              :                 "[DispatcherAicpu][WaitRtsq] Rtsq full, timeout %lus. curhead:%u, sqId:%d",
    1200              :                 dfxTimeOutConfig_.sqFullWaitTimeOut, head, streamInfo.sqId);
    1201            0 :             return HCCL_E_AGAIN;
    1202              :         }
    1203              : 
    1204              :         // 等待下发阶段,每隔30s打印一次状态
    1205            1 :         if (curUsec - lastUsec > NANOSECOND_TO_SECOND * dfx::kPrintSqInterval) {
    1206            0 :             lastUsec = curUsec;
    1207            0 :             HCCL_RUN_INFO(
    1208              :                 "[DispatcherAicpu][WaitRtsq] Current state. sqid:%d, head:%u, tail:%u, sqeCount:%u", streamInfo.sqId,
    1209              :                 head, tail, sqeCount);
    1210              :         }
    1211              : 
    1212              :         // 等待下发过程中出现cqe异常, 需要终止当前算子SQE的下发过程
    1213            1 :         if (checkOpExecStatusCallback_ != nullptr) {
    1214            0 :             HcclResult opExecStatus = checkOpExecStatusCallback_();
    1215            0 :             CHK_PRT_RET(
    1216              :                 opExecStatus != HCCL_SUCCESS,
    1217              :                 HCCL_ERROR(
    1218              :                     "[DispatcherAicpu][WaitRtsq] hccl aicpu stop launch for task exception or stop command, ret:%d",
    1219              :                     opExecStatus),
    1220              :                 opExecStatus);
    1221              :         }
    1222              :     }
    1223              : 
    1224            1 :     return HCCL_SUCCESS;
    1225              : }
    1226              : 
    1227            0 : HcclResult DispatcherAiCpu::MemcpyRtsq(
    1228              :     Stream& stream, const size_t sqeCount, const uint8_t* sqeArray, const uint8_t* sqeTypeArray,
    1229              :     const AicpuDfxInfo* sqeDfxInfoArray, const bool profL1Enable, const std::vector<uint64_t>& profTimestamps,
    1230              :     const size_t profTimestampStartIdx)
    1231              : {
    1232              :     // 检验入参
    1233            0 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1234            0 :     if (sqeCount == 0) {
    1235            0 :         HCCL_DEBUG(
    1236              :             "[DispatcherAiCpu][MemcpyRtsq] no sqe, streamId:%d, sqId:%u", streamInfo.actualStreamId, streamInfo.sqId);
    1237            0 :         return HCCL_SUCCESS;
    1238            0 :     } else if (sqeCount > streamInfo.sqDepth) {
    1239            0 :         HCCL_ERROR(
    1240              :             "[DispatcherAiCpu][MemcpyRtsq] sqeCount %u should be smaller than sqDepth %u]", sqeCount,
    1241              :             streamInfo.sqDepth);
    1242            0 :         return HCCL_E_PTR;
    1243              :     }
    1244            0 :     CHK_PTR_NULL(sqeArray);
    1245            0 :     CHK_PTR_NULL(sqeTypeArray);
    1246            0 :     CHK_PTR_NULL(sqeDfxInfoArray);
    1247            0 :     if (profL1Enable) {
    1248              :         // 会访问profTimestamps[profTimestampStartIdx, profTimestampStartIdx + sqeCount - 1]
    1249            0 :         CHK_PRT_RET(
    1250              :             profTimestamps.size() == 0, HCCL_ERROR("[DispatcherAiCpu][MemcpyRtsq] empty profTimestamps"),
    1251              :             HCCL_E_INTERNAL);
    1252            0 :         CHK_PRT_RET(
    1253              :             profTimestampStartIdx >= profTimestamps.size(),
    1254              :             HCCL_ERROR(
    1255              :                 "[DispatcherAiCpu][MemcpyRtsq] profTimestampStartIdx[%u] >= profTimestamps.size[%u]",
    1256              :                 profTimestampStartIdx, profTimestamps.size()),
    1257              :             HCCL_E_INTERNAL);
    1258            0 :         CHK_PRT_RET(
    1259              :             (profTimestampStartIdx + sqeCount - 1) >= profTimestamps.size(),
    1260              :             HCCL_ERROR(
    1261              :                 "[DispatcherAiCpu][MemcpyRtsq] profTimestampStartIdx[%u] + sqeCount[%u] - 1 >= profTimestamps.size[%u]",
    1262              :                 profTimestampStartIdx, sqeCount, profTimestamps.size()),
    1263              :             HCCL_E_INTERNAL);
    1264              :     }
    1265              : 
    1266              :     // 获得RTSQ的head和tail
    1267            0 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
    1268            0 :     CHK_PTR_NULL(sqeContext);
    1269            0 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
    1270            0 :     CHK_PTR_NULL(sqeContextBuffer);
    1271            0 :     uint32_t& head = sqeContextBuffer->sqHead;
    1272            0 :     uint32_t& tail = sqeContextBuffer->sqTail;
    1273              : 
    1274              :     // Dump debug information
    1275            0 :     const uint32_t newTail = (tail + sqeCount) % streamInfo.sqDepth;
    1276            0 :     HCCL_INFO(
    1277              :         "[DispatcherAicpu][MemcpyRtsq] before memcpy, sqid:%d sqeCount:%u head:%u curtail:%u newTail:%u",
    1278              :         streamInfo.sqId, sqeCount, head, tail, newTail);
    1279              : 
    1280              :     // 准备memcpy中目的末端基地址 (RTSQ从tail开始拷贝, [head, tail)为待执行SQE)
    1281            0 :     uint8_t* rtsqSqeTailBaseAddr = reinterpret_cast<uint8_t*>(streamInfo.sqBaseAddr) + tail * HCCL_SQE_SIZE;
    1282            0 :     uint8_t* mirrorRtsqSqeTailBaseAddr = sqeContextBuffer->rtsMirrorBuffer + tail * HCCL_SQE_SIZE;
    1283            0 :     uint8_t* rtsqSqeTypeTailBaseAddr = sqeContextBuffer->rtsqSqeType + tail;
    1284            0 :     AicpuDfxInfo* rtsqDfxInfoTailBaseAddr = sqeContextBuffer->rtsDfxInfo + tail;
    1285              : 
    1286            0 :     uint32_t tailLeft = streamInfo.sqDepth - tail; // RTSQ tail到buffer末端的剩余空间 (不包括buffer前端到head的剩余空间)
    1287            0 :     HCCL_INFO(
    1288              :         "[DispatcherAicpu][MemcpyRtsq] cpy sqe, tailLeft:%u, sqeCount:%u, streamId:%u", tailLeft, sqeCount,
    1289              :         stream.id());
    1290            0 :     if (sqeCount <= tailLeft) { // buffer末端剩余空间放得下新增sqe
    1291              :         // 向buffer末端拷贝sqeCount个SQE信息
    1292              : 
    1293              :         // 拷贝SQE内容到RTSQ
    1294            0 :         CHK_SAFETY_FUNC_RET(
    1295              :             memcpy_s(rtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, sqeCount * HCCL_SQE_SIZE));
    1296              : 
    1297              :         // 拷贝SQE内容到RTSQ mirror
    1298            0 :         CHK_SAFETY_FUNC_RET(
    1299              :             memcpy_s(mirrorRtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, sqeCount * HCCL_SQE_SIZE));
    1300              : 
    1301              :         // 拷贝SQE类型
    1302            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqSqeTypeTailBaseAddr, tailLeft, sqeTypeArray, sqeCount));
    1303              : 
    1304              :         // 拷贝SQE DfxInfo
    1305            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1306              :             rtsqDfxInfoTailBaseAddr, tailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray,
    1307              :             sqeCount * sizeof(AicpuDfxInfo)));
    1308              :     } else { // 需要buffer末端和首端的剩余空间
    1309              :         // 先向buffer末端拷贝tailLeft个SQE信息, 再向buffer首端拷贝sqeCount-tailLeft个SQE信息
    1310              : 
    1311              :         // 拷贝SQE内容到RTSQ
    1312            0 :         CHK_SAFETY_FUNC_RET(
    1313              :             memcpy_s(rtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, tailLeft * HCCL_SQE_SIZE));
    1314            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1315              :             reinterpret_cast<uint8_t*>(streamInfo.sqBaseAddr), streamInfo.sqDepth * HCCL_SQE_SIZE,
    1316              :             sqeArray + tailLeft * HCCL_SQE_SIZE, (sqeCount - tailLeft) * HCCL_SQE_SIZE));
    1317              : 
    1318              :         // 拷贝SQE内容到RTSQ mirror
    1319            0 :         CHK_SAFETY_FUNC_RET(
    1320              :             memcpy_s(mirrorRtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, tailLeft * HCCL_SQE_SIZE));
    1321            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1322              :             sqeContextBuffer->rtsMirrorBuffer, streamInfo.sqDepth * HCCL_SQE_SIZE, sqeArray + tailLeft * HCCL_SQE_SIZE,
    1323              :             (sqeCount - tailLeft) * HCCL_SQE_SIZE));
    1324              : 
    1325              :         // 拷贝SQE type
    1326            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqSqeTypeTailBaseAddr, tailLeft, sqeTypeArray, tailLeft));
    1327            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1328              :             sqeContextBuffer->rtsqSqeType, streamInfo.sqDepth, sqeTypeArray + tailLeft, (sqeCount - tailLeft)));
    1329              : 
    1330              :         // 拷贝SQE DfxInfo
    1331            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1332              :             rtsqDfxInfoTailBaseAddr, tailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray,
    1333              :             tailLeft * sizeof(AicpuDfxInfo)));
    1334            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(
    1335              :             sqeContextBuffer->rtsDfxInfo, streamInfo.sqDepth * sizeof(AicpuDfxInfo), sqeDfxInfoArray + tailLeft,
    1336              :             (sqeCount - tailLeft) * sizeof(AicpuDfxInfo)));
    1337              :     }
    1338              : 
    1339              :     // 更新RTSQ ring buffer的tail
    1340            0 :     CHK_RET(ConfigSqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_TAIL, newTail));
    1341            0 :     tail = newTail;
    1342            0 :     PLF_CONFIG_INFO(
    1343              :         PLF_TASK, "%s success, sqid:%d, sqe_num:%u, curHead:%u, curtail:%u", __func__, streamInfo.sqId, sqeCount, head,
    1344              :         tail);
    1345              : 
    1346              :     // 上报profiling信息
    1347            0 :     if (profL1Enable) {
    1348              :         // Cache hit下SQE ring buffer中[tail-cnt, tail)为待下发SQE, 其数量一定为0 (否则更新tailSqeIdx后,
    1349              :         // 会导致待下发SQE未下发, 而已下发SQE重复下发)
    1350            0 :         CHK_PRT_RET(
    1351              :             sqeContextBuffer->sqeCnt != 0,
    1352              :             HCCL_ERROR(
    1353              :                 "[DispatcherAicpu][MemcpyRtsq] sqeContextBuffer->sqeCnt[%u] should be zero!", sqeContextBuffer->sqeCnt),
    1354              :             HCCL_E_INTERNAL);
    1355              : 
    1356              :         // 上报flip placeholder的profiling信息
    1357            0 :         if ((*sqeTypeArray) == SqeType::FLIP_PLACEHOLDER_SQE) {
    1358            0 :             CHK_PRT_RET(
    1359              :                 sqeCount != 1, HCCL_ERROR("[DispatcherAicpu][MemcpyRtsq] sqeCount[%u] should be 1!", sqeCount),
    1360              :                 HCCL_E_INTERNAL);
    1361              : 
    1362              :             // 注意: 参考AddFlipTask, 先上报flip task (提醒profiling翻转taskid), 之后再拷贝到SQE ring buffer
    1363              :             // (捕捉placeholder SQE相关的profiling信息) 注意:
    1364              :             // ProfilingManager::TaskProfilingCallBack->ReportFilpTask不会扫描SQE ring buffer,
    1365              :             // 也不会更新其中的streamToSqeIdxMap_
    1366            0 :             if (callback_ != nullptr) {
    1367            0 :                 const rtStarsPlaceHolderSqe_t* placeholderSqePtr
    1368              :                     = reinterpret_cast<const rtStarsPlaceHolderSqe_t*>(sqeArray);
    1369              :                 hccl::FlipTaskPara para(
    1370            0 :                     stream.id(), placeholderSqePtr->header.taskId, placeholderSqePtr->u.flip_task_info.flipNumReport);
    1371            0 :                 hccl::TaskPara taskPara(TaskType::TASK_FLIP, para);
    1372            0 :                 callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1373            0 :             }
    1374              :         }
    1375              : 
    1376              :         // 循环拷贝cached SQE到SQE ring buffer中
    1377            0 :         size_t reportSqeCount = 0;
    1378            0 :         while (reportSqeCount < sqeCount) {
    1379            0 :             CHK_PRT_RET(
    1380              :                 sqeContextBuffer->tailSqeIdx > HCCL_SQE_MAX_CNT,
    1381              :                 HCCL_ERROR(
    1382              :                     "[DispatcherAicpu][MemcpyRtsq] tailSqeIdx[%u] > HCCL_SQE_MAX_CNT[%u]", sqeContextBuffer->tailSqeIdx,
    1383              :                     HCCL_SQE_MAX_CNT),
    1384              :                 HCCL_E_INTERNAL);
    1385            0 :             const size_t sqeTailLeft = HCCL_SQE_MAX_CNT - sqeContextBuffer->tailSqeIdx;
    1386            0 :             if (sqeTailLeft > 0) {
    1387              :                 // 准备profiling上报的目的末端基地址 (SQE ring buffer从tail开始拷贝)
    1388            0 :                 uint8_t* sqeLocalBuffTailBaseAddr
    1389            0 :                     = sqeContextBuffer->localBuff + sqeContextBuffer->tailSqeIdx * HCCL_SQE_SIZE;
    1390            0 :                 uint8_t* sqeTypeTailBaseAddr = sqeContextBuffer->sqeType + sqeContextBuffer->tailSqeIdx;
    1391            0 :                 AicpuDfxInfo* dfxInfoTailBaseAddr = sqeContextBuffer->dfxInfo + sqeContextBuffer->tailSqeIdx;
    1392            0 :                 uint64_t* profTimestapTailBaseAddr = sqeContextBuffer->profTimestap + sqeContextBuffer->tailSqeIdx;
    1393              : 
    1394              :                 // 向SQE ring buffer末端拷贝SQE信息[reportSqeCount, reportSqeCount + tmpSqeCount - 1]
    1395              :                 // (只用于profiling上报, 不会下发)
    1396            0 :                 const size_t tmpSqeCount = std::min(sqeCount - reportSqeCount, sqeTailLeft);
    1397            0 :                 HCCL_INFO(
    1398              :                     "[DispatcherAicpu][MemcpyRtsq] report sqe profiling, sqeCount[%u] reportSqeCount[%u] "
    1399              :                     "tailSqeIdx[%u] sqeTailLeft[%u] tmpSqeCount[%u]",
    1400              :                     sqeCount, reportSqeCount, sqeContextBuffer->tailSqeIdx, sqeTailLeft, tmpSqeCount);
    1401              : 
    1402              :                 // 拷贝SQE内容
    1403            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(
    1404              :                     sqeLocalBuffTailBaseAddr, sqeTailLeft * HCCL_SQE_SIZE, sqeArray + reportSqeCount * HCCL_SQE_SIZE,
    1405              :                     tmpSqeCount * HCCL_SQE_SIZE));
    1406              : 
    1407              :                 // 拷贝SQE类型
    1408            0 :                 CHK_SAFETY_FUNC_RET(
    1409              :                     memcpy_s(sqeTypeTailBaseAddr, sqeTailLeft, sqeTypeArray + reportSqeCount, tmpSqeCount));
    1410              : 
    1411              :                 // 拷贝SQE DfxInfo
    1412            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(
    1413              :                     dfxInfoTailBaseAddr, sqeTailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray + reportSqeCount,
    1414              :                     tmpSqeCount * sizeof(AicpuDfxInfo)));
    1415              : 
    1416              :                 // 拷贝SQE timestamp
    1417            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(
    1418              :                     profTimestapTailBaseAddr, sqeTailLeft * sizeof(uint64_t),
    1419              :                     profTimestamps.data() + profTimestampStartIdx + reportSqeCount, tmpSqeCount * sizeof(uint64_t)));
    1420              : 
    1421              :                 // 注意: sqeContextBuffer->sqeCnt不更新, 仍然为0 (即拷贝的SQE信息为已下发待上报), 避免SQE重复下发
    1422            0 :                 sqeContextBuffer->tailSqeIdx += static_cast<uint16_t>(tmpSqeCount);
    1423            0 :                 reportSqeCount += tmpSqeCount;
    1424              :             } else {
    1425              :                 // 注意: SQE ring buffer中待下发SQE数量一定为0, 不需要调用LaunchTask将待下发变成已下发待上报,
    1426              :                 // 可以直接上报profiling将已下发待上报变成已上报 注意: 调用后,
    1427              :                 // ProfilingManager::StartReportSqeIdx为HCCL_SQE_MAX_CNT
    1428            0 :                 if (callback_ != nullptr) {
    1429            0 :                     hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1430            0 :                     hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1431            0 :                     callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1432            0 :                 }
    1433              : 
    1434              :                 // SQE ring buffer中所有SQE均为已上报 -> 清理SQE ring buffer
    1435            0 :                 HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] Sqe index to %u, need clear", HCCL_SQE_MAX_CNT);
    1436            0 :                 CHK_PRT_RET(
    1437              :                     sqeContextBuffer->sqeCnt != 0,
    1438              :                     HCCL_ERROR(
    1439              :                         "[DispatcherAicpu][MemcpyRtsq] Sqe index to %u, but sqeCnt[%u] is not 0", HCCL_SQE_MAX_CNT,
    1440              :                         sqeContextBuffer->sqeCnt),
    1441              :                     HCCL_E_INTERNAL);
    1442            0 :                 CHK_RET(stream.ClearLocalBuff()); // 会将stream.sqeContextBuffer中的sqeCnt和tailSqeIdx设置为0
    1443            0 :                 CHK_PRT_RET(
    1444              :                     sqeContextBuffer->sqeCnt != 0,
    1445              :                     HCCL_ERROR(
    1446              :                         "[DispatcherAicpu][MemcpyRtsq] sqeCnt[%u] should be 0 after clear", sqeContextBuffer->sqeCnt),
    1447              :                     HCCL_E_INTERNAL);
    1448            0 :                 CHK_PRT_RET(
    1449              :                     sqeContextBuffer->tailSqeIdx != 0,
    1450              :                     HCCL_ERROR(
    1451              :                         "[DispatcherAicpu][MemcpyRtsq] tailSqeIdx[%u] should be 0 after clear",
    1452              :                         sqeContextBuffer->tailSqeIdx),
    1453              :                     HCCL_E_INTERNAL);
    1454              : 
    1455              :                 // 参考HcclCommAicpu::ClearLocalBuff, 调用Stream::ClearLocalBuff后,
    1456              :                 // 应该调用ProfilingManager::UpdateStartReportSqeIdx手动将ProfilingManager::StartReportSqeIdx设置为0
    1457              :                 // 注意: 由于platform暂未将UpdateStartReportSqeIdx作为回调函数传入, 无法直接调用此framework函数 ->
    1458              :                 // 通过callback_ (即ProfilingManager::TaskProfilingCallBack)
    1459              :                 // 间接将ProfilingManager::StartReportSqeIdx设置为0 注意:
    1460              :                 // 由于调用前ProfilingManager::StartReportSqeIdx为HCCL_SQE_MAX_CNT, tailSqeIdx为0,
    1461              :                 // 即从startIdx=HCCL_SQE_MAX_CNT到endIdx=0, ProfilingManager不会进入profiling上报代码,
    1462              :                 // 而是只会调用UpdateStartReportSqeIdx设置StartReportSqeIdx为0
    1463            0 :                 if (callback_ != nullptr) {
    1464            0 :                     HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] re-invoke callback_ to reset StartReportSqeIdx as 0 in "
    1465              :                               "ProfilingManager");
    1466              : 
    1467            0 :                     hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1468            0 :                     hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1469            0 :                     callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1470            0 :                 }
    1471              :             }
    1472              :         }
    1473              :     }
    1474              : 
    1475            0 :     return HCCL_SUCCESS;
    1476              : }
    1477              : 
    1478            0 : HcclResult DispatcherAiCpu::AddFlipTask(Stream& stream)
    1479              : {
    1480            0 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
    1481            0 :     CHK_PTR_NULL(sqeContext);
    1482            0 :     SqeRingBuffer* sqeContextBuffer = &(sqeContext->buffer);
    1483            0 :     CHK_PTR_NULL(sqeContextBuffer);
    1484            0 :     uint16_t flipNum = sqeContextBuffer->filpNum;
    1485            0 :     uint16_t taskId = sqeContextBuffer->tailSqeTaskId;
    1486              : 
    1487            0 :     if (callback_ != nullptr) {
    1488            0 :         hccl::FlipTaskPara para(stream.id(), taskId, flipNum);
    1489            0 :         hccl::TaskPara taskPara(TaskType::TASK_FLIP, para);
    1490            0 :         callback_(callBackUserPtr_, (void*)&taskPara, sizeof(struct TaskPara));
    1491            0 :     }
    1492              : 
    1493            0 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1494              : 
    1495            0 :     uint8_t* sqeBufferAddr = nullptr;
    1496            0 :     uint8_t* sqeTypeAddr = nullptr;
    1497            0 :     uint8_t* sqeDfxInfoAddr = nullptr;
    1498            0 :     CHK_RET(stream.GetNextSqeBufferAddr(sqeBufferAddr, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1499              : 
    1500            0 :     AicpuDfxInfo* const dfxInfo = (AicpuDfxInfo* const)sqeDfxInfoAddr;
    1501            0 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
    1502            0 :     dfxInfo->remoteRank = INVALID_VALUE_RANKID;
    1503            0 :     dfxInfo->notifyId = INVALID_VALUE_RANKID;
    1504            0 :     addOneFlipPlaceHolderSqe_(streamInfo.actualStreamId, flipNum, taskId, sqeBufferAddr, sqeTypeAddr);
    1505              : 
    1506            0 :     PLF_CONFIG_INFO(
    1507              :         PLF_TASK, "%s para: taskId[%u] streamId[%u] flipNum[%u]", __func__, taskId, streamInfo.actualStreamId, flipNum);
    1508            0 :     return HCCL_SUCCESS;
    1509              : }
    1510              : 
    1511            0 : HcclResult DispatcherAiCpu::AddRetryPreamble(Stream& stream) { return AddFlipTask(stream); }
    1512              : 
    1513           22 : void DispatcherAiCpu::SaveStreamInfo(hccl::Stream& stream)
    1514              : {
    1515           22 :     const HcclComStreamInfo& streamInfo = stream.GetHcclStreamInfo();
    1516           22 :     auto it = streamMap_.find(streamInfo.actualStreamId);
    1517           22 :     if (it == streamMap_.end()) {
    1518           17 :         streamMap_.insert({streamInfo.actualStreamId, stream});
    1519           17 :         HCCL_INFO("[DispatcherAiCpu][SaveStreamInfo] stream id[%d]", streamInfo.actualStreamId);
    1520            5 :     } else if (it->second.IsInvalid()) {
    1521              :         // stream id复用: 旧stream已销毁(IsInvalid=true), 用新stream覆盖, 否则dispatcher会一直跳过该id
    1522            0 :         it->second = stream;
    1523            0 :         HCCL_INFO(
    1524              :             "[DispatcherAiCpu][SaveStreamInfo] refresh invalidated stream id stream id[%d]", streamInfo.actualStreamId);
    1525              :     }
    1526           44 :     return;
    1527              : }
    1528              : 
    1529            2 : HcclResult DispatcherAiCpu::StreamSync(Stream& stream)
    1530              : {
    1531            2 :     uint32_t head = 0;
    1532            2 :     uint32_t tail = 0;
    1533              :     const HcclComStreamInfo* streamInfo;
    1534            2 :     u64 startUsec = GetCurAicpuTimestamp();
    1535            2 :     u64 lastUsec = startUsec;
    1536            2 :     CHK_RET(stream.GetStreamInfo(streamInfo));
    1537              : 
    1538            2 :     CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo->sqId, DRV_SQCQ_PROP_SQ_TAIL, tail));
    1539            2 :     HCCL_INFO("StreamSync aicpu stream sqid[%d] tail[%u]", streamInfo->sqId, tail);
    1540              :     do {
    1541            2 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo->sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
    1542            2 :         u64 curUsec = GetCurAicpuTimestamp();
    1543            2 :         if (curUsec - startUsec > NANOSECOND_TO_SECOND * dfxTimeOutConfig_.sqeTimeOutTimeOut) {
    1544            1 :             HCCL_ERROR(
    1545              :                 "stream sync timeout %lus. curhead:%u, curtall:%u, sqId:%d", dfxTimeOutConfig_.sqeTimeOutTimeOut, head,
    1546              :                 tail, streamInfo->sqId);
    1547            1 :             return HCCL_E_TIMEOUT;
    1548              :         }
    1549              : 
    1550              :         // 等待下发阶段,每隔30s打印一次状态
    1551            1 :         if (curUsec - lastUsec > NANOSECOND_TO_SECOND * dfx::kPrintSqInterval) {
    1552            0 :             lastUsec = curUsec;
    1553            0 :             HCCL_RUN_INFO("[StreamSync]Current state. sqid:%d, head:%u, tail:%u", streamInfo->sqId, head, tail);
    1554              :         }
    1555            1 :     } while (head != tail);
    1556              : 
    1557            1 :     return HCCL_SUCCESS;
    1558              : }
    1559              : 
    1560            5 : u64 DispatcherAiCpu::CalcDbAddr(u32 dbindex)
    1561              : {
    1562            5 :     u64 dbAddr = 0;
    1563            5 :     if (aicpuInfo_.devType == DevType::DEV_TYPE_910_93) {
    1564              :         // 910_93 HCCS_SW 组网
    1565            2 :         constexpr u64 roceBaseAddr = 0x202000000000ULL;
    1566            2 :         constexpr u64 roceVfDbCfg0Reg = 0x230ULL;
    1567            2 :         constexpr u64 chipAddrOffset = 0x20000000000ULL;
    1568            2 :         constexpr u64 dieAddrOffset = 0x10000000000ULL;
    1569            2 :         constexpr u32 dbDieIdMask = 0x00ff0000;
    1570            2 :         constexpr u32 dbDieIdShift = 16; // 16 is dbDieIdShift
    1571            2 :         dbAddr = roceBaseAddr + roceVfDbCfg0Reg + chipAddrOffset * aicpuInfo_.chipId
    1572            2 :                  + dieAddrOffset * ((dbindex & dbDieIdMask) >> dbDieIdShift);
    1573              :     } else {
    1574            3 :         constexpr u64 roceBaseAddr = 0x2000000000ULL;
    1575            3 :         constexpr u64 roceVfDbCfg0Reg = 0x230ULL;
    1576            3 :         constexpr u64 chipAddrOffset = 0x80000000000ULL;
    1577            3 :         constexpr u64 dieAddrOffset = 0x10000000000ULL;
    1578            3 :         constexpr u32 dbDieIdMask = 0x00ff0000;
    1579            3 :         constexpr u32 dbDieIdShift = 16; // 16 is dbDieIdShift
    1580            3 :         dbAddr = roceBaseAddr + roceVfDbCfg0Reg + chipAddrOffset * aicpuInfo_.chipId
    1581            3 :                  + dieAddrOffset * ((dbindex & dbDieIdMask) >> dbDieIdShift);
    1582              :     }
    1583              : 
    1584            5 :     HCCL_DEBUG(
    1585              :         "%s dbindex:%u, devType:%u, chipId:%lld, dbAddr:%llu", __func__, dbindex, aicpuInfo_.devType, aicpuInfo_.chipId,
    1586              :         dbAddr);
    1587            5 :     return dbAddr;
    1588              : }
    1589              : 
    1590          448 : void DispatcherAiCpu::InitTimeOutConfig()
    1591              : {
    1592          448 :     dfxTimeOutConfig_.useCredit = false;
    1593          448 :     dfxTimeOutConfig_.sqeTimeOutTimeOut = GetMaxNotifyWaitTime();
    1594          449 :     dfxTimeOutConfig_.sqeCreditTimeOut = RT_STARS_NEVER_TIMEOUT_KERNEL_CREDIT;
    1595          449 :     dfxTimeOutConfig_.sqeWaitTimeOut = dfx::kKfcTimeOut;
    1596          449 :     dfxTimeOutConfig_.sqFullWaitTimeOut = dfx::kSqFullWaitTimeOut;
    1597          449 :     HCCL_INFO(
    1598              :         "[DispatcherAiCpu][InitTimeOutConfig]DFX timeout config init successfully with details: [%s]",
    1599              :         dfxTimeOutConfig_.ToString().c_str());
    1600          448 : }
    1601              : } // namespace hccl
        

Generated by: LCOV version 2.0-1