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.4 % 777 376
Test Date: 2026-08-04 10:52:23 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          444 :     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          444 :         addOneNotifyWaitSqe_ = AddOneNotifyWaitSqeV1;
      82          444 :         addOneRecordSqe_ = AddOneRecordSqeV1;
      83          444 :         addOneWriteValueRecordSqe_ = AddOneWriteValueRecordSqeV1;
      84          444 :         addOneMemcpySqe_ = AddOneMemcpySqeV1;
      85          444 :         addOneEventResetSqe_ = AddOneEventResetSqeV1;
      86          444 :         addOneEventRecordSqe_ = AddOneEventRecordSqeV1;
      87          444 :         addOneEventWaitSqe_ = AddOneEventWaitSqeV1;
      88          444 :         addOneRdmaDbSendSqe_ = AddOneRdmaDbSendSqeV1;
      89          444 :         addOneFlipPlaceHolderSqe_ = AddOneFlipPlaceHolderSqeV1;
      90          444 :         addOneCacheMemcpyPlaceHolderSqe_ = AddOneCacheMemcpyPlaceHolderSqeV1;
      91          444 :         addOneCacheNotifyWaitPlaceholderSqe_ = AddOneCacheNotifyWaitPlaceholderSqeV1;
      92          444 :         addOneCacheNotifyRecordPlaceholderSqe_ = AddOneCacheNotifyRecordPlaceholderSqeV1;
      93          444 :         addOneCacheWriteValuePlaceholderSqe_ = AddOneCacheWriteValuePlaceholderSqeV1;
      94          444 :         addOneCacheMemcpyRecordPlaceholderSqe_ = AddOneCacheMemcpyRecordPlaceholderSqeV1;
      95          444 :         CHK_PTR_NULL(addOneRdmaDbSendSqe_);
      96          444 :         CHK_PTR_NULL(addOneFlipPlaceHolderSqe_);
      97          444 :         CHK_PTR_NULL(addOneCacheMemcpyPlaceHolderSqe_);
      98          444 :         CHK_PTR_NULL(addOneCacheNotifyWaitPlaceholderSqe_);
      99          444 :         CHK_PTR_NULL(addOneCacheNotifyRecordPlaceholderSqe_);
     100          444 :         CHK_PTR_NULL(addOneCacheWriteValuePlaceholderSqe_);
     101          444 :         CHK_PTR_NULL(addOneCacheMemcpyRecordPlaceholderSqe_);
     102              :     }
     103              : 
     104          444 :     CHK_PTR_NULL(addOneNotifyWaitSqe_);
     105          444 :     CHK_PTR_NULL(addOneRecordSqe_);
     106          444 :     CHK_PTR_NULL(addOneWriteValueRecordSqe_);
     107          444 :     CHK_PTR_NULL(addOneMemcpySqe_);
     108          444 :     CHK_PTR_NULL(addOneEventResetSqe_);
     109          444 :     CHK_PTR_NULL(addOneEventRecordSqe_);
     110          444 :     CHK_PTR_NULL(addOneEventWaitSqe_);
     111              : 
     112          444 :     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      2967779 :     while (((tail < head ? streamInfo.sqDepth : 0U) + tail - head + cnt >= streamInfo.sqDepth) && (tail != head)) { // 判断剩余sqe空间是否足够下发
     638              :         // 需要放在while循环进来后第一个执行
     639      2967777 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
     640              : 
     641              :         // 非阻塞下发场景,rtsq队列空间不足时直接返回
     642      2967777 :         if (isBlockLaunch == false) {
     643            0 :             return HCCL_SUCCESS;
     644              :         }
     645              : 
     646              :         // 当前流无法下发,把其他流都launch一遍,避免等待的其他流没有launch
     647      4520132 :         for (auto it = streamMap_.begin(); it != streamMap_.end(); ++it) {
     648      1552355 :             if (it->first != streamInfo.actualStreamId) {
     649            1 :                 if (it->second.IsInvalid()) { // 跳过已销毁的stream (streamMap_只增不删, 原stream销毁后副本通过shared invalid标志感知)
     650            0 :                     HCCL_WARNING("[DispatcherAiCpu][LaunchTask] skip invalid stream in streamMap, streamId:%d", it->first);
     651            0 :                     continue;
     652              :                 }
     653            1 :                 CHK_RET(LaunchTask(it->second, false));
     654              :             }
     655              :         }
     656      2967777 :         u64 curUsec = GetCurAicpuTimestamp();
     657      2967777 :         if (dfxTimeOutConfig_.sqFullWaitTimeOut != 0 && 
     658      2967776 :             (curUsec - startUsec > NANOSECOND_TO_SECOND * dfxTimeOutConfig_.sqFullWaitTimeOut)) {
     659            2 :             HCCL_ERROR("Rtsq full, timeout %lus. curhead:%u, sqId:%d", dfxTimeOutConfig_.sqFullWaitTimeOut, head,
     660              :                 streamInfo.sqId);
     661            2 :             return HCCL_E_AGAIN;
     662              :         }
     663              : 
     664              :         // 等待下发阶段,每隔30s打印一次状态
     665      2967775 :         if (curUsec - lastUsec > NANOSECOND_TO_SECOND * dfx::kPrintSqInterval) {
     666            0 :             lastUsec = curUsec;
     667            0 :             HCCL_RUN_INFO("[LaunchTask][WaitLaunchWhileLoop]Current state. sqid:%d, head:%u, tail:%u, cnt:%u",
     668              :                 streamInfo.sqId, head, tail, cnt);
     669              :         }
     670              : 
     671              :         // 下发过程中出现cqe异常
     672      2967775 :         if (checkOpExecStatusCallback_ != nullptr) {
     673            0 :             HcclResult opExecStatus = checkOpExecStatusCallback_();
     674            0 :             CHK_PRT_RET(opExecStatus != HCCL_SUCCESS,
     675              :                 HCCL_ERROR("hccl aicpu stop launch for task exception or stop command, ret:%d", opExecStatus),
     676              :                 opExecStatus);
     677              :         }
     678              :     }
     679              : 
     680            2 :     uint32_t left = streamInfo.sqDepth - tail;                     // sqeAddr 剩余空间
     681            2 :     const auto tailSqeIdx = sqeContextBuffer->tailSqeIdx;
     682            2 :     HCCL_INFO("cpy sqe, left:%u, tailSqeId:%u, cnt:%u, streamId:%u", left, tailSqeIdx, cnt, stream.id());
     683            2 :     if (cnt <= left) { // 剩余buffer放得下新增sqe
     684            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(
     685              :             reinterpret_cast<uint8_t *>(streamInfo.sqBaseAddr) + tail * HCCL_SQE_SIZE,
     686              :             left * HCCL_SQE_SIZE,
     687              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE,
     688              :             cnt * HCCL_SQE_SIZE));
     689              : 
     690            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsMirrorBuffer + tail * HCCL_SQE_SIZE,
     691              :             left * HCCL_SQE_SIZE,
     692              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE,
     693              :             cnt * HCCL_SQE_SIZE));
     694              : 
     695            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsqSqeType + tail, left,
     696              :             sqeContextBuffer->sqeType + (tailSqeIdx - cnt), cnt));
     697            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsDfxInfo + tail, left * sizeof(AicpuDfxInfo),
     698              :             sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt), cnt * sizeof(AicpuDfxInfo)));
     699              :     } else {
     700            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(reinterpret_cast<uint8_t *>(streamInfo.sqBaseAddr) + tail * HCCL_SQE_SIZE,
     701              :             left * HCCL_SQE_SIZE,
     702              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE,
     703              :             left * HCCL_SQE_SIZE));
     704              : 
     705            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(reinterpret_cast<uint8_t *>(streamInfo.sqBaseAddr),
     706              :             streamInfo.sqDepth * HCCL_SQE_SIZE,
     707              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt + left) * HCCL_SQE_SIZE,
     708              :             (cnt - left) * HCCL_SQE_SIZE));
     709              : 
     710            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsMirrorBuffer + tail * HCCL_SQE_SIZE,
     711              :             left * HCCL_SQE_SIZE,
     712              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE,
     713              :             left * HCCL_SQE_SIZE));
     714              : 
     715            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsMirrorBuffer,
     716              :             streamInfo.sqDepth * HCCL_SQE_SIZE,
     717              :             sqeContextBuffer->localBuff + (tailSqeIdx - cnt + left) * HCCL_SQE_SIZE,
     718              :             (cnt - left) * HCCL_SQE_SIZE));
     719              : 
     720            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsqSqeType + tail,
     721              :             left, sqeContextBuffer->sqeType + (tailSqeIdx - cnt), left));
     722            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsqSqeType + 0, streamInfo.sqDepth,
     723              :             sqeContextBuffer->sqeType + (tailSqeIdx - cnt + left), (cnt - left)));
     724            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsDfxInfo + tail,
     725              :             left * sizeof(AicpuDfxInfo), sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt), left * sizeof(AicpuDfxInfo)));
     726            1 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsDfxInfo + 0, streamInfo.sqDepth * sizeof(AicpuDfxInfo),
     727              :             sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt + left), (cnt - left) * sizeof(AicpuDfxInfo)));
     728              :     }
     729              :     // 打印算子展开下发的SQE内容for debug
     730              :     // 设置HCCL_DEBUG_CONFIG="task", 或者设置ASCEND_GLOBAL_LOG_LEVEL=0
     731            2 :     if ((UNLIKELY(GetExternalInputDebugConfig() & PLF_TASK)) || UNLIKELY(HcclCheckLogLevel(HCCL_LOG_DEBUG))) {
     732            2 :         const int32_t streamId = stream.GetHcclStreamInfo().actualStreamId;
     733            2 :         PLF_CONFIG_DEBUG(PLF_TASK, "[DispatcherAicpu][LaunchTask] dump content of %u dispatched SQEs with stream id %u", cnt, streamId);
     734              : 
     735            2 :         uint8_t *sqeArray = sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE;
     736            2 :         uint8_t *sqeTypeArray = sqeContextBuffer->sqeType + (tailSqeIdx - cnt);
     737            2 :         AicpuDfxInfo *sqeDfxInfoArray = sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt);
     738           14 :         for (size_t sqeIdx = 0; sqeIdx < cnt; ++sqeIdx) {
     739           12 :             uint8_t *sqePtr = sqeArray + sqeIdx * HCCL_SQE_SIZE;
     740           12 :             const uint8_t sqeType = sqeTypeArray[sqeIdx];
     741           12 :             if (sqeType == SqeType::FLIP_PLACEHOLDER_SQE) {
     742            0 :                 const rtStarsPlaceHolderSqe_t *placeholderSqePtr = reinterpret_cast<const rtStarsPlaceHolderSqe_t *>(sqeArray + sqeIdx * HCCL_SQE_SIZE);
     743            0 :                 PLF_CONFIG_DEBUG(PLF_TASK, "[DispatcherAicpu][LaunchTask] %uth dispatched SQE (placeholder) header.type[%u] taskid[%u]", sqeIdx, placeholderSqePtr->header.type, placeholderSqePtr->header.taskId);
     744              :             } else {
     745           12 :                 PLF_CONFIG_DEBUG(PLF_TASK, "[DispatcherAicpu][LaunchTask] %uth dispatched SQE", sqeIdx);
     746              :             }
     747              :             
     748           12 :             CHK_RET(OpUnfoldCache::DumpSqeContent(sqePtr, sqeType));
     749              : 
     750           12 :             const AicpuDfxInfo& dfxinfo = sqeDfxInfoArray[sqeIdx];
     751           12 :             PLF_CONFIG_DEBUG(PLF_TASK, "[DispatcherAicpu][LaunchTask] AicpuDfxInfo: remoteRank[%u] opRingBufferIdx[%u] notifyId[%u]",
     752              :                 dfxinfo.remoteRank, dfxinfo.opRingBufferIdx, dfxinfo.notifyId);
     753              :         }
     754              :     }
     755              : 
     756              :     // 当前算子展开的SQE需要被动态缓存
     757            2 :     if (needAddSqe_) {
     758            0 :         CHK_PTR_NULL(cachePtr_);
     759              : 
     760              :         // 查找key对应的cache entry, 如果不存在 (即当前算子第一次LaunchTask), 创建新的cache entry
     761            0 :         OpUnfoldCacheEntry *entryPtr = nullptr;
     762            0 :         CHK_RET(cachePtr_->FindEntry(key_, &entryPtr));
     763            0 :         if (entryPtr == nullptr) {
     764            0 :             CHK_RET(cachePtr_->AddEntry(key_, userInputMemRanges_, userOutputMemRanges_, &entryPtr));
     765              :         }
     766            0 :         CHK_PTR_NULL(entryPtr);
     767              : 
     768              :         // 准备SQE相关信息的数组基地址
     769            0 :         uint8_t *sqeArray = sqeContextBuffer->localBuff + (tailSqeIdx - cnt) * HCCL_SQE_SIZE;
     770            0 :         uint8_t *sqeTypeArray = sqeContextBuffer->sqeType + (tailSqeIdx - cnt);
     771            0 :         AicpuDfxInfo *sqeDfxInfoArray = sqeContextBuffer->dfxInfo + (tailSqeIdx - cnt);
     772              : 
     773              :         // 遍历sqeType找到placeholder的位置
     774            0 :         std::vector<size_t> placeholderIdxes;
     775            0 :         uint8_t *curSqeTypePtr = sqeTypeArray;
     776            0 :         for (size_t sqeTypeIdx = 0; sqeTypeIdx < cnt; ++sqeTypeIdx) {
     777            0 :             if (*curSqeTypePtr == SqeType::FLIP_PLACEHOLDER_SQE) {
     778            0 :                 placeholderIdxes.emplace_back(sqeTypeIdx);
     779              :             }
     780            0 :             ++curSqeTypePtr;
     781              :         }
     782              : 
     783              :         // 在动态缓存中分配实际需要的SQE数组
     784            0 :         const size_t cacheableSqeCount = cnt - placeholderIdxes.size();
     785            0 :         const int32_t streamId = stream.GetHcclStreamInfo().actualStreamId;
     786            0 :         size_t arrayIdx = 0;
     787            0 :         CHK_RET(entryPtr->AllocSqeArray(cacheableSqeCount, streamId, arrayIdx));
     788              : 
     789              :         // 分段拷贝SQE相关信息到cache entry中
     790            0 :         size_t cacheableSqeStartIdx = 0; // SQE start index (在动态缓存对应SQE数组中的索引)
     791            0 :         size_t bufferSqeStartIdx = 0; // SQE start index (在SQE ring buffer中的索引)
     792            0 :         for (size_t i = 0; i < placeholderIdxes.size(); ++i) {
     793              :             // [bufferSqeStartIdx, curPlaceholderIdx) -> [cacheableSqeStartIdx, cacheableSqeStartIdx + curPlaceholderIdx - bufferSqeStartIdx)
     794            0 :             const size_t curPlaceholderIdx = placeholderIdxes[i];
     795            0 :             HCCL_INFO("[DispatcherAicpu][LaunchTask] %uth placeholder copy dispatchedSqeArray[%u:%u) into cachedSqeArrays[%u][%u:%u)", i, bufferSqeStartIdx, curPlaceholderIdx, arrayIdx, cacheableSqeStartIdx, cacheableSqeStartIdx + curPlaceholderIdx - bufferSqeStartIdx);
     796            0 :             if (curPlaceholderIdx <= bufferSqeStartIdx) { // NO non-placeholder dispatched SQE to admit
     797              :                 // NOTE: NO need to change cacheableSqeStartIdx
     798            0 :                 bufferSqeStartIdx = curPlaceholderIdx + 1;
     799              :             } else {
     800            0 :                 const size_t curSqeCount = curPlaceholderIdx - bufferSqeStartIdx;
     801            0 :                 CHK_RET(entryPtr->MemcpySqeArray(arrayIdx, cacheableSqeStartIdx, curSqeCount,
     802              :                     sqeArray + bufferSqeStartIdx * HCCL_SQE_SIZE,
     803              :                     sqeTypeArray + bufferSqeStartIdx,
     804              :                     sqeDfxInfoArray + bufferSqeStartIdx,
     805              :                     isAlltoallv_, alltoallvMetadataPtr_
     806              :                 ));
     807            0 :                 cacheableSqeStartIdx += curSqeCount;
     808            0 :                 bufferSqeStartIdx = curPlaceholderIdx + 1;
     809              :             }
     810              :         }
     811              : 
     812              :         // 存在剩余SQE, 即最后一个SQE不是placeholder
     813            0 :         if (LIKELY(bufferSqeStartIdx < cnt)) {
     814              :             // [bufferSqeStartIdx, cnt - 1] -> [cacheableSqeStartIdx, cacheableSqeStartIdx + cnt - bufferSqeStartIdx)
     815            0 :             const size_t curSqeCount = cnt - bufferSqeStartIdx;
     816            0 :             CHK_RET(entryPtr->MemcpySqeArray(arrayIdx, cacheableSqeStartIdx, curSqeCount,
     817              :                 sqeArray + bufferSqeStartIdx * HCCL_SQE_SIZE,
     818              :                 sqeTypeArray + bufferSqeStartIdx,
     819              :                 sqeDfxInfoArray + bufferSqeStartIdx,
     820              :                 isAlltoallv_, alltoallvMetadataPtr_
     821              :             ));
     822              :         }
     823            0 :     }
     824              : 
     825            2 :     CHK_RET(ConfigSqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_TAIL, newTail));
     826            2 :     tail = newTail;
     827            2 :     PLF_CONFIG_INFO(PLF_TASK,
     828              :         "%s success, sqid:%d, sqe_num:%u, curHead:%u, curtail:%u", __func__, streamInfo.sqId, cnt, head, tail);
     829            2 :     sqeContextBuffer->sqeCnt = 0;
     830            2 :     return HCCL_SUCCESS;
     831              : }
     832              : 
     833            8 : HcclResult DispatcherAiCpu::LaunchTasksEx(hccl::Stream &stream, std::vector<Stream> &subStreams)
     834              : {
     835              :     /* 两阶段模式,主流待正式执行时再下 */
     836              :     /* 一阶段第一次,可以先下主流 */
     837            8 :     HcclResult ret = LaunchTask(stream, true);
     838            8 :     if (ret != HCCL_SUCCESS) {
     839            0 :         HCCL_ERROR("[DispatcherAiCpu][LaunchTasksEx] "\
     840              :                    "launch task failed, sqid:%u, ret:%u", stream.sqId(), ret);
     841            0 :         return ret;
     842              :     }
     843              : 
     844            8 :     for (u32 index = 0; index < subStreams.size(); index++) {
     845            0 :         ret = LaunchTask(subStreams[index], true);
     846            0 :         if (ret != HCCL_SUCCESS) {
     847            0 :             HCCL_ERROR("[DispatcherAiCpu][LaunchTasksEx] "\
     848              :                        "launch task failed, sqid:%u, ret:%u", subStreams[index].sqId(), ret);
     849            0 :             return ret;
     850              :         }
     851              :     }
     852              : 
     853            8 :     return HCCL_SUCCESS;
     854              : }
     855              : 
     856            3 : HcclResult DispatcherAiCpu::LaunchAllTasks()
     857              : {
     858            5 :     for (auto it = streamMap_.begin(); it != streamMap_.end(); ++it) {
     859            3 :         if (it->second.IsInvalid()) { // 跳过已销毁的stream (streamMap_只增不删, 原stream销毁后副本通过shared invalid标志感知)
     860            0 :             HCCL_WARNING("[DispatcherAiCpu][LaunchAllTasks] skip invalid stream in streamMap, streamId:%d", it->first);
     861            0 :             continue;
     862              :         }
     863            3 :         HcclResult ret = LaunchTask(it->second, true);
     864            3 :         if (ret != HCCL_SUCCESS) {
     865            1 :             HCCL_ERROR("DispatcherAiCpu][LaunchAllTasks] launch task failed, sqid:%u, ret:%u", it->second.sqId(), ret);
     866            1 :             return ret;
     867              :         }
     868              :     }
     869            2 :     return HCCL_SUCCESS;
     870              : }
     871              : 
     872            1 : HcclResult DispatcherAiCpu::ReduceAsync(const void *src, void *dst, u64 dataCount, const HcclDataType datatype,
     873              :     HcclReduceOp redOp, Stream &stream, HcclReduceType reduceType)
     874              : {
     875            1 :     return (reduceType == HcclReduceType::HCCL_INLINE_REDUCE) ?
     876            1 :         InlineReduceAsync(src, dataCount, datatype, redOp, stream, dst) :
     877            1 :         TbeReduceAsync(src, dst, dataCount, datatype, redOp, stream, dst);
     878              : }
     879              : 
     880            2 : HcclResult DispatcherAiCpu::InlineReduceAsync(const void *src, u64 dataCount, const HcclDataType datatype,
     881              :     HcclReduceOp redOp, hccl::Stream &stream, void *dst, u32 remoteUserRank, hccl::LinkType inLinkType)
     882              : {
     883              :     // 参数有效性检查
     884            2 :     CHK_PTR_NULL(stream.ptr());
     885            2 :     if (dataCount == 0) {
     886            0 :         HCCL_INFO("%s src memory size is 0, not need inline reduce.", __func__);
     887            0 :         return HCCL_SUCCESS;
     888              :     }
     889            2 :     const HcclComStreamInfo &streamInfo = stream.GetHcclStreamInfo();
     890              : 
     891            2 :     aclDataType runtimeDataType = DT_MAP_TABLE[datatype];
     892            2 :     aclrtReduceKind rtReduceOp = RK_MAP_TABLE[redOp];
     893              : 
     894              :     // 将数据按4GB切分循环处理
     895            2 :     uint64_t spiltLoop = 0;
     896            2 :     uint64_t addr_offset = 0;
     897            2 :     uint64_t countSplit = 0;
     898            2 :     uint64_t countSize = dataCount * SIZE_TABLE[datatype];
     899            2 :     uint8_t *sqeBuffer = nullptr;
     900            2 :     uint8_t *sqeTypeAddr = nullptr;
     901            2 :     uint8_t *sqeDfxInfoAddr = nullptr;
     902            2 :     uint16_t taskId = 0U;
     903              : 
     904            2 :     if (countSize > HCCL_SDMA_MAX_COUNT_4GB) {
     905            0 :         spiltLoop = (countSize % HCCL_SDMA_MAX_COUNT_4GB) ? (countSize / HCCL_SDMA_MAX_COUNT_4GB) :
     906            0 :                                                             ((countSize / HCCL_SDMA_MAX_COUNT_4GB) - 1);
     907            0 :         HCCL_INFO("%s InlineReduceAsync SDMA task countSize is bigger than 4GB"
     908              :             " and do segmentation splitloop:%llu", __func__, spiltLoop);
     909              :     }
     910            2 :     uint8_t linkType = static_cast<uint8_t>(inLinkType);
     911            4 :     for (uint64_t index = 0; index <= spiltLoop; index++) {
     912            2 :         addr_offset = index * HCCL_SDMA_MAX_COUNT_4GB;
     913            2 :         countSplit = (index == spiltLoop) ? (countSize - index * HCCL_SDMA_MAX_COUNT_4GB) : (HCCL_SDMA_MAX_COUNT_4GB);
     914            2 :         void *srcSplit = static_cast<void *>(static_cast<char *>(const_cast<void *>(src)) + addr_offset);
     915            2 :         void *dstSplit = static_cast<void *>(static_cast<char *>(dst) + addr_offset);
     916              : 
     917            2 :         CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     918            2 :         AicpuDfxInfo * const dfxInfo = (AicpuDfxInfo * const)sqeDfxInfoAddr;
     919            2 :         dfxInfo->opRingBufferIdx = opRingBufferIdx_;
     920            2 :         dfxInfo->remoteRank = remoteUserRank;
     921            2 :         dfxInfo->notifyId = INVALID_VALUE_RANKID;
     922            2 :         addOneMemcpySqe_(streamInfo.actualStreamId, taskId, srcSplit, countSplit, runtimeDataType, rtReduceOp, dstSplit, 0,
     923              :             aicpuInfo_.ssid, aicpuInfo_.devId, aicpuInfo_.overflowAddr, linkType, sqeBuffer, sqeTypeAddr, hcclQos_);
     924              : 
     925            2 :         PLF_CONFIG_INFO(PLF_TASK,
     926              :             "%s para: linkType[%u] srcSplit[%p] dstSplit[%p] countSplit[%llu] taskId[%u] streamId[%u] remoteRank[%u] "\
     927              :             "rtDatatType[%d] rtReduceOp[%d]", __func__, linkType, srcSplit, dstSplit, countSplit, taskId,
     928              :             streamInfo.actualStreamId, remoteUserRank, runtimeDataType, rtReduceOp);
     929              :     }
     930              : 
     931            2 :     return HCCL_SUCCESS;
     932              : }
     933              : 
     934            1 : HcclResult DispatcherAiCpu::TbeReduceAsync(const void *src1, const void *src2, u64 count, const HcclDataType datatype,
     935              :     HcclReduceOp redOp, Stream &stream, const void *dst)
     936              : {
     937            1 :     HCCL_ERROR("[DispatcherAiCpu][TbeReduceAsync] aicpu do not support the tbe reduce");
     938            1 :     return HCCL_E_NOT_SUPPORT;
     939              : }
     940              : 
     941            5 : HcclResult DispatcherAiCpu::RdmaSend(u32 dbindex, u64 dbinfo, hccl::Stream &stream, RdmaTaskInfo &taskInfo)
     942              : {
     943            5 :     const HcclComStreamInfo &streamInfo = stream.GetHcclStreamInfo();
     944              : 
     945            5 :     uint8_t *sqeBuffer = nullptr;
     946            5 :     uint8_t *sqeTypeAddr = nullptr;
     947            5 :     uint8_t *sqeDfxInfoAddr = nullptr;
     948            5 :     uint16_t taskId = 0U;
     949              : 
     950            5 :     CHK_RET(GetStreamSqeBufferAddr(stream, sqeBuffer, sqeTypeAddr, sqeDfxInfoAddr, taskId));
     951            5 :     AicpuDfxInfo * const dfxInfo = (AicpuDfxInfo * const)sqeDfxInfoAddr;
     952            5 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
     953            5 :     dfxInfo->remoteRank = taskInfo.remoteRank;
     954            5 :     dfxInfo->notifyId = INVALID_UINT; // 多个wr只敲一次doorbell的情况下,一般只会有一个notify
     955              : 
     956            5 :     uint32_t wrLen = 0; // 统计wr的总数据量
     957            5 :     for (const WrInformation& wr : taskInfo.wrInfos) {
     958            0 :         wrLen += wr.wrData.memList.len;
     959            0 :         dfxInfo->notifyId = (wr.notifyId != INVALID_UINT) ? wr.notifyId : dfxInfo->notifyId;
     960              :     }
     961              : 
     962            5 :     u64 dbAddr = CalcDbAddr(dbindex);
     963            5 :     addOneRdmaDbSendSqe_(streamInfo.actualStreamId, taskId, dbinfo, dbAddr, wrLen,
     964            5 :         static_cast<uint8_t>(taskInfo.rdmaType), sqeBuffer, sqeTypeAddr);
     965              : 
     966            5 :     PLF_CONFIG_INFO(PLF_TASK,
     967              :         "%s para: streamId[%u] taskId[%u] remoteRank[%u] RdmaType[%d] wrLen[%u] notifyId[%u]",
     968              :         __func__, streamInfo.actualStreamId, taskId, taskInfo.remoteRank, taskInfo.rdmaType, wrLen, dfxInfo->notifyId);
     969              : 
     970            5 :     return HCCL_SUCCESS;
     971              : }
     972              : 
     973            0 : HcclResult DispatcherAiCpu::RdmaRecord(u32 dbindex, u64 dbinfo, const struct SendWr &wr, hccl::Stream &stream,
     974              :     RdmaType rdmaType, u32 userRank, u64 offset, u32 notifyId)
     975              : {
     976            0 :     return HCCL_SUCCESS;
     977              : }
     978              : 
     979           13 : HcclResult DispatcherAiCpu::GetStreamSqeBufferAddr(hccl::Stream &stream, uint8_t *&sqeBufferAddr, uint8_t *&sqeTypeAddr,
     980              :     uint8_t *&sqeDfxInfoAddr, uint16_t &taskId)
     981              : {
     982           13 :     SaveStreamInfo(stream);
     983           13 :     HcclSqeContext* sqeContext = stream.GetSqeContextPtr();
     984           13 :     CHK_PTR_NULL(sqeContext);
     985           13 :     if (UNLIKELY(sqeContext->buffer.sqeCnt >= HCCL_PER_LAUNCH_SQE_CNT)) {
     986            0 :         HCCL_INFO("GetStreamSqeBufferAddr tailSqeIdx[%u], try to launchTask", sqeContext->buffer.tailSqeIdx);
     987            0 :         CHK_RET(LaunchTask(stream, true));
     988              :     }
     989           13 :     if (UNLIKELY(sqeContext->buffer.tailSqeIdx >= HCCL_SQE_MAX_CNT)) {
     990            0 :         CHK_RET(LaunchTask(stream, true));
     991              : 
     992            0 :         if (callback_ != nullptr) {
     993            0 :             hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
     994            0 :             hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
     995            0 :             callback_(callBackUserPtr_, (void *)&taskPara, sizeof(struct TaskPara));
     996            0 :         }
     997              :     }
     998           13 :     SqeRingBuffer *sqeContextBuffer = &(sqeContext->buffer);
     999           13 :     uint16_t flipNum = sqeContextBuffer->filpNum;
    1000           13 :     uint16_t nextTaskId = sqeContextBuffer->tailSqeTaskId;
    1001              :     // nextTaskId=0的时候下发PlaceHolder
    1002           13 :     if (UNLIKELY(nextTaskId == 0  && flipNum != 0)) {
    1003            0 :         CHK_RET(AddFlipTask(stream));
    1004              :     }
    1005           13 :     if (UNLIKELY(sqeContext->buffer.tailSqeIdx >= HCCL_SQE_MAX_CNT)) {
    1006            0 :         CHK_RET(LaunchTask(stream, true));
    1007              : 
    1008            0 :         if (callback_ != nullptr) {
    1009            0 :             hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1010            0 :             hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1011            0 :             callback_(callBackUserPtr_, (void *)&taskPara, sizeof(struct TaskPara));
    1012            0 :         }
    1013              :     }
    1014           13 :     CHK_RET(stream.GetNextSqeBufferAddr(sqeBufferAddr, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1015           13 :     return HCCL_SUCCESS;
    1016              : }
    1017              : 
    1018            2 : HcclResult DispatcherAiCpu::WaitRtsq(Stream& stream, const size_t& sqeCount, const bool isBlockLaunch) {
    1019              :     // 注意: 目前WaitRtsq不会被递归调用, 所以isBlockLaunch永远为true; 为防止以后LaunchTask递归使用WaitRtsq, 编码时考虑isBlockLaunch为false的情况
    1020              : 
    1021              :     // 检验入参
    1022            2 :     const HcclComStreamInfo &streamInfo = stream.GetHcclStreamInfo();
    1023            2 :     if (sqeCount == 0) {
    1024            0 :         CHK_PRT_CONT(isBlockLaunch,
    1025              :             HCCL_DEBUG("[DispatcherAiCpu][WaitRtsq] no sqe, streamId:%d, sqId:%u", streamInfo.actualStreamId, streamInfo.sqId));
    1026            0 :         return HCCL_SUCCESS;
    1027            2 :     } else if (sqeCount > streamInfo.sqDepth) {
    1028            0 :         HCCL_ERROR("[DispatcherAiCpu][WaitRtsq] sqeCount %u should be smaller than sqDepth %u]", sqeCount, streamInfo.sqDepth);
    1029            0 :         return HCCL_E_PTR;
    1030              :     }
    1031              :     
    1032              :     // Get head and tail of RTSQ ring buffer
    1033            2 :     HcclSqeContext *sqeContext = stream.GetSqeContextPtr();
    1034            2 :     CHK_PTR_NULL(sqeContext);
    1035            2 :     SqeRingBuffer *sqeContextBuffer = &(sqeContext->buffer);
    1036            2 :     CHK_PTR_NULL(sqeContextBuffer);
    1037            2 :     uint32_t& head = sqeContextBuffer->sqHead;
    1038            2 :     uint32_t& tail = sqeContextBuffer->sqTail;
    1039              : 
    1040              :     // Dump debug information
    1041            2 :     const uint32_t newTail = (tail + sqeCount) % streamInfo.sqDepth;
    1042              :     // 仅在阻塞下发场景打印,避免非阻塞场景调用时刷屏
    1043            2 :     CHK_PRT_CONT(isBlockLaunch,
    1044              :         HCCL_INFO("[DispatcherAicpu][WaitRtsq] sqid:%d sqeCount:%u head:%u curtail:%u newTail:%u", streamInfo.sqId, sqeCount, head, tail, newTail));
    1045              : 
    1046              :     // 轮询RTSQ直至获得足够大的剩余空间
    1047            2 :     u64 startUsec = GetCurAicpuTimestamp();
    1048            2 :     u64 lastUsec = startUsec;
    1049            3 :     while (((tail < head ? streamInfo.sqDepth : 0U) + tail - head + sqeCount >= streamInfo.sqDepth) && (tail != head)) { // 判断RTSQ中剩余sqe空间是否足够下发
    1050              :         // 需要放在while循环进来后第一个执行 (获取最新的RTSQ head, 查看RTSQ的消费进度)
    1051            2 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
    1052              : 
    1053              :         // 非阻塞下发场景,rtsq队列空间不足时直接返回
    1054            2 :         if (isBlockLaunch == false) {
    1055            1 :             return HCCL_SUCCESS;
    1056              :         }
    1057              : 
    1058              :         // 当前流无法下发,把其他流都launch一遍,避免等待的其他流没有launch
    1059            2 :         for (auto it = streamMap_.begin(); it != streamMap_.end(); ++it) {
    1060            1 :             if (it->first != streamInfo.actualStreamId) { // 不是当前stream
    1061            1 :                 if (it->second.IsInvalid()) { // 跳过已销毁的stream (streamMap_只增不删, 原stream销毁后副本通过shared invalid标志感知)
    1062            0 :                     HCCL_WARNING("[DispatcherAiCpu][WaitRtsq] skip invalid stream in streamMap, streamId:%d", it->first);
    1063            0 :                     continue;
    1064              :                 }
    1065            1 :                 CHK_RET(LaunchTask(it->second, false)); // 非阻塞launch
    1066              :             }
    1067              :         }
    1068              : 
    1069              :         // 等待超时
    1070            1 :         u64 curUsec = GetCurAicpuTimestamp();
    1071            1 :         if (dfxTimeOutConfig_.sqFullWaitTimeOut != 0 && 
    1072            0 :             (curUsec - startUsec > NANOSECOND_TO_SECOND * dfxTimeOutConfig_.sqFullWaitTimeOut)) {
    1073            0 :             HCCL_ERROR("[DispatcherAicpu][WaitRtsq] Rtsq full, timeout %lus. curhead:%u, sqId:%d", dfxTimeOutConfig_.sqFullWaitTimeOut, head, streamInfo.sqId);
    1074            0 :             return HCCL_E_AGAIN;
    1075              :         }
    1076              : 
    1077              :         // 等待下发阶段,每隔30s打印一次状态
    1078            1 :         if (curUsec - lastUsec > NANOSECOND_TO_SECOND * dfx::kPrintSqInterval) {
    1079            0 :             lastUsec = curUsec;
    1080            0 :             HCCL_RUN_INFO("[DispatcherAicpu][WaitRtsq] Current state. sqid:%d, head:%u, tail:%u, sqeCount:%u",
    1081              :                 streamInfo.sqId, head, tail, sqeCount);
    1082              :         }
    1083              : 
    1084              :         // 等待下发过程中出现cqe异常, 需要终止当前算子SQE的下发过程
    1085            1 :         if (checkOpExecStatusCallback_ != nullptr) {
    1086            0 :             HcclResult opExecStatus = checkOpExecStatusCallback_();
    1087            0 :             CHK_PRT_RET(opExecStatus != HCCL_SUCCESS,
    1088              :                 HCCL_ERROR("[DispatcherAicpu][WaitRtsq] hccl aicpu stop launch for task exception or stop command, ret:%d", opExecStatus),
    1089              :                 opExecStatus);
    1090              :         }
    1091              :     }
    1092              :     
    1093            1 :     return HCCL_SUCCESS;
    1094              : }
    1095              : 
    1096            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) {
    1097              :     // 检验入参
    1098            0 :     const HcclComStreamInfo &streamInfo = stream.GetHcclStreamInfo();
    1099            0 :     if (sqeCount == 0) {
    1100            0 :         HCCL_DEBUG("[DispatcherAiCpu][MemcpyRtsq] no sqe, streamId:%d, sqId:%u", streamInfo.actualStreamId, streamInfo.sqId);
    1101            0 :         return HCCL_SUCCESS;
    1102            0 :     } else if (sqeCount > streamInfo.sqDepth) {
    1103            0 :         HCCL_ERROR("[DispatcherAiCpu][MemcpyRtsq] sqeCount %u should be smaller than sqDepth %u]", sqeCount, streamInfo.sqDepth);
    1104            0 :         return HCCL_E_PTR;
    1105              :     }
    1106            0 :     CHK_PTR_NULL(sqeArray);
    1107            0 :     CHK_PTR_NULL(sqeTypeArray);
    1108            0 :     CHK_PTR_NULL(sqeDfxInfoArray);
    1109            0 :     if (profL1Enable) {
    1110              :         // 会访问profTimestamps[profTimestampStartIdx, profTimestampStartIdx + sqeCount - 1]
    1111            0 :         CHK_PRT_RET(profTimestamps.size() == 0, HCCL_ERROR("[DispatcherAiCpu][MemcpyRtsq] empty profTimestamps"), HCCL_E_INTERNAL);
    1112            0 :         CHK_PRT_RET(profTimestampStartIdx >= profTimestamps.size(), HCCL_ERROR("[DispatcherAiCpu][MemcpyRtsq] profTimestampStartIdx[%u] >= profTimestamps.size[%u]", profTimestampStartIdx, profTimestamps.size()), HCCL_E_INTERNAL);
    1113            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);
    1114              :     }
    1115              : 
    1116              :     // 获得RTSQ的head和tail
    1117            0 :     HcclSqeContext *sqeContext = stream.GetSqeContextPtr();
    1118            0 :     CHK_PTR_NULL(sqeContext);
    1119            0 :     SqeRingBuffer *sqeContextBuffer = &(sqeContext->buffer);
    1120            0 :     CHK_PTR_NULL(sqeContextBuffer);
    1121            0 :     uint32_t& head = sqeContextBuffer->sqHead;
    1122            0 :     uint32_t& tail = sqeContextBuffer->sqTail;
    1123              : 
    1124              :     // Dump debug information
    1125            0 :     const uint32_t newTail = (tail + sqeCount) % streamInfo.sqDepth;
    1126            0 :     HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] before memcpy, sqid:%d sqeCount:%u head:%u curtail:%u newTail:%u", streamInfo.sqId, sqeCount, head, tail, newTail);
    1127              : 
    1128              :     // 准备memcpy中目的末端基地址 (RTSQ从tail开始拷贝, [head, tail)为待执行SQE)
    1129            0 :     uint8_t *rtsqSqeTailBaseAddr = reinterpret_cast<uint8_t *>(streamInfo.sqBaseAddr) + tail * HCCL_SQE_SIZE;
    1130            0 :     uint8_t *mirrorRtsqSqeTailBaseAddr = sqeContextBuffer->rtsMirrorBuffer + tail * HCCL_SQE_SIZE;
    1131            0 :     uint8_t *rtsqSqeTypeTailBaseAddr = sqeContextBuffer->rtsqSqeType + tail;
    1132            0 :     AicpuDfxInfo *rtsqDfxInfoTailBaseAddr = sqeContextBuffer->rtsDfxInfo + tail;
    1133              : 
    1134            0 :     uint32_t tailLeft = streamInfo.sqDepth - tail; // RTSQ tail到buffer末端的剩余空间 (不包括buffer前端到head的剩余空间)
    1135            0 :     HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] cpy sqe, tailLeft:%u, sqeCount:%u, streamId:%u", tailLeft, sqeCount, stream.id());
    1136            0 :     if (sqeCount <= tailLeft) { // buffer末端剩余空间放得下新增sqe
    1137              :         // 向buffer末端拷贝sqeCount个SQE信息
    1138              : 
    1139              :         // 拷贝SQE内容到RTSQ
    1140            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, sqeCount * HCCL_SQE_SIZE));
    1141              : 
    1142              :         // 拷贝SQE内容到RTSQ mirror
    1143            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(mirrorRtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, sqeCount * HCCL_SQE_SIZE));
    1144              : 
    1145              :         // 拷贝SQE类型
    1146            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqSqeTypeTailBaseAddr, tailLeft, sqeTypeArray, sqeCount));
    1147              : 
    1148              :         // 拷贝SQE DfxInfo
    1149            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqDfxInfoTailBaseAddr, tailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray, sqeCount * sizeof(AicpuDfxInfo)));
    1150              :     } else { // 需要buffer末端和首端的剩余空间
    1151              :         // 先向buffer末端拷贝tailLeft个SQE信息, 再向buffer首端拷贝sqeCount-tailLeft个SQE信息
    1152              : 
    1153              :         // 拷贝SQE内容到RTSQ
    1154            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, tailLeft * HCCL_SQE_SIZE));
    1155            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(reinterpret_cast<uint8_t *>(streamInfo.sqBaseAddr),
    1156              :             streamInfo.sqDepth * HCCL_SQE_SIZE,
    1157              :             sqeArray + tailLeft * HCCL_SQE_SIZE,
    1158              :             (sqeCount - tailLeft) * HCCL_SQE_SIZE));
    1159              : 
    1160              :         // 拷贝SQE内容到RTSQ mirror
    1161            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(mirrorRtsqSqeTailBaseAddr, tailLeft * HCCL_SQE_SIZE, sqeArray, tailLeft * HCCL_SQE_SIZE));
    1162            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsMirrorBuffer,
    1163              :             streamInfo.sqDepth * HCCL_SQE_SIZE,
    1164              :             sqeArray + tailLeft * HCCL_SQE_SIZE,
    1165              :             (sqeCount - tailLeft) * HCCL_SQE_SIZE));
    1166              : 
    1167              :         // 拷贝SQE type
    1168            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqSqeTypeTailBaseAddr, tailLeft, sqeTypeArray, tailLeft));
    1169            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsqSqeType, streamInfo.sqDepth, sqeTypeArray + tailLeft, (sqeCount - tailLeft)));
    1170              : 
    1171              :         // 拷贝SQE DfxInfo
    1172            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(rtsqDfxInfoTailBaseAddr,
    1173              :             tailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray, tailLeft * sizeof(AicpuDfxInfo)));
    1174            0 :         CHK_SAFETY_FUNC_RET(memcpy_s(sqeContextBuffer->rtsDfxInfo, streamInfo.sqDepth * sizeof(AicpuDfxInfo),
    1175              :             sqeDfxInfoArray + tailLeft, (sqeCount - tailLeft) * sizeof(AicpuDfxInfo)));
    1176              :     }
    1177              : 
    1178              :     // 更新RTSQ ring buffer的tail
    1179            0 :     CHK_RET(ConfigSqStatusByType(aicpuInfo_.devId, streamInfo.sqId, DRV_SQCQ_PROP_SQ_TAIL, newTail));
    1180            0 :     tail = newTail;
    1181            0 :     PLF_CONFIG_INFO(PLF_TASK,
    1182              :         "%s success, sqid:%d, sqe_num:%u, curHead:%u, curtail:%u", __func__, streamInfo.sqId, sqeCount, head, tail);
    1183              :     
    1184              :     // 上报profiling信息
    1185            0 :     if (profL1Enable) {
    1186              :         // Cache hit下SQE ring buffer中[tail-cnt, tail)为待下发SQE, 其数量一定为0 (否则更新tailSqeIdx后, 会导致待下发SQE未下发, 而已下发SQE重复下发)
    1187            0 :         CHK_PRT_RET(sqeContextBuffer->sqeCnt != 0, HCCL_ERROR("[DispatcherAicpu][MemcpyRtsq] sqeContextBuffer->sqeCnt[%u] should be zero!", sqeContextBuffer->sqeCnt), HCCL_E_INTERNAL);
    1188              : 
    1189              :         // 上报flip placeholder的profiling信息
    1190            0 :         if ((*sqeTypeArray) == SqeType::FLIP_PLACEHOLDER_SQE) {
    1191            0 :             CHK_PRT_RET(sqeCount != 1, HCCL_ERROR("[DispatcherAicpu][MemcpyRtsq] sqeCount[%u] should be 1!", sqeCount), HCCL_E_INTERNAL);
    1192              : 
    1193              :             // 注意: 参考AddFlipTask, 先上报flip task (提醒profiling翻转taskid), 之后再拷贝到SQE ring buffer (捕捉placeholder SQE相关的profiling信息)
    1194              :             // 注意: ProfilingManager::TaskProfilingCallBack->ReportFilpTask不会扫描SQE ring buffer, 也不会更新其中的streamToSqeIdxMap_
    1195            0 :             if (callback_ != nullptr) {
    1196            0 :                 const rtStarsPlaceHolderSqe_t *placeholderSqePtr = reinterpret_cast<const rtStarsPlaceHolderSqe_t *>(sqeArray);
    1197            0 :                 hccl::FlipTaskPara para(stream.id(), placeholderSqePtr->header.taskId, placeholderSqePtr->u.flip_task_info.flipNumReport);
    1198            0 :                 hccl::TaskPara taskPara(TaskType::TASK_FLIP, para);
    1199            0 :                 callback_(callBackUserPtr_, (void *)&taskPara, sizeof(struct TaskPara));
    1200            0 :             }
    1201              :         }
    1202              : 
    1203              :         // 循环拷贝cached SQE到SQE ring buffer中
    1204            0 :         size_t reportSqeCount = 0;
    1205            0 :         while (reportSqeCount < sqeCount) {
    1206            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);
    1207            0 :             const size_t sqeTailLeft = HCCL_SQE_MAX_CNT - sqeContextBuffer->tailSqeIdx;
    1208            0 :             if (sqeTailLeft > 0) {
    1209              :                 // 准备profiling上报的目的末端基地址 (SQE ring buffer从tail开始拷贝)
    1210            0 :                 uint8_t *sqeLocalBuffTailBaseAddr = sqeContextBuffer->localBuff + sqeContextBuffer->tailSqeIdx * HCCL_SQE_SIZE;
    1211            0 :                 uint8_t *sqeTypeTailBaseAddr = sqeContextBuffer->sqeType + sqeContextBuffer->tailSqeIdx;
    1212            0 :                 AicpuDfxInfo *dfxInfoTailBaseAddr = sqeContextBuffer->dfxInfo + sqeContextBuffer->tailSqeIdx;
    1213            0 :                 uint64_t *profTimestapTailBaseAddr = sqeContextBuffer->profTimestap + sqeContextBuffer->tailSqeIdx;
    1214              : 
    1215              :                 // 向SQE ring buffer末端拷贝SQE信息[reportSqeCount, reportSqeCount + tmpSqeCount - 1] (只用于profiling上报, 不会下发)
    1216            0 :                 const size_t tmpSqeCount = std::min(sqeCount - reportSqeCount, sqeTailLeft);
    1217            0 :                 HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] report sqe profiling, sqeCount[%u] reportSqeCount[%u] tailSqeIdx[%u] sqeTailLeft[%u] tmpSqeCount[%u]", sqeCount, reportSqeCount, sqeContextBuffer->tailSqeIdx, sqeTailLeft, tmpSqeCount);
    1218              : 
    1219              :                 // 拷贝SQE内容
    1220            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(sqeLocalBuffTailBaseAddr, sqeTailLeft * HCCL_SQE_SIZE, sqeArray + reportSqeCount * HCCL_SQE_SIZE, tmpSqeCount * HCCL_SQE_SIZE));
    1221              : 
    1222              :                 // 拷贝SQE类型
    1223            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(sqeTypeTailBaseAddr, sqeTailLeft, sqeTypeArray + reportSqeCount, tmpSqeCount));
    1224              : 
    1225              :                 // 拷贝SQE DfxInfo
    1226            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(dfxInfoTailBaseAddr, sqeTailLeft * sizeof(AicpuDfxInfo), sqeDfxInfoArray + reportSqeCount, tmpSqeCount * sizeof(AicpuDfxInfo)));
    1227              : 
    1228              :                 // 拷贝SQE timestamp
    1229            0 :                 CHK_SAFETY_FUNC_RET(memcpy_s(profTimestapTailBaseAddr, sqeTailLeft * sizeof(uint64_t), profTimestamps.data() + profTimestampStartIdx + reportSqeCount, tmpSqeCount * sizeof(uint64_t)));
    1230              : 
    1231              :                 // 注意: sqeContextBuffer->sqeCnt不更新, 仍然为0 (即拷贝的SQE信息为已下发待上报), 避免SQE重复下发
    1232            0 :                 sqeContextBuffer->tailSqeIdx += static_cast<uint16_t>(tmpSqeCount);
    1233            0 :                 reportSqeCount += tmpSqeCount;
    1234              :             } else {
    1235              :                 // 注意: SQE ring buffer中待下发SQE数量一定为0, 不需要调用LaunchTask将待下发变成已下发待上报, 可以直接上报profiling将已下发待上报变成已上报
    1236              :                 // 注意: 调用后, ProfilingManager::StartReportSqeIdx为HCCL_SQE_MAX_CNT
    1237            0 :                 if (callback_ != nullptr) {
    1238            0 :                     hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1239            0 :                     hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1240            0 :                     callback_(callBackUserPtr_, (void *)&taskPara, sizeof(struct TaskPara));
    1241            0 :                 }
    1242              :                 
    1243              :                 // SQE ring buffer中所有SQE均为已上报 -> 清理SQE ring buffer
    1244            0 :                 HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] Sqe index to %u, need clear", HCCL_SQE_MAX_CNT);
    1245            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);
    1246            0 :                 CHK_RET(stream.ClearLocalBuff()); // 会将stream.sqeContextBuffer中的sqeCnt和tailSqeIdx设置为0
    1247            0 :                 CHK_PRT_RET(sqeContextBuffer->sqeCnt != 0, HCCL_ERROR("[DispatcherAicpu][MemcpyRtsq] sqeCnt[%u] should be 0 after clear", sqeContextBuffer->sqeCnt), HCCL_E_INTERNAL);
    1248            0 :                 CHK_PRT_RET(sqeContextBuffer->tailSqeIdx != 0, HCCL_ERROR("[DispatcherAicpu][MemcpyRtsq] tailSqeIdx[%u] should be 0 after clear", sqeContextBuffer->tailSqeIdx), HCCL_E_INTERNAL);
    1249              : 
    1250              :                 // 参考HcclCommAicpu::ClearLocalBuff, 调用Stream::ClearLocalBuff后, 应该调用ProfilingManager::UpdateStartReportSqeIdx手动将ProfilingManager::StartReportSqeIdx设置为0
    1251              :                 // 注意: 由于platform暂未将UpdateStartReportSqeIdx作为回调函数传入, 无法直接调用此framework函数 -> 通过callback_ (即ProfilingManager::TaskProfilingCallBack) 间接将ProfilingManager::StartReportSqeIdx设置为0
    1252              :                 // 注意: 由于调用前ProfilingManager::StartReportSqeIdx为HCCL_SQE_MAX_CNT, tailSqeIdx为0, 即从startIdx=HCCL_SQE_MAX_CNT到endIdx=0, ProfilingManager不会进入profiling上报代码, 而是只会调用UpdateStartReportSqeIdx设置StartReportSqeIdx为0
    1253            0 :                 if (callback_ != nullptr) {
    1254            0 :                     HCCL_INFO("[DispatcherAicpu][MemcpyRtsq] re-invoke callback_ to reset StartReportSqeIdx as 0 in ProfilingManager");
    1255              : 
    1256            0 :                     hccl::AiCPUStreamTasks para(stream.id(), reinterpret_cast<void*>(sqeContext));
    1257            0 :                     hccl::TaskPara taskPara(TaskType::TASK_BATCH_REPORT, para);
    1258            0 :                     callback_(callBackUserPtr_, (void *)&taskPara, sizeof(struct TaskPara));
    1259            0 :                 }
    1260              :             }
    1261              :         }
    1262              :     }
    1263              : 
    1264            0 :     return HCCL_SUCCESS;
    1265              : }
    1266              : 
    1267            0 : HcclResult DispatcherAiCpu::AddFlipTask(Stream &stream)
    1268              : {
    1269            0 :     HcclSqeContext *sqeContext = stream.GetSqeContextPtr();
    1270            0 :     CHK_PTR_NULL(sqeContext);
    1271            0 :     SqeRingBuffer *sqeContextBuffer = &(sqeContext->buffer);
    1272            0 :     CHK_PTR_NULL(sqeContextBuffer);
    1273            0 :     uint16_t flipNum = sqeContextBuffer->filpNum;
    1274            0 :     uint16_t taskId = sqeContextBuffer->tailSqeTaskId;
    1275              : 
    1276            0 :     if (callback_ != nullptr) {
    1277            0 :         hccl::FlipTaskPara para(stream.id(), taskId, flipNum);
    1278            0 :         hccl::TaskPara taskPara(TaskType::TASK_FLIP, para);
    1279            0 :         callback_(callBackUserPtr_, (void *)&taskPara, sizeof(struct TaskPara));
    1280            0 :     }
    1281              : 
    1282            0 :     const HcclComStreamInfo &streamInfo = stream.GetHcclStreamInfo();
    1283              :  
    1284            0 :     uint8_t *sqeBufferAddr = nullptr;
    1285            0 :     uint8_t *sqeTypeAddr = nullptr;
    1286            0 :     uint8_t *sqeDfxInfoAddr = nullptr;
    1287            0 :     CHK_RET(stream.GetNextSqeBufferAddr(sqeBufferAddr, sqeTypeAddr, sqeDfxInfoAddr, taskId));
    1288              :  
    1289            0 :     AicpuDfxInfo * const dfxInfo = (AicpuDfxInfo * const)sqeDfxInfoAddr;
    1290            0 :     dfxInfo->opRingBufferIdx = opRingBufferIdx_;
    1291            0 :     dfxInfo->remoteRank = INVALID_VALUE_RANKID;
    1292            0 :     dfxInfo->notifyId = INVALID_VALUE_RANKID;
    1293            0 :     addOneFlipPlaceHolderSqe_(streamInfo.actualStreamId, flipNum, taskId, sqeBufferAddr, sqeTypeAddr);
    1294              :  
    1295            0 :     PLF_CONFIG_INFO(PLF_TASK,
    1296              :         "%s para: taskId[%u] streamId[%u] flipNum[%u]", __func__, taskId, streamInfo.actualStreamId, flipNum);
    1297            0 :     return HCCL_SUCCESS;
    1298              : }
    1299              : 
    1300            0 : HcclResult DispatcherAiCpu::AddRetryPreamble(Stream &stream)
    1301              : {
    1302            0 :     return AddFlipTask(stream);
    1303              : }
    1304              : 
    1305           22 : void DispatcherAiCpu::SaveStreamInfo(hccl::Stream &stream)
    1306              : {
    1307           22 :     const HcclComStreamInfo &streamInfo = stream.GetHcclStreamInfo();
    1308           22 :     auto it = streamMap_.find(streamInfo.actualStreamId);
    1309           22 :     if (it == streamMap_.end()) {
    1310           17 :         streamMap_.insert({streamInfo.actualStreamId, stream});
    1311           17 :         HCCL_INFO("[DispatcherAiCpu][SaveStreamInfo] stream id[%d]", streamInfo.actualStreamId);
    1312            5 :     } else if (it->second.IsInvalid()) {
    1313              :         // stream id复用: 旧stream已销毁(IsInvalid=true), 用新stream覆盖, 否则dispatcher会一直跳过该id
    1314            0 :         it->second = stream;
    1315            0 :         HCCL_INFO("[DispatcherAiCpu][SaveStreamInfo] refresh invalidated stream id stream id[%d]", streamInfo.actualStreamId);
    1316              :     }
    1317           44 :     return;
    1318              : }
    1319              : 
    1320            2 : HcclResult DispatcherAiCpu::StreamSync(Stream &stream)
    1321              : {
    1322            2 :     uint32_t head = 0;
    1323            2 :     uint32_t tail = 0;
    1324              :     const HcclComStreamInfo *streamInfo;
    1325            2 :     u64 startUsec = GetCurAicpuTimestamp();
    1326            2 :     u64 lastUsec = startUsec;
    1327            2 :     CHK_RET(stream.GetStreamInfo(streamInfo));
    1328              : 
    1329            2 :     CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo->sqId, DRV_SQCQ_PROP_SQ_TAIL, tail));
    1330            2 :     HCCL_INFO("StreamSync aicpu stream sqid[%d] tail[%u]", streamInfo->sqId, tail);
    1331              :     do {
    1332            2 :         CHK_RET(QuerySqStatusByType(aicpuInfo_.devId, streamInfo->sqId, DRV_SQCQ_PROP_SQ_HEAD, head));
    1333            2 :         u64 curUsec = GetCurAicpuTimestamp();
    1334            2 :         if (curUsec - startUsec > NANOSECOND_TO_SECOND * dfxTimeOutConfig_.sqeTimeOutTimeOut) {
    1335            1 :             HCCL_ERROR("stream sync timeout %lus. curhead:%u, curtall:%u, sqId:%d",
    1336              :                 dfxTimeOutConfig_.sqeTimeOutTimeOut, head, tail, streamInfo->sqId);
    1337            1 :             return HCCL_E_TIMEOUT;
    1338              :         }
    1339              : 
    1340              :         // 等待下发阶段,每隔30s打印一次状态
    1341            1 :         if (curUsec - lastUsec > NANOSECOND_TO_SECOND * dfx::kPrintSqInterval) {
    1342            0 :             lastUsec = curUsec;
    1343            0 :             HCCL_RUN_INFO("[StreamSync]Current state. sqid:%d, head:%u, tail:%u",
    1344              :                 streamInfo->sqId, head, tail);
    1345              :         }
    1346            1 :     } while (head != tail);
    1347              : 
    1348            1 :     return HCCL_SUCCESS;
    1349              : }
    1350              : 
    1351            5 : u64 DispatcherAiCpu::CalcDbAddr(u32 dbindex)
    1352              : {
    1353            5 :     u64 dbAddr = 0;
    1354            5 :     if (aicpuInfo_.devType == DevType::DEV_TYPE_910_93) {
    1355              :         // 910_93 HCCS_SW 组网
    1356            2 :         constexpr u64 roceBaseAddr = 0x202000000000ULL;
    1357            2 :         constexpr u64 roceVfDbCfg0Reg = 0x230ULL;
    1358            2 :         constexpr u64 chipAddrOffset = 0x20000000000ULL;
    1359            2 :         constexpr u64 dieAddrOffset = 0x10000000000ULL;
    1360            2 :         constexpr u32 dbDieIdMask = 0x00ff0000;
    1361            2 :         constexpr u32 dbDieIdShift = 16; // 16 is dbDieIdShift
    1362            2 :         dbAddr = roceBaseAddr + roceVfDbCfg0Reg + chipAddrOffset * aicpuInfo_.chipId +
    1363            2 :             dieAddrOffset * ((dbindex & dbDieIdMask) >> dbDieIdShift);
    1364              :     } else {
    1365            3 :         constexpr u64 roceBaseAddr = 0x2000000000ULL;
    1366            3 :         constexpr u64 roceVfDbCfg0Reg = 0x230ULL;
    1367            3 :         constexpr u64 chipAddrOffset = 0x80000000000ULL;
    1368            3 :         constexpr u64 dieAddrOffset = 0x10000000000ULL;
    1369            3 :         constexpr u32 dbDieIdMask = 0x00ff0000;
    1370            3 :         constexpr u32 dbDieIdShift = 16; // 16 is dbDieIdShift
    1371            3 :         dbAddr = roceBaseAddr + roceVfDbCfg0Reg + chipAddrOffset * aicpuInfo_.chipId +
    1372            3 :             dieAddrOffset * ((dbindex & dbDieIdMask) >> dbDieIdShift);
    1373              :     }
    1374              : 
    1375            5 :     HCCL_DEBUG("%s dbindex:%u, devType:%u, chipId:%lld, dbAddr:%llu",
    1376              :         __func__, dbindex, aicpuInfo_.devType, aicpuInfo_.chipId, dbAddr);
    1377            5 :     return dbAddr;
    1378              : }
    1379              : 
    1380          444 : void DispatcherAiCpu::InitTimeOutConfig()
    1381              : {
    1382          444 :     dfxTimeOutConfig_.useCredit = false;
    1383          444 :     dfxTimeOutConfig_.sqeTimeOutTimeOut = GetMaxNotifyWaitTime();
    1384          444 :     dfxTimeOutConfig_.sqeCreditTimeOut = RT_STARS_NEVER_TIMEOUT_KERNEL_CREDIT;
    1385          444 :     dfxTimeOutConfig_.sqeWaitTimeOut = dfx::kKfcTimeOut;
    1386          444 :     dfxTimeOutConfig_.sqFullWaitTimeOut = dfx::kSqFullWaitTimeOut;
    1387          444 :     HCCL_INFO("[DispatcherAiCpu][InitTimeOutConfig]DFX timeout config init successfully with details: [%s]",
    1388              :         dfxTimeOutConfig_.ToString().c_str());
    1389          444 : }
    1390              : } // namespace hccl
        

Generated by: LCOV version 2.0-1