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

Generated by: LCOV version 2.0-1