LCOV - code coverage report
Current view: top level - legacy/ascend910/framework/common/src/order_launch - order_launch.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 55.9 % 179 100
Test Date: 2026-08-29 17:38:31 Functions: 66.7 % 15 10

            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 "order_launch.h"
      12              : #include "log.h"
      13              : #include "acl/acl_rt.h"
      14              : #include "config_log.h"
      15              : #include "hccl_types.h"
      16              : #include "adapter_rts_common.h"
      17              : #include "stream_utils.h"
      18              : 
      19              : namespace hccl {
      20         1336 : OrderLaunch& OrderLaunch::GetInstance(s32 deviceLogicID)
      21              : {
      22         2116 :     static OrderLaunch orderLaunch[MAX_MODULE_DEVICE_NUM];
      23         1335 :     if (static_cast<u32>(deviceLogicID) >= MAX_MODULE_DEVICE_NUM) {
      24          275 :         HCCL_WARNING("[OrderLaunch][GetInstance]Invalid deviceLogicID[%d]", deviceLogicID);
      25          275 :         return orderLaunch[0];
      26              :     }
      27         1060 :     HCCL_DEBUG("[OrderLaunch][GetInstance]Valid deviceLogicID[%d]", deviceLogicID);
      28         1061 :     return orderLaunch[deviceLogicID];
      29              : }
      30              : 
      31          780 : OrderLaunch::OrderLaunch() : initialized_(true) {}
      32              : 
      33          780 : OrderLaunch::~OrderLaunch()
      34              : {
      35          780 :     std::unique_lock<std::mutex> mapLock(streamMutex_);
      36          780 :     initialized_ = false;
      37          780 :     groupCtxMap_.clear();
      38          780 :     DestroyRes();
      39          780 : }
      40              : 
      41          780 : void OrderLaunch::DestroyRes()
      42              : {
      43          780 :     for (auto& entry : contextResMgrMap_) {
      44            0 :         entry.second.DestroyResources();
      45              :     }
      46          780 :     contextResMgrMap_.clear();
      47          780 :     hcomStreamMap_.clear();
      48          780 : }
      49              : 
      50          523 : HcclResult OrderLaunch::RegisterOrderLaunch(const std::string& group)
      51              : {
      52          523 :     std::unique_lock<std::mutex> mapLock(streamMutex_);
      53          523 :     if (groupCtxMap_.find(group) != groupCtxMap_.end()) {
      54            1 :         HCCL_WARNING("%s skip, group[%s] has already been registered", __func__, group.c_str());
      55            1 :         return HCCL_SUCCESS;
      56              :     }
      57              :     // 只记录group,context暂不赋值,只在算子下发阶段对context赋值
      58          522 :     groupCtxMap_.insert({group, INVALID_U64});
      59          522 :     HCCL_INFO("%s success, group[%s]", __func__, group.c_str());
      60          522 :     return HCCL_SUCCESS;
      61          523 : }
      62              : 
      63              : /**
      64              :  * @brief 从order launch系统注销group
      65              :  * 注销group时,会清理group与context的映射关系。
      66              :  * 只有当context下没有其他group时,才会清理context对应的资源。
      67              :  */
      68          811 : HcclResult OrderLaunch::UnRegisterOrderLaunch(const std::string& group)
      69              : {
      70          811 :     CHK_PRT_RET(initialized_ == false, HCCL_WARNING("OrderLaunch has been destroyed"), HCCL_SUCCESS);
      71          811 :     std::unique_lock<std::mutex> mapLock(streamMutex_);
      72          811 :     auto it = groupCtxMap_.find(group);
      73          810 :     if (it == groupCtxMap_.end()) {
      74          288 :         HCCL_WARNING("%s skip, group[%s] has not been registered", __func__, group.c_str());
      75          288 :         return HCCL_SUCCESS;
      76              :     }
      77              : 
      78          520 :     u64 context = it->second;
      79          521 :     HCCL_INFO(
      80              :         "[OrderLaunch][UnRegisterOrderLaunch] group[%s] context[0x%llx], contextGroupsMap_.size[%zu]", group.c_str(),
      81              :         context, contextGroupsMap_.size());
      82          523 :     if (contextGroupsMap_.find(context) != contextGroupsMap_.end()) {
      83            1 :         contextGroupsMap_[context].erase(group);
      84            1 :         if (contextGroupsMap_[context].empty()) {
      85            1 :             contextGroupsMap_.erase(context);
      86            1 :             if (contextResMgrMap_.find(context) != contextResMgrMap_.end()) {
      87            1 :                 contextResMgrMap_[context].DestroyResources();
      88            1 :                 contextResMgrMap_.erase(context);
      89              :             }
      90            1 :             HCCL_INFO("%s contextGroupsMap_ erase context[0x%llx]", __func__, context);
      91              :         }
      92              :     }
      93              : 
      94          523 :     groupCtxMap_.erase(it);
      95          523 :     HCCL_INFO("%s success, group[%s]", __func__, group.c_str());
      96          523 :     return HCCL_SUCCESS;
      97          811 : }
      98              : 
      99              : /**
     100              :  * @brief 设置图模式使用的HCOM stream
     101              :  * 图模式下,通信使用的附属从流预先设置到hcomStreamMap_中
     102              :  */
     103            0 : HcclResult OrderLaunch::SetHcomStream(u32 graphId, const Stream& hcomAttachedStream)
     104              : {
     105            0 :     std::unique_lock<std::mutex> mapLock(streamMutex_);
     106            0 :     hcomStreamMap_[graphId] = hcomAttachedStream;
     107            0 :     HCCL_INFO("%s success, graphId[%u], hcomStreamId[%u]", __func__, graphId, hcomAttachedStream.id());
     108            0 :     return HCCL_SUCCESS;
     109            0 : }
     110              : 
     111              : /**
     112              :  * @brief 初始化group的context映射关系
     113              :  *
     114              :  * 获取当前线程的context,建立以下映射关系:
     115              :  *   - groupCtxMap_[group] = currentContext
     116              :  *   - contextGroupsMap_[currentContext] 包含 group
     117              :  *   - contextResMgrMap_[currentContext] 包含该context的资源管理器
     118              :  */
     119            1 : HcclResult OrderLaunch::InitGroupCtx(const std::string& group)
     120              : {
     121            1 :     u64 currentContext = INVALID_U64;
     122            1 :     HcclResult ret = GetCurrentContext(currentContext);
     123            1 :     CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[%s]GetCurrentContext failed, ret[%d]", __func__, ret), ret);
     124              : 
     125            1 :     if (contextResMgrMap_.find(currentContext) == contextResMgrMap_.end()) {
     126            1 :         contextResMgrMap_[currentContext] = OrderLaunchResMgr();
     127            1 :         HCCL_INFO("[OrderLaunch][InitGroupCtx] created new OrderLaunchResMgr for context[0x%llx]", currentContext);
     128              :     }
     129              : 
     130            1 :     auto& resMgr = contextResMgrMap_[currentContext];
     131            1 :     if (!resMgr.contextInitialized) {
     132            1 :         resMgr.MarkContextInitialized(currentContext);
     133              :     }
     134              : 
     135            1 :     groupCtxMap_[group] = currentContext;
     136            1 :     contextGroupsMap_[currentContext].insert(group);
     137              : 
     138            1 :     HCCL_RUN_INFO("[%s]group[%s] init or update context[0x%llx]", __func__, group.c_str(), currentContext);
     139            1 :     return HCCL_SUCCESS;
     140              : }
     141              : 
     142              : // aclgraph模式下,先在kernel stream上写record,再在上order stream写wait;解order stream的wait
     143            1 : HcclResult OrderLaunch::AclgraphLaunchInOrderToOrderStream(
     144              :     std::string& group, const Stream& kernelStream, const Stream& mainStream, std::shared_ptr<LocalNotify> notify0,
     145              :     std::shared_ptr<LocalNotify> notify1, u32 timeOut, HcclRtEvent event)
     146              : {
     147            1 :     std::unique_lock<std::mutex> mapLock(streamMutex_);
     148              :     // group未注册过,或者未记录过算子下发阶段的线程context
     149            1 :     if (groupCtxMap_.find(group) == groupCtxMap_.end() || groupCtxMap_[group] == INVALID_U64) {
     150            1 :         CHK_RET(InitGroupCtx(group));
     151              :     }
     152              : 
     153            1 :     u64 context = groupCtxMap_[group];
     154            1 :     Stream& aclgraphStream = contextResMgrMap_[context].aclgraphStream;
     155            1 :     EnsureOrderStreamForGroup(group, context, aclgraphStream); // aclgraph控制流
     156              : 
     157            1 :     rtModel_t rtModel = nullptr;
     158            1 :     bool isCapture = false;
     159            1 :     CHK_RET(GetStreamCaptureInfo(mainStream.ptr(), rtModel, isCapture));
     160            1 :     CHK_RET(AddStreamToModel(aclgraphStream.ptr(), rtModel));
     161              : 
     162            1 :     aclError ret = ACL_SUCCESS;
     163              :     // kernelStream -> aclgraphStream
     164            1 :     ret = aclrtRecordEvent(event, kernelStream.ptr());
     165            1 :     CHK_PRT_RET(ret != ACL_SUCCESS, HCCL_ERROR("[%s]aclrtRecordEvent failed, ret[%d]", __func__, ret), HCCL_E_RUNTIME);
     166            0 :     HCCL_CONFIG_INFO(HCCL_TASK, "[%s]aclrtRecordEvent para: kernelStreamId[%d]", __func__, kernelStream.id());
     167              : 
     168            0 :     ret = aclrtStreamWaitEvent(aclgraphStream.ptr(), event);
     169            0 :     CHK_PRT_RET(
     170              :         ret != ACL_SUCCESS, HCCL_ERROR("[%s]aclrtStreamWaitEvent failed, ret[%d]", __func__, ret), HCCL_E_RUNTIME);
     171            0 :     HCCL_CONFIG_INFO(HCCL_TASK, "[%s]aclrtStreamWaitEvent para: orderStreamId[%d]", __func__, aclgraphStream.id());
     172              : 
     173            0 :     HCCL_INFO(
     174              :         "[%s] group[%s], kernelStreamId[%u], orderStreamId[%u], context[0x%llx]", __func__, group.c_str(),
     175              :         kernelStream.id(), aclgraphStream.id(), context);
     176            0 :     CHK_RET(LaunchInOrder(group, kernelStream, aclgraphStream, notify0, notify1, timeOut));
     177            0 :     return HCCL_SUCCESS;
     178            1 : }
     179              : 
     180              : /**
     181              :  * @brief ACLGRAPH模式第二步:在order stream上record事件并解kernel stream的wait
     182              :  * 执行流程:
     183              :  * 1. 在order stream上record事件
     184              :  * 2. 在kernel stream上wait该事件,解开kernel stream的阻塞
     185              :  */
     186              : HcclResult
     187            0 : OrderLaunch::AclgraphLaunchInOrderToKernelStream(std::string& group, const Stream& kernelStream, HcclRtEvent event)
     188              : {
     189            0 :     std::unique_lock<std::mutex> mapLock(streamMutex_);
     190              : 
     191            0 :     auto ctxIt = groupCtxMap_.find(group);
     192            0 :     CHK_PRT_RET(
     193              :         ctxIt == groupCtxMap_.end(), HCCL_ERROR("[%s]fail, group[%s] is not in groupCtxMap_", __func__, group.c_str()),
     194              :         HCCL_E_NOT_FOUND);
     195              : 
     196            0 :     u64 context = ctxIt->second;
     197            0 :     if (contextResMgrMap_.find(context) == contextResMgrMap_.end()) {
     198            0 :         HCCL_ERROR("[%s]fail, context[0x%llx] is not in contextResMgrMap_", __func__, context);
     199            0 :         return HCCL_E_NOT_FOUND;
     200              :     }
     201              : 
     202            0 :     Stream& aclgraphStream = contextResMgrMap_[context].aclgraphStream;
     203              : 
     204            0 :     aclError ret = ACL_SUCCESS;
     205            0 :     ret = aclrtRecordEvent(event, aclgraphStream.ptr());
     206            0 :     CHK_PRT_RET(ret != ACL_SUCCESS, HCCL_ERROR("[%s]aclrtRecordEvent failed, ret[%d]", __func__, ret), HCCL_E_RUNTIME);
     207            0 :     HCCL_CONFIG_INFO(HCCL_TASK, "[%s]aclrtRecordEvent para: orderStreamId[%d]", __func__, aclgraphStream.id());
     208              : 
     209            0 :     ret = aclrtStreamWaitEvent(kernelStream.ptr(), event);
     210            0 :     CHK_PRT_RET(
     211              :         ret != ACL_SUCCESS, HCCL_ERROR("[%s]aclrtStreamWaitEvent failed, ret[%d]", __func__, ret), HCCL_E_RUNTIME);
     212            0 :     HCCL_CONFIG_INFO(HCCL_TASK, "[%s]aclrtStreamWaitEvent para: kernelStreamId[%d]", __func__, kernelStream.id());
     213              : 
     214            0 :     HCCL_INFO(
     215              :         "[%s] group[%s], kernelStreamId[%u], orderStreamId[%u], context[0x%llx]", __func__, group.c_str(),
     216              :         kernelStream.id(), aclgraphStream.id(), ctxIt->second);
     217            0 :     return HCCL_SUCCESS;
     218            0 : }
     219              : 
     220            0 : HcclResult OrderLaunch::OpbaseLaunchInOrder(
     221              :     std::string& group, const Stream& kernelStream, std::shared_ptr<LocalNotify> notify0,
     222              :     std::shared_ptr<LocalNotify> notify1, u32 timeOut)
     223              : {
     224            0 :     std::unique_lock<std::mutex> mapLock(streamMutex_);
     225            0 :     HCCL_INFO(
     226              :         "[OrderLaunch][OpbaseLaunchInOrder] group[%s], kernelStreamId[%u], timeOut[%d ms]", group.c_str(),
     227              :         kernelStream.id(), timeOut);
     228              :     // group未注册过,或者未记录过算子下发阶段的线程context
     229            0 :     if (groupCtxMap_.find(group) == groupCtxMap_.end() || groupCtxMap_[group] == INVALID_U64) {
     230            0 :         CHK_RET(InitGroupCtx(group));
     231              :     }
     232              : 
     233            0 :     u64 context = groupCtxMap_[group];
     234            0 :     Stream& opbaseStream = contextResMgrMap_[context].opbaseStream;
     235            0 :     EnsureOrderStreamForGroup(group, context, opbaseStream); // 单算子控制流
     236              : 
     237            0 :     HCCL_INFO(
     238              :         "[%s] group[%s], kernelStreamId[%u], orderStreamId[%u], context[0x%llx]", __func__, group.c_str(),
     239              :         kernelStream.id(), opbaseStream.id(), context);
     240            0 :     CHK_RET(LaunchInOrder(group, kernelStream, opbaseStream, notify0, notify1, timeOut));
     241            0 :     return HCCL_SUCCESS;
     242            0 : }
     243              : 
     244              : /**
     245              :  * @brief 图模式下的按序下发
     246              :  *
     247              :  * 图模式下,使用预先设置的hcomAttachedStream作为order stream
     248              :  */
     249            0 : HcclResult OrderLaunch::HcomLaunchInOrder(
     250              :     std::string& group, const Stream& kernelStream, u32 graphId, std::shared_ptr<LocalNotify> notify0,
     251              :     std::shared_ptr<LocalNotify> notify1, u32 timeOut)
     252              : {
     253            0 :     std::unique_lock<std::mutex> mapLock(streamMutex_);
     254            0 :     Stream hostOrderStream;
     255            0 :     if (hcomStreamMap_.find(graphId) == hcomStreamMap_.end()) {
     256            0 :         HCCL_ERROR("[%s] graphId[%u] group[%s] stream not found", __func__, graphId, group.c_str());
     257            0 :         return HCCL_E_NOT_FOUND;
     258              :     }
     259            0 :     hostOrderStream = hcomStreamMap_[graphId];
     260            0 :     CHK_PTR_NULL(hostOrderStream.ptr());
     261            0 :     HCCL_INFO("[%s] group[%s], graphId[%u], streamId[%u]", __func__, group.c_str(), graphId, hostOrderStream.id());
     262            0 :     CHK_RET(LaunchInOrder(group, kernelStream, hostOrderStream, notify0, notify1, timeOut));
     263            0 :     return HCCL_SUCCESS;
     264            0 : }
     265              : 
     266              : /**
     267              :  * @brief 使用notify机制实现stream间的按序下发
     268              :  * 1. wait notify0 on kernelStream - 等待kernel stream上的算子完成
     269              :  * 2. record notify0 on hostOrderStream - 在order stream上record notify
     270              :  * 3. wait notify1 on hostOrderStream - 等待其他算子在order stream上完成
     271              :  */
     272            0 : HcclResult OrderLaunch::LaunchInOrder(
     273              :     [[maybe_unused]] const std::string& group, const Stream& kernelStream, const Stream& hostOrderStream,
     274              :     std::shared_ptr<LocalNotify> notify0, std::shared_ptr<LocalNotify> notify1, u32 timeOut)
     275              : {
     276            0 :     CHK_SMART_PTR_NULL(notify0);
     277            0 :     CHK_SMART_PTR_NULL(notify1);
     278            0 :     aclError ret = ACL_SUCCESS;
     279            0 :     ret = aclrtWaitAndResetNotify(notify0->ptr(), kernelStream.ptr(), timeOut);
     280            0 :     CHK_PRT_RET(
     281              :         ret != ACL_SUCCESS,
     282              :         HCCL_ERROR(
     283              :             "[%s] aclrtWaitAndResetNotify failed, ret[%d], notifyId[%u], streamId[%d], timeOut[%d s]", __func__, ret,
     284              :             notify0->notifyId_, kernelStream.id(), timeOut),
     285              :         HCCL_E_RUNTIME);
     286            0 :     HCCL_CONFIG_INFO(
     287              :         HCCL_TASK, "[%s] aclrtWaitAndResetNotify para: notifyId[%u], streamId[%d], timeOut[%d s]", __func__,
     288              :         notify0->notifyId_, kernelStream.id(), timeOut);
     289              : 
     290            0 :     ret = aclrtRecordNotify(notify0->ptr(), hostOrderStream.ptr());
     291            0 :     CHK_PRT_RET(
     292              :         ret != ACL_SUCCESS,
     293              :         HCCL_ERROR(
     294              :             "[%s] aclrtRecordNotify failed, ret[%d], notifyId[%u], streamId[%d]", __func__, ret, notify0->notifyId_,
     295              :             hostOrderStream.id()),
     296              :         HCCL_E_RUNTIME);
     297            0 :     HCCL_CONFIG_INFO(
     298              :         HCCL_TASK, "[%s] aclrtRecordNotify para: notifyId[%u], streamId[%d]", __func__, notify0->notifyId_,
     299              :         hostOrderStream.id());
     300              : 
     301            0 :     ret = aclrtWaitAndResetNotify(notify1->ptr(), hostOrderStream.ptr(), timeOut);
     302            0 :     CHK_PRT_RET(
     303              :         ret != ACL_SUCCESS,
     304              :         HCCL_ERROR(
     305              :             "[%s] aclrtWaitAndResetNotify failed, ret[%d], notifyId[%u], streamId[%d], timeOut[%d s]", __func__, ret,
     306              :             notify1->notifyId_, hostOrderStream.id(), timeOut),
     307              :         HCCL_E_RUNTIME);
     308            0 :     HCCL_CONFIG_INFO(
     309              :         HCCL_TASK, "[%s] aclrtWaitAndResetNotify para: notifyId[%u], streamId[%d], timeOut[%d s]", __func__,
     310              :         notify1->notifyId_, hostOrderStream.id(), timeOut);
     311            0 :     return HCCL_SUCCESS;
     312              : }
     313              : 
     314            1 : HcclResult OrderLaunch::EnsureOrderStreamForGroup(std::string& group, u64 context, Stream& orderStream)
     315              : {
     316            1 :     auto it = groupCtxMap_.find(group);
     317            1 :     if (it == groupCtxMap_.end()) {
     318            0 :         HCCL_ERROR("[%s] group[%s] not found", __func__, group.c_str());
     319            0 :         return HCCL_E_PARA;
     320              :     }
     321              : 
     322            1 :     if (contextResMgrMap_.find(context) == contextResMgrMap_.end()) {
     323            0 :         HCCL_ERROR("[%s] context[0x%llx] not found for group[%s]", __func__, context, group.c_str());
     324            0 :         return HCCL_E_PARA;
     325              :     }
     326              : 
     327            1 :     auto& groupCtxRes = contextResMgrMap_[context];
     328              : 
     329            1 :     if (orderStream.ptr() == nullptr) {
     330            1 :         HCCL_INFO(
     331              :             "[OrderLaunch][EnsureOrderStreamForGroup] creating new order stream for group[%s], context[0x%llx]",
     332              :             group.c_str(), context);
     333              :         // Stream 尚未创建,基于传入的 context 创建
     334              :         // 创建新的order stream; streamMode = 1 使能遇错即停,避免出错后流卡住不退
     335            1 :         constexpr u32 streamMode = 1;
     336            1 :         orderStream = Stream(StreamType::STREAM_TYPE_ONLINE);
     337            1 :         CHK_RET(hrtStreamSetMode(orderStream.ptr(), streamMode));
     338            1 :         HCCL_INFO(
     339              :             "[OrderLaunch] Created new order stream with id[%d] with context [0x%llx]", orderStream.id(), context);
     340              : 
     341              :         // 对group->contextResource的映射关系进行更新
     342            1 :         if (!groupCtxRes.contextInitialized) {
     343            0 :             groupCtxRes.MarkContextInitialized(context);
     344              :         } else {
     345            1 :             groupCtxRes.UpdateContext(context);
     346              :         }
     347              :         // 对context->group的映射关系进行更新
     348            1 :         contextGroupsMap_[context].insert(group);
     349            1 :         HCCL_INFO(
     350              :             "[OrderLaunch] Added group[%s] to context [0x%llx] with order stream id[%d]", group.c_str(), context,
     351              :             orderStream.id());
     352              :     } else {
     353            0 :         HCCL_INFO(
     354              :             "[OrderLaunch][EnsureOrderStreamForGroup] order stream already exists, group[%s], context[0x%llx], "
     355              :             "streamId[%d]",
     356              :             group.c_str(), context, orderStream.id());
     357              :     }
     358            1 :     return HCCL_SUCCESS;
     359              : }
     360              : 
     361              : /**
     362              :  * @brief 获取当前线程的context
     363              :  * 通过hrtCtxGetCurrent接口获取当前线程关联的runtime context
     364              :  */
     365            1 : HcclResult OrderLaunch::GetCurrentContext(u64& currentContext) const
     366              : {
     367            1 :     HcclRtContext rtCtx = nullptr;
     368            1 :     CHK_RET(hrtCtxGetCurrent(&rtCtx));
     369            1 :     currentContext = reinterpret_cast<u64>(rtCtx);
     370              : 
     371            1 :     if (currentContext == INVALID_U64) {
     372            0 :         HCCL_ERROR("[%s] GetCurrentContext failed", __func__);
     373            0 :         return HCCL_E_RUNTIME;
     374              :     }
     375              : 
     376            1 :     return HCCL_SUCCESS;
     377              : }
     378              : } // namespace hccl
        

Generated by: LCOV version 2.0-1