LCOV - code coverage report
Current view: top level - server/dynamic_sched - dynamic_sched_mgr.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 68.5 % 222 152
Test Date: 2026-08-12 11:05:07 Functions: 77.8 % 18 14

            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 "dynamic_sched_mgr.hpp"
      12              : #include <securec.h>
      13              : #include "driver/ascend_hal.h"
      14              : #include "bqs_feature_ctrl.h"
      15              : 
      16              : namespace dgw {
      17              : namespace {
      18              : constexpr int32_t kMicrosecondToNanosecond = 1000;
      19              : constexpr int32_t kDynamicSchedDuration = 2000 * kMicrosecondToNanosecond; // 2ms
      20              : constexpr int32_t kRequestCacheNum = 3;
      21              : constexpr uint32_t KCoLocateNum = 2;
      22              : } // namespace
      23              : 
      24              : // 考虑合设flowgw场景,一个flowgw可能服务两个device,默认device0
      25           69 : DynamicSchedMgr& DynamicSchedMgr::GetInstance(uint32_t deviceId)
      26              : {
      27           69 :     uint32_t index = deviceId >= KCoLocateNum ? 0U : deviceId;
      28           71 :     static DynamicSchedMgr mgr[KCoLocateNum];
      29           69 :     return mgr[index];
      30              : }
      31              : 
      32           11 : FsmStatus DynamicSchedMgr::AddRootModelInfo(const RootModelInfo& rootModelInfo)
      33              : {
      34           11 :     const uint32_t rootModelId = rootModelInfo.rootModelId;
      35           11 :     const auto iter = rootModelInfos_.find(rootModelId);
      36           11 :     if (iter != rootModelInfos_.end()) {
      37            1 :         DGW_LOG_ERROR("Root model info has been added, rootModelId=%u.", rootModelId);
      38            1 :         return FsmStatus::FSM_FAILED;
      39              :     }
      40           10 :     (void)rootModelInfos_.emplace(rootModelId, rootModelInfo);
      41           10 :     return FsmStatus::FSM_SUCCESS;
      42              : }
      43              : 
      44            9 : void DynamicSchedMgr::DeleteQueue(const uint32_t globalLogicId, const uint32_t rootModelId)
      45              : {
      46            9 :     DynamicSchedDurationPrint();
      47            9 :     for (auto iter = rootModelInfos_.begin(); iter != rootModelInfos_.end(); iter++) {
      48            4 :         if ((iter->first == rootModelId) && (iter->second.responseQue.globalLogicId == globalLogicId)) {
      49            4 :             (void)rootModelInfos_.erase(iter);
      50            4 :             return;
      51              :         }
      52              :     }
      53              : }
      54              : 
      55            9 : void DynamicSchedMgr::UpdateNodeId(const int32_t nodeId) { nodeId_ = nodeId; }
      56              : 
      57            6 : void DynamicSchedMgr::GenerateRequest(
      58              :     const std::vector<RequestInfo>& requests, const int32_t centerResponseQueIdx,
      59              :     dynamic::FlowgwRequest& flowgwRequest) const
      60              : {
      61            6 :     flowgwRequest.set_node_id(nodeId_);
      62            6 :     flowgwRequest.set_input_index(centerResponseQueIdx);
      63           11 :     for (const auto& request : requests) {
      64           10 :         for (const auto& decision : request.decisions) {
      65           10 :             for (const auto& dst : request.dsts) {
      66            5 :                 auto queueInfo = flowgwRequest.add_queue_infos();
      67            5 :                 queueInfo->set_logic_group_id(dst.logicGroupId);
      68            5 :                 queueInfo->set_model_uuid(request.src.modelUuid);
      69            5 :                 queueInfo->set_root_model_id(request.src.rootModelId);
      70            5 :                 queueInfo->set_trans_id(decision.transId);
      71            5 :                 queueInfo->set_route_label(decision.routeLabel);
      72              :                 // Compatible for old version
      73            5 :                 queueInfo->set_trans_id_old(static_cast<int32_t>(decision.transId));
      74            5 :                 queueInfo->set_route_label_old(static_cast<int32_t>(decision.routeLabel));
      75            5 :                 auto queueAttr = queueInfo->mutable_queue_attrs();
      76            5 :                 queueAttr->set_queue_id(request.src.queueId);
      77            5 :                 queueAttr->set_device_id(request.src.deviceId);
      78            5 :                 queueAttr->set_logic_id(request.src.queueLogicId);
      79              :             }
      80              :         }
      81              :     }
      82            6 : }
      83              : 
      84            8 : FsmStatus DynamicSchedMgr::SendRequest(const uint32_t rootModelId, const std::vector<RequestInfo>& requests)
      85              : {
      86              :     // get root model info
      87            8 :     const auto iter = rootModelInfos_.find(rootModelId);
      88            8 :     if (iter == rootModelInfos_.end()) {
      89            1 :         DGW_LOG_ERROR("Root model info has not been added, rootModelId=%u.", rootModelId);
      90            1 :         return FsmStatus::FSM_FAILED;
      91              :     }
      92              :     // some requests will not be enqueue because result has been cached
      93            7 :     std::vector<RequestInfo> requestsAfterCache;
      94            7 :     SendRequestToCacheResult(requests, requestsAfterCache);
      95              : 
      96            7 :     if (requestSentNum_ > kRequestCacheNum) {
      97            4 :         for (auto& request : requestsAfterCache) {
      98            2 :             iter->second.requestCache.push_back(request);
      99              :         }
     100            2 :         return FsmStatus::FSM_SUCCESS;
     101              :     }
     102              :     // construct FlowgwRequest protobuf object
     103            5 :     auto cacheSize = iter->second.requestCache.size();
     104            5 :     dynamic::FlowgwRequest flowgwRequest;
     105            5 :     if (cacheSize == 0) {
     106            4 :         GenerateRequest(requestsAfterCache, iter->second.responseQue.globalLogicId, flowgwRequest);
     107              :     } else {
     108            1 :         GenerateRequest(iter->second.requestCache, iter->second.responseQue.globalLogicId, flowgwRequest);
     109            1 :         GenerateRequest(requestsAfterCache, iter->second.responseQue.globalLogicId, flowgwRequest);
     110              :     }
     111            5 :     if (flowgwRequest.queue_infos_size() == 0U) {
     112            0 :         return FsmStatus::FSM_SUCCESS;
     113              :     }
     114              : 
     115              :     const auto enqueueRet =
     116            5 :         EnqueueRequest(flowgwRequest, iter->second.requestQue.deviceId, iter->second.requestQue.queueId);
     117            5 :     if (enqueueRet != FsmStatus::FSM_SUCCESS) {
     118            1 :         return enqueueRet;
     119              :     }
     120            4 :     iter->second.requestCache.clear();
     121            4 :     requestSentNum_++;
     122            4 :     return FsmStatus::FSM_SUCCESS;
     123            7 : }
     124              : 
     125            5 : FsmStatus DynamicSchedMgr::EnqueueRequest(
     126              :     const dynamic::FlowgwRequest& flowgwRequest, const uint32_t deviceId, const uint32_t queueId) const
     127              : {
     128            5 :     const auto reqSize = flowgwRequest.ByteSizeLong();
     129            5 :     Mbuf* mbuf = nullptr;
     130            5 :     auto drvRet = halMbufAlloc(reqSize, &mbuf);
     131            5 :     if (drvRet != DRV_ERROR_NONE) {
     132            0 :         DGW_LOG_ERROR("halMbufAlloc failed, drvRet=%d, dataSize=%lu.", drvRet, reqSize);
     133            0 :         return FsmStatus::FSM_FAILED;
     134              :     }
     135            0 :     auto mbufDeleter = [](Mbuf* buf) { (void)halMbufFree(buf); };
     136            5 :     std::unique_ptr<Mbuf, decltype(mbufDeleter)> mbufGuard(mbuf, mbufDeleter);
     137            5 :     drvRet = halMbufSetDataLen(mbuf, reqSize);
     138            5 :     if (drvRet != DRV_ERROR_NONE) {
     139            0 :         DGW_LOG_ERROR("halMbufSetDataLen failed, drvRet=%d, dataSize=%lu.", drvRet, reqSize);
     140            0 :         return FsmStatus::FSM_FAILED;
     141              :     }
     142              :     // write data
     143            5 :     void* buffAddr = nullptr;
     144            5 :     drvRet = halMbufGetBuffAddr(mbuf, &buffAddr);
     145            5 :     if (drvRet != DRV_ERROR_NONE || buffAddr == nullptr) {
     146            1 :         DGW_LOG_ERROR("Failed to get buff addr, ret[%d].", drvRet);
     147            1 :         return FsmStatus::FSM_FAILED;
     148              :     }
     149            4 :     flowgwRequest.SerializeToArray(buffAddr, static_cast<int32_t>(reqSize));
     150              :     // enqueue
     151            4 :     drvRet = halQueueEnQueue(deviceId, queueId, mbuf);
     152            4 :     if (drvRet == DRV_ERROR_QUEUE_FULL) {
     153            0 :         return FsmStatus::FSM_DEST_FULL;
     154            4 :     } else if (drvRet != DRV_ERROR_NONE) {
     155            0 :         DGW_LOG_ERROR("Failed to enqueue mbuf, ret[%d].", drvRet);
     156            0 :         return FsmStatus::FSM_FAILED;
     157              :     }
     158            4 :     PrintRequestLog(flowgwRequest);
     159            4 :     mbufGuard.release();
     160            4 :     return FsmStatus::FSM_SUCCESS;
     161            5 : }
     162              : 
     163            4 : void DynamicSchedMgr::PrintRequestLog(const dynamic::FlowgwRequest& flowgwRequest) const
     164              : {
     165            4 :     if (!bqs::HostQsLog::GetInstance().CheckLogLevel(static_cast<int32_t>(AICPU), DLOG_INFO)) {
     166            0 :         return;
     167              :     }
     168            4 :     const int32_t queue_infos_size = flowgwRequest.queue_infos_size();
     169            8 :     for (int32_t queue_infos_index = 0; queue_infos_index < queue_infos_size; queue_infos_index++) {
     170            4 :         const auto& queue_info = flowgwRequest.queue_infos(queue_infos_index);
     171            4 :         DGW_LOG_INFO(
     172              :             "Dynamic sched send request, node_id=%d, input_index=%d, queue_id=%u, device_type=%d, "
     173              :             "device_id=%d, logic_id=%u, logic_group_id=%u, model_uuid=%u, trans_id=%lu, route_label=%u, "
     174              :             "root_model_id=%u, queue_infos_index=%d.",
     175              :             flowgwRequest.node_id(), flowgwRequest.input_index(), queue_info.queue_attrs().queue_id(),
     176              :             queue_info.queue_attrs().device_type(), queue_info.queue_attrs().device_id(),
     177              :             queue_info.queue_attrs().logic_id(), queue_info.logic_group_id(), queue_info.model_uuid(),
     178              :             queue_info.trans_id(), queue_info.route_label(), queue_info.root_model_id(), queue_infos_index);
     179              :     }
     180              : }
     181              : 
     182            0 : void DynamicSchedMgr::PrintResponseLog(const dynamic::FlowgwResponse& flowgwResponse) const
     183              : {
     184            0 :     if (!bqs::HostQsLog::GetInstance().CheckLogLevel(static_cast<int32_t>(AICPU), DLOG_INFO)) {
     185            0 :         return;
     186              :     }
     187            0 :     const int32_t queue_infos_size = flowgwResponse.queue_infos_size();
     188            0 :     for (int32_t queue_infos_index = 0; queue_infos_index < queue_infos_size; queue_infos_index++) {
     189            0 :         const auto& queue_info = flowgwResponse.queue_infos(queue_infos_index);
     190            0 :         DGW_LOG_INFO(
     191              :             "Dynamic sched get response, queue_id=%u, device_type=%d, "
     192              :             "device_id=%d, logic_id=%u, logic_group_id=%u, model_uuid=%u, trans_id=%lu, route_label=%u, "
     193              :             "choose_logic_id=%u, root_model_id=%u, queue_infos_index=%d, need_cache=%d.",
     194              :             queue_info.queue_attrs().queue_id(), queue_info.queue_attrs().device_type(),
     195              :             queue_info.queue_attrs().device_id(), queue_info.queue_attrs().logic_id(), queue_info.logic_group_id(),
     196              :             queue_info.model_uuid(), queue_info.trans_id(), queue_info.route_label(), queue_info.choose_logic_id(),
     197              :             queue_info.root_model_id(), queue_infos_index, static_cast<int32_t>(queue_info.need_cache()));
     198              :     }
     199              : }
     200              : 
     201            5 : FsmStatus DynamicSchedMgr::GetResponse(const uint32_t rootModelId, std::vector<ResponseInfo>& responses)
     202              : {
     203              :     // get root model info
     204            5 :     const auto iter = rootModelInfos_.find(rootModelId);
     205            5 :     if (iter == rootModelInfos_.end()) {
     206            1 :         return FsmStatus::FSM_SUCCESS;
     207              :     }
     208            4 :     GetResponseFromCacheResult(responses);
     209              : 
     210            4 :     auto cacheSize = iter->second.requestCache.size();
     211            4 :     if (requestSentNum_ == 0) {
     212            2 :         if (cacheSize != 0) {
     213            1 :             SendRequest(rootModelId, {});
     214              :         }
     215            2 :         return FsmStatus::FSM_SUCCESS;
     216              :     }
     217              :     // dequeue
     218            2 :     void* mbuf = nullptr;
     219            2 :     const auto ret = halQueueDeQueue(iter->second.responseQue.deviceId, iter->second.responseQue.queueId, &mbuf);
     220            2 :     if (ret == DRV_ERROR_NONE) {
     221            1 :         requestSentNum_--;
     222              :         // parse mbuf to FlowgwResponse
     223            0 :         auto mbufDeleter = [](Mbuf* buf) { (void)halMbufFree(buf); };
     224            1 :         std::unique_ptr<Mbuf, decltype(mbufDeleter)> mbufGuard(PtrToPtr<void, Mbuf>(mbuf), mbufDeleter);
     225            1 :         dynamic::FlowgwResponse flowgwResponse;
     226            1 :         void* buffer_addr = nullptr;
     227            1 :         uint64_t buffer_size = 0U;
     228            1 :         if (halMbufGetBuffAddr(PtrToPtr<void, Mbuf>(mbuf), &buffer_addr) != DRV_ERROR_NONE) {
     229            1 :             DGW_LOG_ERROR("halMbufGetBuffAddr failed");
     230            1 :             return FsmStatus::FSM_FAILED;
     231              :         };
     232            0 :         if (halMbufGetBuffSize(PtrToPtr<void, Mbuf>(mbuf), &buffer_size) != DRV_ERROR_NONE) {
     233            0 :             DGW_LOG_ERROR("halMbufGetBuffAddr failed");
     234            0 :             return FsmStatus::FSM_FAILED;
     235              :         };
     236            0 :         google::protobuf::io::ArrayInputStream stream(buffer_addr, static_cast<int32_t>(buffer_size));
     237            0 :         if (!flowgwResponse.ParseFromZeroCopyStream(&stream)) {
     238            0 :             DGW_LOG_ERROR("Response ParseFromZeroCopyStream failed");
     239            0 :             return FsmStatus::FSM_FAILED;
     240              :         }
     241            0 :         PrintResponseLog(flowgwResponse);
     242              :         // write response data
     243            0 :         for (const auto& queueInfo : flowgwResponse.queue_infos()) {
     244            0 :             ResponseInfo responseInfo;
     245            0 :             responseInfo.src.queueId = queueInfo.queue_attrs().queue_id();
     246            0 :             responseInfo.src.queueLogicId = queueInfo.queue_attrs().logic_id();
     247            0 :             responseInfo.src.modelUuid = queueInfo.model_uuid();
     248            0 :             responseInfo.src.rootModelId = queueInfo.root_model_id();
     249              :             GroupResult groupResult;
     250            0 :             groupResult.logicGroupId = queueInfo.logic_group_id();
     251            0 :             groupResult.index = queueInfo.choose_logic_id();
     252            0 :             responseInfo.groupResults.emplace_back(std::move(groupResult));
     253            0 :             if (queueInfo.need_cache()) {
     254            0 :                 UpdateCacheResult(responseInfo);
     255            0 :                 continue;
     256              :             }
     257            0 :             responses.emplace_back(std::move(responseInfo));
     258            0 :         }
     259              : 
     260            0 :         if (requestSentNum_ == 0) {
     261            0 :             if (cacheSize != 0) {
     262            0 :                 SendRequest(rootModelId, {});
     263              :             }
     264              :         }
     265            3 :     } else if (ret != DRV_ERROR_QUEUE_EMPTY) {
     266            1 :         DGW_LOG_ERROR(
     267              :             "failed to dequeue, device_id = %u, queue_id = %u, ret = %d", iter->second.responseQue.deviceId,
     268              :             iter->second.responseQue.queueId, ret);
     269            1 :         return FsmStatus::FSM_FAILED;
     270              :     }
     271            0 :     GetResponseFromCacheResult(responses);
     272            0 :     return FsmStatus::FSM_SUCCESS;
     273              : }
     274              : 
     275            1 : FsmStatus DynamicSchedMgr::ClearCacheRouteResult()
     276              : {
     277            1 :     validCacheInfos_.clear();
     278            1 :     invalidCacheInfos_.clear();
     279            1 :     return FsmStatus::FSM_SUCCESS;
     280              : }
     281              : 
     282            7 : void DynamicSchedMgr::SendRequestToCacheResult(
     283              :     const std::vector<RequestInfo>& requests, std::vector<RequestInfo>& requestsAfterCache)
     284              : {
     285           13 :     for (const auto& request : requests) {
     286            6 :         RequestInfo requestAfterCache;
     287            6 :         requestAfterCache.src = request.src;
     288            6 :         requestAfterCache.decisions = request.decisions;
     289           12 :         for (const auto& dst : request.dsts) {
     290            6 :             CacheRouteKey key = {request.src, dst};
     291            6 :             const auto iterValidCache = validCacheInfos_.find(key);
     292            6 :             if (iterValidCache != validCacheInfos_.end()) {
     293            0 :                 iterValidCache->second.num++;
     294            0 :                 continue;
     295              :             }
     296            6 :             invalidCacheInfos_[key]++;
     297            6 :             requestAfterCache.dsts.emplace_back(dst);
     298              :         }
     299            6 :         if (requestAfterCache.dsts.empty()) {
     300            0 :             continue;
     301              :         }
     302            6 :         requestsAfterCache.emplace_back(std::move(requestAfterCache));
     303            6 :     }
     304            7 : }
     305              : 
     306            0 : void DynamicSchedMgr::UpdateCacheResult(const ResponseInfo& getResponseInfo)
     307              : {
     308            0 :     for (const auto& result : getResponseInfo.groupResults) {
     309            0 :         DstGroupInfo dstGroupInfo = {result.logicGroupId};
     310            0 :         CacheRouteKey key = {getResponseInfo.src, dstGroupInfo};
     311            0 :         const auto iterValidCache = validCacheInfos_.find(key);
     312            0 :         if (iterValidCache != validCacheInfos_.end()) {
     313            0 :             continue;
     314              :         }
     315            0 :         const auto iterInvalidCache = invalidCacheInfos_.find(key);
     316            0 :         if (iterInvalidCache != invalidCacheInfos_.end()) {
     317            0 :             CacheRouteValue cacheRouteValue = {result, iterInvalidCache->second};
     318            0 :             validCacheInfos_.emplace(key, std::move(cacheRouteValue));
     319            0 :             invalidCacheInfos_.erase(iterInvalidCache);
     320              :         }
     321              :     }
     322            0 : }
     323              : 
     324            4 : void DynamicSchedMgr::GetResponseFromCacheResult(std::vector<ResponseInfo>& responses)
     325              : {
     326            4 :     for (auto& cacheInfo : validCacheInfos_) {
     327            0 :         for (uint32_t index = 0U; index < cacheInfo.second.num; index++) {
     328            0 :             std::vector<GroupResult> groupResults;
     329            0 :             groupResults.emplace_back(cacheInfo.second.result);
     330            0 :             ResponseInfo response = {cacheInfo.first.srcQueueInfo, groupResults};
     331            0 :             responses.emplace_back(std::move(response));
     332            0 :             DGW_LOG_INFO(
     333              :                 "get response from cache result, root_model_id=%u, src queue_id=%u, "
     334              :                 "logic_id=%u, logic_group_id=%u, result_index=%u.",
     335              :                 cacheInfo.first.srcQueueInfo.rootModelId, cacheInfo.first.srcQueueInfo.queueId,
     336              :                 cacheInfo.first.srcQueueInfo.queueLogicId, cacheInfo.second.result.logicGroupId,
     337              :                 cacheInfo.second.result.index);
     338            0 :         }
     339            0 :         cacheInfo.second.num = 0U;
     340              :     }
     341            4 : }
     342              : 
     343            4 : void DynamicSchedMgr::DynamicSchedDurationEnd(uint64_t begin)
     344              : {
     345            4 :     uint64_t duration = DynamicSchedNow() - begin;
     346            4 :     durationTotal_ += duration;
     347            4 :     if (duration > kDynamicSchedDuration) {
     348            0 :         durationSize_++;
     349              :     }
     350            4 :     if (duration > durationMax_) {
     351            4 :         durationMax_ = duration;
     352              :     }
     353            4 :     cntTotal_++;
     354            4 : }
     355              : 
     356            9 : void DynamicSchedMgr::DynamicSchedDurationPrint()
     357              : {
     358            9 :     BQS_LOG_RUN_INFO(
     359              :         "DynamicSched, flowgw data: Total(us)=%lu, Cnt=%lu, Per duration(ns)=%lu, Max duration(ns)=%lu,"
     360              :         " Greater 2ms cnt=%lu",
     361              :         durationTotal_ / kMicrosecondToNanosecond, cntTotal_, (durationTotal_ / (cntTotal_ != 0ULL ? cntTotal_ : 1UL)),
     362              :         durationMax_, durationSize_);
     363            9 :     durationTotal_ = 0ULL;
     364            9 :     cntTotal_ = 0ULL;
     365            9 :     durationMax_ = 0ULL;
     366            9 :     durationSize_ = 0ULL;
     367            9 :     call_ = 0ULL;
     368            9 : }
     369              : } // namespace dgw
        

Generated by: LCOV version 2.0-1