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 "qs_interface_process.h"
12 : #include <securec.h>
13 : #include <unistd.h>
14 : #include "common/bqs_log.h"
15 : #include "common/bqs_util.h"
16 : #include "msprof_manager.h"
17 : #include "queue_schedule_hal_interface_ref.h"
18 : #include "common/bqs_feature_ctrl.h"
19 :
20 : namespace bqs {
21 : // 查询bind信息间隔
22 : constexpr uint32_t QUERY_BIND_HOST_PID_INTERVBALE = 10000U;
23 : // 查询bind超时时间
24 : #ifndef aicpusd_UT
25 : constexpr uint32_t QUERY_BIND_HOST_PID_TIME = 120000000U;
26 : #else
27 : constexpr uint32_t QUERY_BIND_HOST_PID_TIME = 100000U;
28 : #endif
29 : // bind结果的日志输出周期
30 : constexpr uint32_t QUERY_BIND_HOST_PID_LOG_INTERVAL = 1000U;
31 57 : QueueScheduleInterface &QueueScheduleInterface::GetInstance()
32 : {
33 57 : static QueueScheduleInterface instance;
34 57 : return instance;
35 : }
36 :
37 : /**
38 : * @ingroup QueueScheduleInterface
39 : * @brief it use to initialize aicpu schedule.
40 : * @param [in] params InitQsParams
41 : * @return BQS_STATUS_OK: success, other: error code
42 : */
43 7 : int32_t QueueScheduleInterface::InitQueueScheduler(const InitQsParams ¶ms)
44 : {
45 7 : const std::unique_lock<std::mutex> lk(mutexForInit_);
46 7 : BQS_LOG_INFO("Start up BqsInterface.numaFlag[%d]", params.numaFlag);
47 7 : if (bqs::GetRunContext() != bqs::RunContext::HOST) {
48 4 : const auto initCpuInfoRet = BindCpuUtils::GetDevCpuInfo(params.deviceId, aiCpuIds_, ctrlCpuIds_,
49 2 : coreNumPerDev_, aicpuNum_, aicpuBaseId_);
50 2 : if (initCpuInfoRet != BQS_STATUS_OK) {
51 1 : return static_cast<int32_t>(initCpuInfoRet);
52 : }
53 : }
54 6 : if (params.numaFlag) {
55 2 : const auto initCpuInfoRet = BindCpuUtils::GetDevCpuInfo(params.deviceIdExtra, aiCpuIdsExtra_,
56 1 : ctrlCpuIdsExtra_, coreNumPerDevExtra_, aicpuNumExtra_, aicpuBaseIdExtra_);
57 1 : if (initCpuInfoRet != BQS_STATUS_OK) {
58 1 : BQS_LOG_ERROR("GetDevCpuInfo error");
59 1 : return static_cast<int32_t>(initCpuInfoRet);
60 : }
61 : }
62 :
63 5 : queueSchedule_.reset(new (std::nothrow) QueueSchedule(params));
64 5 : if (queueSchedule_ == nullptr) {
65 0 : BQS_LOG_ERROR("Fail to allocate QueueSchedule");
66 0 : return static_cast<int32_t>(BQS_STATUS_INNER_ERROR);
67 : }
68 5 : BQS_LOG_INFO("Prepare bind process with host process, deviceId[%u], RunContext is [%u]",
69 : params.deviceId, static_cast<uint32_t>(bqs::GetRunContext()));
70 : // bind process with hostpid in process mode
71 5 : if ((bqs::GetRunContext() != bqs::RunContext::HOST) &&
72 6 : (params.starter != bqs::QsStartType::START_BY_DEPLOYER) &&
73 1 : (params.runMode != QueueSchedulerRunMode::MULTI_THREAD)) {
74 1 : const auto bindRet = CheckBindHostPid(params.pid);
75 1 : if (bindRet != bqs::BQS_STATUS_OK) {
76 1 : BQS_LOG_ERROR("BindHostPid failed");
77 1 : return static_cast<int32_t>(bindRet);
78 : }
79 : }
80 : // init profiling
81 4 : const bool profFlag = params.profFlag;
82 4 : BqsMsprofManager::GetInstance().InitBqsMsprofManager(profFlag, params.profCfgData);
83 :
84 4 : const bqs::BqsStatus bsqStatus = queueSchedule_->StartQueueSchedule();
85 4 : if (bsqStatus != bqs::BQS_STATUS_OK) {
86 2 : BQS_LOG_ERROR("QueueSchedule start failed, ret=%d", static_cast<int32_t>(bsqStatus));
87 2 : return static_cast<int32_t>(bsqStatus);
88 : }
89 2 : return static_cast<int32_t>(BQS_STATUS_OK);
90 7 : }
91 :
92 16 : void QueueScheduleInterface::WaitForStop()
93 : {
94 16 : if (queueSchedule_ != nullptr) {
95 16 : queueSchedule_->WaitForStop();
96 : }
97 16 : }
98 :
99 : /**
100 : * @ingroup QueueScheduleInterface
101 : * @brief it use to destroy all model.
102 : */
103 14 : int32_t QueueScheduleInterface::Destroy() const
104 : {
105 14 : if (queueSchedule_ != nullptr) {
106 14 : queueSchedule_->Destroy();
107 : }
108 14 : return static_cast<int32_t>(BQS_STATUS_OK);
109 : }
110 :
111 4 : uint32_t QueueScheduleInterface::GetAicpuPhysIndex(uint32_t deviceId, const uint32_t aicpuLogIndex) const
112 : {
113 4 : if (FeatureCtrl::IsAosCore()) {
114 : // connot overflow
115 1 : return ((aicpuBaseId_ + aicpuNum_) * deviceId) + aicpuBaseId_ + aicpuLogIndex;
116 : }
117 :
118 3 : if (aicpuLogIndex >= aiCpuIds_.size()) {
119 2 : BQS_LOG_INFO("Get aicpu index not success");
120 2 : return 0U;
121 : }
122 :
123 1 : if (FeatureCtrl::BindCpuOnlyOneDevice()) {
124 : // 只有一个device,vf切分到同一容器时会产生多个deviceId。
125 1 : return aiCpuIds_[aicpuLogIndex];
126 : }
127 0 : return (coreNumPerDev_ * deviceId) + aiCpuIds_[aicpuLogIndex];
128 : }
129 :
130 2 : uint32_t QueueScheduleInterface::GetExtraAicpuPhysIndex(uint32_t deviceId, const uint32_t aicpuLogIndex) const
131 : {
132 : #ifdef _AOSCORE_
133 : // connot overflow
134 : return ((aicpuBaseIdExtra_ + aicpuNumExtra_) * deviceId) + aicpuBaseIdExtra_ + aicpuLogIndex;
135 : #else
136 2 : if (aicpuLogIndex >= aiCpuIdsExtra_.size()) {
137 1 : BQS_LOG_ERROR("Get aicpu index error");
138 1 : return 0U;
139 : }
140 : #ifdef BIND_CPU_ONLY_ONE_DEVICE
141 : // 只有一个device,vf切分到同一容器时会产生多个deviceId。
142 : return aiCpuIdsExtra_[aicpuLogIndex];
143 : #else
144 1 : return (coreNumPerDevExtra_ * deviceId) + aiCpuIdsExtra_[aicpuLogIndex];
145 : #endif
146 : #endif
147 : }
148 :
149 4 : int32_t QueueScheduleInterface::CheckBindHostPid(const uint32_t selfHostPid) const
150 : {
151 4 : BQS_LOG_RUN_INFO("Start query process host pid");
152 4 : if (&drvQueryProcessHostPid == nullptr) {
153 0 : BQS_LOG_INFO("drvQueryProcessHostPid does not exist");
154 0 : return bqs::BQS_STATUS_OK;
155 : }
156 4 : drvError_t ret = DRV_ERROR_NONE;
157 4 : unsigned int hostpid = 0;
158 4 : unsigned int cpType = DEVDRV_PROCESS_CPTYPE_MAX;
159 4 : const int pid = static_cast<int>(getpid());
160 14 : for (uint32_t i = 0; i < QUERY_BIND_HOST_PID_TIME/QUERY_BIND_HOST_PID_INTERVBALE; i++) {
161 13 : ret = drvQueryProcessHostPid(pid, nullptr, nullptr, &hostpid, &cpType);
162 13 : if ((i % QUERY_BIND_HOST_PID_LOG_INTERVAL) == 0U) {
163 4 : BQS_LOG_RUN_INFO("Query process host pid end, ret=%d, hostpid=%u, expect=%u, cpType=%u",
164 : static_cast<int32_t>(ret), hostpid, selfHostPid, cpType);
165 : }
166 13 : if (ret == DRV_ERROR_NO_PROCESS) {
167 10 : BQS_LOG_INFO("call drvQueryProcessHostPid trg again");
168 10 : (void)usleep(QUERY_BIND_HOST_PID_INTERVBALE);
169 10 : continue;
170 : }
171 3 : if (ret != DRV_ERROR_NONE) {
172 1 : BQS_LOG_ERROR("call drvQueryProcessHostPid failed, ret[%d]", static_cast<int32_t>(ret));
173 1 : return bqs::BQS_STATUS_DRIVER_ERROR;
174 : }
175 2 : BQS_LOG_INFO("call drvQueryProcessHostPid result, hostpid[%d], cpType[%d]", hostpid, cpType);
176 2 : if (selfHostPid == static_cast<uint32_t>(hostpid)) {
177 1 : BQS_LOG_RUN_INFO("call drvQueryProcessHostPid success, hostpid[%d]", hostpid);
178 1 : return bqs::BQS_STATUS_OK;
179 : } else {
180 1 : BQS_LOG_ERROR("CheckBindHostPid failed, hostpid not right. ret[%d], pid[%d], hostpid[%d], cpType[%d]",
181 : static_cast<int32_t>(ret), pid, hostpid, cpType);
182 1 : return bqs::BQS_STATUS_DRIVER_ERROR;
183 : }
184 : }
185 1 : BQS_LOG_ERROR("CheckBindHostPid failed, try timeout. ret[%d], pid[%d], hostpid[%d], cpType[%d]",
186 : static_cast<int32_t>(ret), pid, hostpid, cpType);
187 1 : return bqs::BQS_STATUS_DRIVER_ERROR;
188 : }
189 :
190 1 : void QueueScheduleInterface::ReportAbnormal() const
191 : {
192 1 : if (queueSchedule_ != nullptr) {
193 1 : queueSchedule_->ReportAbnormal();
194 : }
195 1 : }
196 : }
|