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-07-28 10:54:05 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 = {EVENT_RECV_REQUEST_MSG,
      27              :     EVENT_SEND_COMPLETION_MSG, EVENT_RECV_COMPLETION_MSG};
      28              : // link setup timeout gap
      29              : constexpr float64_t LINK_SET_UP_TIMEOUE = 60000000.0;
      30              : }
      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(const event_info &event, const uint32_t deviceId,
      49              :     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 = (resIndex == 0U) ?
      56              :         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(const event_info &event, const uint32_t deviceId,
      88              :     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(const event_info &event, const uint32_t deviceId,
     125              :     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(const event_info &event, const uint32_t deviceId,
     176              :     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(CommChannels &channels, const bool isSrc, uint32_t &totalCompCount,
     187              :     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("WARNING: Please check requests capacity[%zu] which is less than entities size[%zu].",
     194              :             requests.capacity(), entities.size());
     195            0 :         return FsmStatus::FSM_FAILED;
     196              :     }
     197              : 
     198           11 :     auto ret = FsmStatus::FSM_SUCCESS;
     199           11 :     uint32_t reqCount = 0U;
     200           11 :     totalCompCount = 0U;
     201           24 :     while (reqCount < GET_DATA_THRESHOLD) {
     202              :         // fill requests
     203           24 :         bool allNullReq = true;
     204           24 :         size_t index = 0UL;
     205           45 :         for (auto iter = entities.begin(); iter != entities.end(); ++iter) {
     206           21 :             const RequestInfo * const hcclReq = (*iter)->FrontUncompReq();
     207           21 :             if (((*iter)->linkStatus_ == ChannelLinkStatus::ABNORMAL) || (hcclReq == nullptr)) {
     208            8 :                 requests[index++] = HCCL_REQUEST_NULL;
     209              :             } else {
     210           13 :                 if (!(hcclReq->isLink)) {
     211            8 :                     requests[index++] = hcclReq->req;
     212            8 :                     allNullReq = false;
     213            8 :                     DGW_LOG_DEBUG("Prepare to testsome req of entity[%s].", (*iter)->ToString().c_str());
     214              :                 } else {
     215            5 :                     if (PreProcessSetUplinkReq(hcclReq) == FsmStatus::FSM_SUCCESS) {
     216            5 :                         requests[index++] = hcclReq->req;
     217            5 :                         allNullReq = false;
     218              :                     } else {
     219            0 :                         requests[index++] = HCCL_REQUEST_NULL;
     220            0 :                         (*iter)->linkStatus_ = ChannelLinkStatus::ABNORMAL;
     221            0 :                         DGW_LOG_ERROR("entity[%s] link setup timeout.", (*iter)->ToString().c_str());
     222              :                     }
     223              :                 }
     224              :             }
     225              :         }
     226           24 :         if (allNullReq) {
     227           11 :             DGW_LOG_DEBUG("Not exist any request which need to be tested.");
     228           11 :             break;
     229              :         }
     230              :         // call HcclTestSome
     231           13 :         int32_t compCount = 0;
     232           13 :         auto &compIndices = channels.compIndices;
     233           13 :         auto &compStatus = channels.compStatus;
     234           13 :         const uint64_t begin = bqs::ProfileManager::GetInstance(resIndex).GetCpuTick();
     235           13 :         const auto hcclRet = HcclTestSome(static_cast<int32_t>(entities.size()), requests.data(),
     236              :                                           &compCount, compIndices.data(), compStatus.data());
     237           26 :         bqs::ProfileManager::GetInstance(resIndex).AddHcclTestSomeCost(
     238           13 :             bqs::ProfileManager::GetInstance(resIndex).GetCpuTick() - begin, isSrc);
     239           13 :         if (hcclRet == static_cast<int32_t>(HCCL_E_IN_STATUS)) {
     240            1 :             DGW_LOG_INFO("Test some is unreachable, ret is [%d].", hcclRet);
     241           12 :         } else if (hcclRet != static_cast<int32_t>(HCCL_SUCCESS)) {
     242            0 :             DGW_LOG_ERROR("Failed to test some, ret is [%d].", hcclRet);
     243            0 :             ret = FsmStatus::FSM_FAILED;
     244            0 :             break;
     245              :         }
     246           13 :         reqCount++;
     247              : 
     248           13 :         if (compCount == 0) {
     249            0 :             DGW_LOG_INFO("Not exist test completed request.");
     250            0 :             break;
     251              :         }
     252           13 :         totalCompCount += static_cast<uint32_t>(compCount);
     253              :         // check result
     254           13 :         (void)ProcTestSomeResults(compCount, channels, hcclRet);
     255              :     }
     256           11 :     if ((!isSrc) && (totalCompCount != 0U)) {
     257            3 :         (void)EntityManager::Instance(resIndex).SupplyEvent(static_cast<uint32_t>(EVENT_QUEUE_FULL_TO_NOT_FULL));
     258            3 :         DGW_LOG_INFO("Success to trigger tag f2nf event.");
     259              :     }
     260           11 :     DGW_LOG_INFO("Test some comm channels success count is %u.", reqCount);
     261           11 :     return ret;
     262              : }
     263              : 
     264           13 : FsmStatus HcclProcess::ProcTestSomeResults(const int32_t compCount, CommChannels &channels, int32_t hcclRet) const
     265              : {
     266           26 :     for (size_t i = 0UL; i < static_cast<size_t>(compCount); i++) {
     267           13 :         const size_t reqIdx = static_cast<size_t>(channels.compIndices[i]);
     268           13 :         HcclStatus &status = channels.compStatus[i];
     269           13 :         ChannelEntityPtr &entity = channels.entities[reqIdx];
     270              :         // check status
     271           13 :         if (status.error != 0) {
     272            1 :             DGW_LOG_ERROR("Comm channel[%s] test some failed, status:[rank:%d, tag:%d, error:%d], hcclRet[%d].",
     273              :                 entity->ToString().c_str(), status.srcRank, status.tag, status.error, hcclRet);
     274            1 :             if (((status.error == static_cast<int32_t>(HCCL_E_TCP_TRANSFER)) ||
     275            1 :                  (status.error == static_cast<int32_t>(HCCL_E_ROCE_TRANSFER))) && (hcclRet == HCCL_E_IN_STATUS)) {
     276            1 :                 entity->linkStatus_ = ChannelLinkStatus::ABNORMAL;
     277            1 :                 DGW_LOG_RUN_INFO("set entity link status is abnormal.");
     278              :             }
     279            1 :             continue;
     280              :         }
     281              :         // process completed request
     282           12 :         (void)entity->ProcessCompReq();
     283              :     }
     284           13 :     return FsmStatus::FSM_SUCCESS;
     285              : }
     286              : 
     287            5 : FsmStatus HcclProcess::ProbeCommChannel(const ChannelEntityPtr &entity, uint32_t &probeCount) const
     288              : {
     289            5 :     if (entity == nullptr) {
     290            0 :         probeCount = 0U;
     291            0 :         return FsmStatus::FSM_FAILED;
     292              :     }
     293            5 :     HcclMessage msg = nullptr;
     294            5 :     uint64_t dataCount = 0UL;
     295              : 
     296            5 :     uint32_t reqTotalCount = 0U;
     297            5 :     uint32_t envelopeCacheCount = 0U;
     298            5 :     uint64_t probeTick = 0UL;
     299           17 :     while (reqTotalCount < GET_DATA_THRESHOLD) {
     300           17 :         auto ret = entity->Probe(dataCount, msg, probeTick);
     301              :         // uncompReqQueue_ full, cache envelope, then continue probe
     302           17 :         if (ret == FsmStatus::FSM_CACHED) {
     303            4 :             envelopeCacheCount++;
     304            4 :             reqTotalCount++;
     305            4 :             continue;
     306              :         }
     307              :         // probe failed, perhaps current channel have no envelope, quit the loop
     308           13 :         if (ret != FsmStatus::FSM_SUCCESS) {
     309            5 :             break;
     310              :         }
     311              :         // probe success, alloc mbuf and call HcclImrecv to get request
     312            8 :         reqTotalCount++;
     313            8 :         ret = entity->ReceiveData(msg, dataCount, probeTick);
     314            8 :         if (ret != FsmStatus::FSM_SUCCESS) {
     315            0 :             break;
     316              :         }
     317              :     }
     318            5 :     probeCount = reqTotalCount;
     319            5 :     DGW_LOG_INFO("Probe comm channel success, total count is [%u], envelope cached count is [%u], entity:[%s].",
     320              :         reqTotalCount, envelopeCacheCount, entity->ToString().c_str());
     321            5 :     return FsmStatus::FSM_SUCCESS;
     322              : }
     323              : 
     324            0 : FsmStatus HcclProcess::SupplyEvents(const uint32_t resIndex) const
     325              : {
     326              :     // supply F2NF event
     327            0 :     (void)EntityManager::Instance(resIndex).SupplyEvent(static_cast<uint32_t>(EVENT_QUEUE_FULL_TO_NOT_FULL));
     328              : 
     329            0 :     if (!bqs::RouterServer::GetInstance().GetCallHcclFlag()) {
     330            0 :         return FsmStatus::FSM_SUCCESS;
     331              :     }
     332              :     // supply hccl event
     333            0 :     if (oneTrackEventEnabled_) {
     334            0 :         (void)EntityManager::Instance(resIndex).SupplyEvent(EVENT_RECV_COMPLETION_MSG);
     335              :     } else {
     336            0 :         for (const auto eventId : g_supplyEvents) {
     337            0 :             (void)EntityManager::Instance(resIndex).SupplyEvent(eventId);
     338              :         };
     339              :     }
     340            0 :     DGW_LOG_INFO("Supply event success.");
     341            0 :     return FsmStatus::FSM_SUCCESS;
     342              : }
     343              : 
     344           10 : FsmStatus HcclProcess::ReplyHcclEvent(const event_info &event, const uint32_t deviceId) const
     345              : {
     346           10 :     const uint32_t eventId = static_cast<uint32_t>(event.comm.event_id);
     347              :     // ack event
     348           20 :     const auto drvRet = halEschedAckEvent(deviceId,
     349           10 :         static_cast<EVENT_ID>(eventId), event.comm.subevent_id, nullptr, 0U);
     350           10 :     if (drvRet != DRV_ERROR_NONE) {
     351            0 :         DGW_LOG_ERROR("Failed to reply event[%u], deviceId[%u], ret is %d.", eventId, deviceId, drvRet);
     352            0 :         return FsmStatus::FSM_FAILED;
     353              :     }
     354           10 :     DGW_LOG_INFO("reply event[%u], deviceId[%u] success.", eventId, deviceId);
     355              : 
     356              :     // statistic callback count
     357           10 :     switch (eventId) {
     358            2 :         case dgw::EVENT_RECV_REQUEST_MSG: {
     359            2 :             bqs::StatisticManager::GetInstance().HcclMpiRecvReqCallbackStat();
     360            2 :             break;
     361              :         }
     362            3 :         case dgw::EVENT_SEND_COMPLETION_MSG: {
     363            3 :             bqs::StatisticManager::GetInstance().HcclMpiSendCompCallbackStat();
     364            3 :             break;
     365              :         }
     366            5 :         case dgw::EVENT_RECV_COMPLETION_MSG: {
     367            5 :             bqs::StatisticManager::GetInstance().HcclMpiRecvCompCallbackStat();
     368            5 :             break;
     369              :         }
     370            0 :         default: {
     371            0 :             DGW_LOG_ERROR("Unsupported event[%u].", eventId);
     372            0 :             break;
     373              :         }
     374              :     }
     375           10 :     return FsmStatus::FSM_SUCCESS;
     376              : }
     377              : 
     378            7 : FsmStatus HcclProcess::PreProcessSetUplinkReq(const RequestInfo * const hcclReq) const
     379              : {
     380            7 :     const uint64_t curTick = bqs::ProfileManager::GetInstance().GetCpuTick();
     381            7 :     if (curTick >= hcclReq->startTick) {
     382            6 :         const auto timeCost = bqs::ProfileManager::GetInstance().GetTimeCost(curTick - hcclReq->startTick);
     383            6 :         if (timeCost >= LINK_SET_UP_TIMEOUE) {
     384            1 :             DGW_LOG_ERROR("curtick:%lu, setuptick:%lu, threshold:%.2fus, linkSetUp timeout:%.2fus.", curTick,
     385              :                           hcclReq->startTick, LINK_SET_UP_TIMEOUE, timeCost);
     386            1 :             return FsmStatus::FSM_FAILED;
     387              :         }
     388            5 :         return FsmStatus::FSM_SUCCESS;
     389              :     }
     390            1 :     DGW_LOG_ERROR("cur tick:%lu is smaller than SetUpTick:%lu.", curTick, hcclReq->startTick);
     391            1 :     return FsmStatus::FSM_FAILED;
     392              : }
     393              : }  // namespace dgw
        

Generated by: LCOV version 2.0-1