LCOV - code coverage report
Current view: top level - server - hccl_process.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.4 % 223 186
Test Date: 2026-08-12 11:05:07 Functions: 94.1 % 17 16

            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 "hccl_process.h"
      12              : #include <cstdint>
      13              : #include "fsm/state_base.h"
      14              : #include "common/bqs_log.h"
      15              : #include "queue_manager.h"
      16              : #include "statistic_manager.h"
      17              : #include "entity_manager.h"
      18              : #include "router_server.h"
      19              : #include "profile_manager.h"
      20              : 
      21              : namespace dgw {
      22              : namespace {
      23              : // call hccl api max count when processing one event
      24              : constexpr uint32_t GET_DATA_THRESHOLD = 100U;
      25              : // supply hccl events
      26              : const std::vector<uint32_t> g_supplyEvents = {
      27              :     EVENT_RECV_REQUEST_MSG, EVENT_SEND_COMPLETION_MSG, EVENT_RECV_COMPLETION_MSG};
      28              : // link setup timeout gap
      29              : constexpr float64_t LINK_SET_UP_TIMEOUE = 60000000.0;
      30              : } // namespace
      31              : 
      32           15 : HcclProcess& HcclProcess::GetInstance()
      33              : {
      34              :     static HcclProcess instance;
      35           15 :     instance.Init();
      36           15 :     return instance;
      37              : }
      38              : 
      39           16 : void HcclProcess::Init()
      40              : {
      41           16 :     if (inited_) {
      42           14 :         return;
      43              :     }
      44            2 :     oneTrackEventEnabled_ = false;
      45            2 :     inited_ = true;
      46              : }
      47              : 
      48            3 : FsmStatus HcclProcess::ProcessRecvRequestEvent(
      49              :     const event_info& event, const uint32_t deviceId, const uint32_t resIndex)
      50              : {
      51            3 :     if (oneTrackEventEnabled_) {
      52            1 :         return FsmStatus::FSM_SUCCESS;
      53              :     }
      54            2 :     auto ret = FsmStatus::FSM_SUCCESS;
      55            2 :     auto& recvRequestEventAtomicFlag =
      56              :         (resIndex == 0U) ? recvRequestEventAtomicFlag_ : recvRequestEventAtomicFlagExtra_;
      57            2 :     if (!recvRequestEventAtomicFlag.test_and_set()) {
      58            2 :         DGW_LOG_INFO("Begin to process recv request event.");
      59              :         // init profiling data
      60            2 :         const uint64_t eventBegin = bqs::ProfileManager::GetInstance(resIndex).GetCpuTick();
      61            2 :         const uint64_t schedDelay = static_cast<uint64_t>(event.comm.sched_timestamp - event.comm.submit_timestamp);
      62            2 :         const uint64_t schedTimes = bqs::StatisticManager::GetInstance().HcclMpiRecvRequestEventStat();
      63            2 :         bqs::ProfileManager::GetInstance(resIndex).InitMarkerForRecvReqEvent(schedTimes, schedDelay);
      64              :         // process recv request
      65              :         const std::function<FsmStatus(const ChannelEntityPtr&, uint32_t&)> probeFunc =
      66            6 :             [this](const ChannelEntityPtr& entity, uint32_t& probeCount) -> FsmStatus {
      67            2 :             return ProbeCommChannel(entity, probeCount);
      68            2 :         };
      69            2 :         ret = EntityManager::Instance(resIndex).ProbeSrcCommChannel(probeFunc);
      70              :         // print profiling data
      71            2 :         bqs::ProfileManager::GetInstance(resIndex).DoMarkerForRecvReqEvent(eventBegin);
      72              :         // clear event working flag
      73              :         recvRequestEventAtomicFlag.clear();
      74              : 
      75              :         // ack event: if reply action in atomic lock, it maybe cause lost event
      76            2 :         (void)ReplyHcclEvent(event, deviceId);
      77              :         // postprocess: check and supply recv request event
      78            2 :         (void)EntityManager::Instance(resIndex).SupplyRecvRequestEvent();
      79            2 :     } else {
      80            0 :         bqs::StatisticManager::GetInstance().HcclMpiRecvReqFalseAwakenStat();
      81            0 :         ret = FsmStatus::FSM_FAILED;
      82            0 :         DGW_LOG_INFO("Recv request event is being processed by other thread.");
      83              :     }
      84            2 :     return ret;
      85              : }
      86              : 
      87            4 : FsmStatus HcclProcess::ProcessSendCompletionEvent(
      88              :     const event_info& event, const uint32_t deviceId, const uint32_t resIndex)
      89              : {
      90            4 :     if (oneTrackEventEnabled_) {
      91            1 :         return FsmStatus::FSM_SUCCESS;
      92              :     }
      93            3 :     auto ret = FsmStatus::FSM_SUCCESS;
      94            3 :     auto& sendCompEventAtomicFlag = (resIndex == 0U) ? sendCompEventAtomicFlag_ : sendCompEventAtomicFlagExtra_;
      95            3 :     if (!sendCompEventAtomicFlag.test_and_set()) {
      96            3 :         DGW_LOG_INFO("Begin to process send completion event.");
      97              :         // init profiling data
      98            3 :         const uint64_t eventBegin = bqs::ProfileManager::GetInstance(resIndex).GetCpuTick();
      99            3 :         const uint64_t schedDelay = static_cast<uint64_t>(event.comm.sched_timestamp - event.comm.submit_timestamp);
     100            3 :         const uint64_t schedTimes = bqs::StatisticManager::GetInstance().HcclMpiSendCompEventStat();
     101            3 :         bqs::ProfileManager::GetInstance(resIndex).InitMarkerForSendCompEvent(schedTimes, schedDelay);
     102              :         // process send comppletion
     103              :         const std::function<FsmStatus(CommChannels&, uint32_t&, uint32_t&)> testSomeFunc =
     104            9 :             [this](CommChannels& channels, uint32_t& totalCompCount, uint32_t& resIndexTmp) -> FsmStatus {
     105            3 :             return TestSomeCommChannels(channels, false, totalCompCount, resIndexTmp);
     106            3 :         };
     107            3 :         ret = EntityManager::Instance(resIndex).TestSomeCommChannels(testSomeFunc, false);
     108              :         // print profiling data
     109            3 :         bqs::ProfileManager::GetInstance(resIndex).DoMarkerForSendCompEvent(eventBegin);
     110              :         // clear event working flag
     111              :         sendCompEventAtomicFlag.clear();
     112              : 
     113              :         // ack event: if reply action in atomic lock, it maybe cause lost event
     114            3 :         (void)ReplyHcclEvent(event, deviceId);
     115            3 :         DGW_LOG_INFO("reply event[%u], deviceId[%u] success.", event.comm.event_id, deviceId);
     116            3 :     } else {
     117            0 :         bqs::StatisticManager::GetInstance().HcclMpiSendCompFalseAwakenStat();
     118            0 :         ret = FsmStatus::FSM_FAILED;
     119            0 :         DGW_LOG_INFO("Send completion event is being processed by other thread.");
     120              :     }
     121            3 :     return ret;
     122              : }
     123              : 
     124            5 : FsmStatus HcclProcess::ProcessRecvCompletionEvent(
     125              :     const event_info& event, const uint32_t deviceId, const uint32_t resIndex)
     126              : {
     127            5 :     auto ret = FsmStatus::FSM_SUCCESS;
     128            5 :     auto& recvCompEventAtomicFlag = (resIndex == 0U) ? recvCompEventAtomicFlag_ : recvCompEventAtomicFlagExtra_;
     129            5 :     if (!recvCompEventAtomicFlag.test_and_set()) {
     130            5 :         DGW_LOG_INFO("Begin to process recv completion event.deviceId[%u]", deviceId);
     131              :         // init profiling data
     132            5 :         const uint64_t eventBegin = bqs::ProfileManager::GetInstance(resIndex).GetCpuTick();
     133            5 :         const uint64_t schedDelay = static_cast<uint64_t>(event.comm.sched_timestamp - event.comm.submit_timestamp);
     134            5 :         const uint64_t schedTimes = bqs::StatisticManager::GetInstance().HcclMpiRecvCompEventStat();
     135            5 :         bqs::ProfileManager::GetInstance(resIndex).InitMarkerForRecvCompEvent(schedTimes, schedDelay);
     136              :         // process recv completion event
     137              :         const std::function<FsmStatus(CommChannels&, uint32_t&, uint32_t&)> testSomeFunc =
     138           15 :             [this](CommChannels& channels, uint32_t& totalCompCount, uint32_t& resIndexTmp) -> FsmStatus {
     139            5 :             return TestSomeCommChannels(channels, true, totalCompCount, resIndexTmp);
     140            5 :         };
     141            5 :         ret = EntityManager::Instance(resIndex).TestSomeCommChannels(testSomeFunc, true);
     142              : 
     143            5 :         if (oneTrackEventEnabled_) {
     144              :             // process send comppletion
     145              :             const std::function<FsmStatus(CommChannels&, uint32_t&, uint32_t&)> testSomeSendFunc =
     146            9 :                 [this](CommChannels& channels, uint32_t& totalCompCount, uint32_t& resIndexTmp) -> FsmStatus {
     147            3 :                 return TestSomeCommChannels(channels, false, totalCompCount, resIndexTmp);
     148            3 :             };
     149            3 :             (void)EntityManager::Instance(resIndex).TestSomeCommChannels(testSomeSendFunc, false);
     150              : 
     151              :             // process recv request
     152              :             const std::function<FsmStatus(const ChannelEntityPtr&, uint32_t&)> probeFunc =
     153            9 :                 [this](const ChannelEntityPtr& entity, uint32_t& probeCount) -> FsmStatus {
     154            3 :                 return ProbeCommChannel(entity, probeCount);
     155            3 :             };
     156            3 :             (void)EntityManager::Instance(resIndex).ProbeSrcCommChannel(probeFunc);
     157            3 :             (void)EntityManager::Instance(resIndex).SupplyOneTrackEvent();
     158            3 :         }
     159              : 
     160              :         // clear event working flag
     161              :         recvCompEventAtomicFlag.clear();
     162              :         // ack event: if reply action in atomic lock, it maybe cause lost event
     163            5 :         (void)ReplyHcclEvent(event, deviceId);
     164              :         // print profiling data
     165            5 :         bqs::ProfileManager::GetInstance(resIndex).DoMarkerForRecvCompEvent(eventBegin);
     166            5 :         DGW_LOG_INFO("reply event[%u], deviceId[%u] success.", event.comm.event_id, deviceId);
     167            5 :     } else {
     168            0 :         bqs::StatisticManager::GetInstance().HcclMpiRecvCompFalseAwakenStat();
     169            0 :         ret = FsmStatus::FSM_FAILED;
     170            0 :         DGW_LOG_INFO("Send completion event is being processed by other thread.");
     171              :     }
     172            5 :     return ret;
     173              : }
     174              : 
     175            1 : FsmStatus HcclProcess::ProcessCongestionReliefEvent(
     176              :     const event_info& event, const uint32_t deviceId, const uint32_t resIndex) const
     177              : {
     178              :     (void)deviceId;
     179              :     (void)event;
     180              :     (void)resIndex;
     181            1 :     DGW_LOG_ERROR("WARNING! Receive congestion relief event!");
     182            1 :     bqs::StatisticManager::GetInstance().HcclMpiF2nfEventStat();
     183            1 :     return FsmStatus::FSM_SUCCESS;
     184              : }
     185              : 
     186           11 : FsmStatus HcclProcess::TestSomeCommChannels(
     187              :     CommChannels& channels, const bool isSrc, uint32_t& totalCompCount, const uint32_t resIndex) const
     188              : {
     189           11 :     auto& entities = channels.entities;
     190           11 :     auto& requests = channels.requests;
     191              :     // check request count
     192           11 :     if (entities.size() > requests.capacity()) {
     193            0 :         DGW_LOG_ERROR(
     194              :             "WARNING: Please check requests capacity[%zu] which is less than entities size[%zu].", requests.capacity(),
     195              :             entities.size());
     196            0 :         return FsmStatus::FSM_FAILED;
     197              :     }
     198              : 
     199           11 :     auto ret = FsmStatus::FSM_SUCCESS;
     200           11 :     uint32_t reqCount = 0U;
     201           11 :     totalCompCount = 0U;
     202           24 :     while (reqCount < GET_DATA_THRESHOLD) {
     203              :         // fill requests
     204           24 :         bool allNullReq = true;
     205           24 :         size_t index = 0UL;
     206           45 :         for (auto iter = entities.begin(); iter != entities.end(); ++iter) {
     207           21 :             const RequestInfo* const hcclReq = (*iter)->FrontUncompReq();
     208           21 :             if (((*iter)->linkStatus_ == ChannelLinkStatus::ABNORMAL) || (hcclReq == nullptr)) {
     209            8 :                 requests[index++] = HCCL_REQUEST_NULL;
     210              :             } else {
     211           13 :                 if (!(hcclReq->isLink)) {
     212            8 :                     requests[index++] = hcclReq->req;
     213            8 :                     allNullReq = false;
     214            8 :                     DGW_LOG_DEBUG("Prepare to testsome req of entity[%s].", (*iter)->ToString().c_str());
     215              :                 } else {
     216            5 :                     if (PreProcessSetUplinkReq(hcclReq) == FsmStatus::FSM_SUCCESS) {
     217            5 :                         requests[index++] = hcclReq->req;
     218            5 :                         allNullReq = false;
     219              :                     } else {
     220            0 :                         requests[index++] = HCCL_REQUEST_NULL;
     221            0 :                         (*iter)->linkStatus_ = ChannelLinkStatus::ABNORMAL;
     222            0 :                         DGW_LOG_ERROR("entity[%s] link setup timeout.", (*iter)->ToString().c_str());
     223              :                     }
     224              :                 }
     225              :             }
     226              :         }
     227           24 :         if (allNullReq) {
     228           11 :             DGW_LOG_DEBUG("Not exist any request which need to be tested.");
     229           11 :             break;
     230              :         }
     231              :         // call HcclTestSome
     232           13 :         int32_t compCount = 0;
     233           13 :         auto& compIndices = channels.compIndices;
     234           13 :         auto& compStatus = channels.compStatus;
     235           13 :         const uint64_t begin = bqs::ProfileManager::GetInstance(resIndex).GetCpuTick();
     236           26 :         const auto hcclRet = HcclTestSome(
     237           13 :             static_cast<int32_t>(entities.size()), requests.data(), &compCount, compIndices.data(), compStatus.data());
     238           26 :         bqs::ProfileManager::GetInstance(resIndex).AddHcclTestSomeCost(
     239           13 :             bqs::ProfileManager::GetInstance(resIndex).GetCpuTick() - begin, isSrc);
     240           13 :         if (hcclRet == static_cast<int32_t>(HCCL_E_IN_STATUS)) {
     241            1 :             DGW_LOG_INFO("Test some is unreachable, ret is [%d].", hcclRet);
     242           12 :         } else if (hcclRet != static_cast<int32_t>(HCCL_SUCCESS)) {
     243            0 :             DGW_LOG_ERROR("Failed to test some, ret is [%d].", hcclRet);
     244            0 :             ret = FsmStatus::FSM_FAILED;
     245            0 :             break;
     246              :         }
     247           13 :         reqCount++;
     248              : 
     249           13 :         if (compCount == 0) {
     250            0 :             DGW_LOG_INFO("Not exist test completed request.");
     251            0 :             break;
     252              :         }
     253           13 :         totalCompCount += static_cast<uint32_t>(compCount);
     254              :         // check result
     255           13 :         (void)ProcTestSomeResults(compCount, channels, hcclRet);
     256              :     }
     257           11 :     if ((!isSrc) && (totalCompCount != 0U)) {
     258            3 :         (void)EntityManager::Instance(resIndex).SupplyEvent(static_cast<uint32_t>(EVENT_QUEUE_FULL_TO_NOT_FULL));
     259            3 :         DGW_LOG_INFO("Success to trigger tag f2nf event.");
     260              :     }
     261           11 :     DGW_LOG_INFO("Test some comm channels success count is %u.", reqCount);
     262           11 :     return ret;
     263              : }
     264              : 
     265           13 : FsmStatus HcclProcess::ProcTestSomeResults(const int32_t compCount, CommChannels& channels, int32_t hcclRet) const
     266              : {
     267           26 :     for (size_t i = 0UL; i < static_cast<size_t>(compCount); i++) {
     268           13 :         const size_t reqIdx = static_cast<size_t>(channels.compIndices[i]);
     269           13 :         HcclStatus& status = channels.compStatus[i];
     270           13 :         ChannelEntityPtr& entity = channels.entities[reqIdx];
     271              :         // check status
     272           13 :         if (status.error != 0) {
     273            1 :             DGW_LOG_ERROR(
     274              :                 "Comm channel[%s] test some failed, status:[rank:%d, tag:%d, error:%d], hcclRet[%d].",
     275              :                 entity->ToString().c_str(), status.srcRank, status.tag, status.error, hcclRet);
     276            1 :             if (((status.error == static_cast<int32_t>(HCCL_E_TCP_TRANSFER)) ||
     277            1 :                  (status.error == static_cast<int32_t>(HCCL_E_ROCE_TRANSFER))) &&
     278              :                 (hcclRet == HCCL_E_IN_STATUS)) {
     279            1 :                 entity->linkStatus_ = ChannelLinkStatus::ABNORMAL;
     280            1 :                 DGW_LOG_RUN_INFO("set entity link status is abnormal.");
     281              :             }
     282            1 :             continue;
     283              :         }
     284              :         // process completed request
     285           12 :         (void)entity->ProcessCompReq();
     286              :     }
     287           13 :     return FsmStatus::FSM_SUCCESS;
     288              : }
     289              : 
     290            5 : FsmStatus HcclProcess::ProbeCommChannel(const ChannelEntityPtr& entity, uint32_t& probeCount) const
     291              : {
     292            5 :     if (entity == nullptr) {
     293            0 :         probeCount = 0U;
     294            0 :         return FsmStatus::FSM_FAILED;
     295              :     }
     296            5 :     HcclMessage msg = nullptr;
     297            5 :     uint64_t dataCount = 0UL;
     298              : 
     299            5 :     uint32_t reqTotalCount = 0U;
     300            5 :     uint32_t envelopeCacheCount = 0U;
     301            5 :     uint64_t probeTick = 0UL;
     302           17 :     while (reqTotalCount < GET_DATA_THRESHOLD) {
     303           17 :         auto ret = entity->Probe(dataCount, msg, probeTick);
     304              :         // uncompReqQueue_ full, cache envelope, then continue probe
     305           17 :         if (ret == FsmStatus::FSM_CACHED) {
     306            4 :             envelopeCacheCount++;
     307            4 :             reqTotalCount++;
     308            4 :             continue;
     309              :         }
     310              :         // probe failed, perhaps current channel have no envelope, quit the loop
     311           13 :         if (ret != FsmStatus::FSM_SUCCESS) {
     312            5 :             break;
     313              :         }
     314              :         // probe success, alloc mbuf and call HcclImrecv to get request
     315            8 :         reqTotalCount++;
     316            8 :         ret = entity->ReceiveData(msg, dataCount, probeTick);
     317            8 :         if (ret != FsmStatus::FSM_SUCCESS) {
     318            0 :             break;
     319              :         }
     320              :     }
     321            5 :     probeCount = reqTotalCount;
     322            5 :     DGW_LOG_INFO(
     323              :         "Probe comm channel success, total count is [%u], envelope cached count is [%u], entity:[%s].", reqTotalCount,
     324              :         envelopeCacheCount, entity->ToString().c_str());
     325            5 :     return FsmStatus::FSM_SUCCESS;
     326              : }
     327              : 
     328            0 : FsmStatus HcclProcess::SupplyEvents(const uint32_t resIndex) const
     329              : {
     330              :     // supply F2NF event
     331            0 :     (void)EntityManager::Instance(resIndex).SupplyEvent(static_cast<uint32_t>(EVENT_QUEUE_FULL_TO_NOT_FULL));
     332              : 
     333            0 :     if (!bqs::RouterServer::GetInstance().GetCallHcclFlag()) {
     334            0 :         return FsmStatus::FSM_SUCCESS;
     335              :     }
     336              :     // supply hccl event
     337            0 :     if (oneTrackEventEnabled_) {
     338            0 :         (void)EntityManager::Instance(resIndex).SupplyEvent(EVENT_RECV_COMPLETION_MSG);
     339              :     } else {
     340            0 :         for (const auto eventId : g_supplyEvents) {
     341            0 :             (void)EntityManager::Instance(resIndex).SupplyEvent(eventId);
     342              :         };
     343              :     }
     344            0 :     DGW_LOG_INFO("Supply event success.");
     345            0 :     return FsmStatus::FSM_SUCCESS;
     346              : }
     347              : 
     348           10 : FsmStatus HcclProcess::ReplyHcclEvent(const event_info& event, const uint32_t deviceId) const
     349              : {
     350           10 :     const uint32_t eventId = static_cast<uint32_t>(event.comm.event_id);
     351              :     // ack event
     352              :     const auto drvRet =
     353           10 :         halEschedAckEvent(deviceId, static_cast<EVENT_ID>(eventId), event.comm.subevent_id, nullptr, 0U);
     354           10 :     if (drvRet != DRV_ERROR_NONE) {
     355            0 :         DGW_LOG_ERROR("Failed to reply event[%u], deviceId[%u], ret is %d.", eventId, deviceId, drvRet);
     356            0 :         return FsmStatus::FSM_FAILED;
     357              :     }
     358           10 :     DGW_LOG_INFO("reply event[%u], deviceId[%u] success.", eventId, deviceId);
     359              : 
     360              :     // statistic callback count
     361           10 :     switch (eventId) {
     362            2 :         case dgw::EVENT_RECV_REQUEST_MSG: {
     363            2 :             bqs::StatisticManager::GetInstance().HcclMpiRecvReqCallbackStat();
     364            2 :             break;
     365              :         }
     366            3 :         case dgw::EVENT_SEND_COMPLETION_MSG: {
     367            3 :             bqs::StatisticManager::GetInstance().HcclMpiSendCompCallbackStat();
     368            3 :             break;
     369              :         }
     370            5 :         case dgw::EVENT_RECV_COMPLETION_MSG: {
     371            5 :             bqs::StatisticManager::GetInstance().HcclMpiRecvCompCallbackStat();
     372            5 :             break;
     373              :         }
     374            0 :         default: {
     375            0 :             DGW_LOG_ERROR("Unsupported event[%u].", eventId);
     376            0 :             break;
     377              :         }
     378              :     }
     379           10 :     return FsmStatus::FSM_SUCCESS;
     380              : }
     381              : 
     382            7 : FsmStatus HcclProcess::PreProcessSetUplinkReq(const RequestInfo* const hcclReq) const
     383              : {
     384            7 :     const uint64_t curTick = bqs::ProfileManager::GetInstance().GetCpuTick();
     385            7 :     if (curTick >= hcclReq->startTick) {
     386            6 :         const auto timeCost = bqs::ProfileManager::GetInstance().GetTimeCost(curTick - hcclReq->startTick);
     387            6 :         if (timeCost >= LINK_SET_UP_TIMEOUE) {
     388            1 :             DGW_LOG_ERROR(
     389              :                 "curtick:%lu, setuptick:%lu, threshold:%.2fus, linkSetUp timeout:%.2fus.", curTick, hcclReq->startTick,
     390              :                 LINK_SET_UP_TIMEOUE, timeCost);
     391            1 :             return FsmStatus::FSM_FAILED;
     392              :         }
     393            5 :         return FsmStatus::FSM_SUCCESS;
     394              :     }
     395            1 :     DGW_LOG_ERROR("cur tick:%lu is smaller than SetUpTick:%lu.", curTick, hcclReq->startTick);
     396            1 :     return FsmStatus::FSM_FAILED;
     397              : }
     398              : } // namespace dgw
        

Generated by: LCOV version 2.0-1