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& params)
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(
49 2 : params.deviceId, aiCpuIds_, ctrlCpuIds_, 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(
56 1 : params.deviceIdExtra, aiCpuIdsExtra_, ctrlCpuIdsExtra_, coreNumPerDevExtra_, aicpuNumExtra_,
57 1 : aicpuBaseIdExtra_);
58 1 : if (initCpuInfoRet != BQS_STATUS_OK) {
59 1 : BQS_LOG_ERROR("GetDevCpuInfo error");
60 1 : return static_cast<int32_t>(initCpuInfoRet);
61 : }
62 : }
63 :
64 5 : queueSchedule_.reset(new (std::nothrow) QueueSchedule(params));
65 5 : if (queueSchedule_ == nullptr) {
66 0 : BQS_LOG_ERROR("Fail to allocate QueueSchedule");
67 0 : return static_cast<int32_t>(BQS_STATUS_INNER_ERROR);
68 : }
69 5 : BQS_LOG_INFO(
70 : "Prepare bind process with host process, deviceId[%u], RunContext is [%u]", params.deviceId,
71 : static_cast<uint32_t>(bqs::GetRunContext()));
72 : // bind process with hostpid in process mode
73 6 : if ((bqs::GetRunContext() != bqs::RunContext::HOST) && (params.starter != bqs::QsStartType::START_BY_DEPLOYER) &&
74 1 : (params.runMode != QueueSchedulerRunMode::MULTI_THREAD)) {
75 1 : const auto bindRet = CheckBindHostPid(params.pid);
76 1 : if (bindRet != bqs::BQS_STATUS_OK) {
77 1 : BQS_LOG_ERROR("BindHostPid failed");
78 1 : return static_cast<int32_t>(bindRet);
79 : }
80 : }
81 : // init profiling
82 4 : const bool profFlag = params.profFlag;
83 4 : BqsMsprofManager::GetInstance().InitBqsMsprofManager(profFlag, params.profCfgData);
84 :
85 4 : const bqs::BqsStatus bsqStatus = queueSchedule_->StartQueueSchedule();
86 4 : if (bsqStatus != bqs::BQS_STATUS_OK) {
87 2 : BQS_LOG_ERROR("QueueSchedule start failed, ret=%d", static_cast<int32_t>(bsqStatus));
88 2 : return static_cast<int32_t>(bsqStatus);
89 : }
90 2 : return static_cast<int32_t>(BQS_STATUS_OK);
91 7 : }
92 :
93 16 : void QueueScheduleInterface::WaitForStop()
94 : {
95 16 : if (queueSchedule_ != nullptr) {
96 16 : queueSchedule_->WaitForStop();
97 : }
98 16 : }
99 :
100 : /**
101 : * @ingroup QueueScheduleInterface
102 : * @brief it use to destroy all model.
103 : */
104 14 : int32_t QueueScheduleInterface::Destroy() const
105 : {
106 14 : if (queueSchedule_ != nullptr) {
107 14 : queueSchedule_->Destroy();
108 : }
109 14 : return static_cast<int32_t>(BQS_STATUS_OK);
110 : }
111 :
112 4 : uint32_t QueueScheduleInterface::GetAicpuPhysIndex(uint32_t deviceId, const uint32_t aicpuLogIndex) const
113 : {
114 4 : if (FeatureCtrl::IsAosCore()) {
115 : // connot overflow
116 1 : return ((aicpuBaseId_ + aicpuNum_) * deviceId) + aicpuBaseId_ + aicpuLogIndex;
117 : }
118 :
119 3 : if (aicpuLogIndex >= aiCpuIds_.size()) {
120 2 : BQS_LOG_INFO("Get aicpu index not success");
121 2 : return 0U;
122 : }
123 :
124 1 : if (FeatureCtrl::BindCpuOnlyOneDevice()) {
125 : // 只有一个device,vf切分到同一容器时会产生多个deviceId。
126 1 : return aiCpuIds_[aicpuLogIndex];
127 : }
128 0 : return (coreNumPerDev_ * deviceId) + aiCpuIds_[aicpuLogIndex];
129 : }
130 :
131 2 : uint32_t QueueScheduleInterface::GetExtraAicpuPhysIndex(uint32_t deviceId, const uint32_t aicpuLogIndex) const
132 : {
133 : #ifdef _AOSCORE_
134 : // connot overflow
135 : return ((aicpuBaseIdExtra_ + aicpuNumExtra_) * deviceId) + aicpuBaseIdExtra_ + aicpuLogIndex;
136 : #else
137 2 : if (aicpuLogIndex >= aiCpuIdsExtra_.size()) {
138 1 : BQS_LOG_ERROR("Get aicpu index error");
139 1 : return 0U;
140 : }
141 : #ifdef BIND_CPU_ONLY_ONE_DEVICE
142 : // 只有一个device,vf切分到同一容器时会产生多个deviceId。
143 : return aiCpuIdsExtra_[aicpuLogIndex];
144 : #else
145 1 : return (coreNumPerDevExtra_ * deviceId) + aiCpuIdsExtra_[aicpuLogIndex];
146 : #endif
147 : #endif
148 : }
149 :
150 4 : int32_t QueueScheduleInterface::CheckBindHostPid(const uint32_t selfHostPid) const
151 : {
152 4 : BQS_LOG_RUN_INFO("Start query process host pid");
153 4 : if (&drvQueryProcessHostPid == nullptr) {
154 0 : BQS_LOG_INFO("drvQueryProcessHostPid does not exist");
155 0 : return bqs::BQS_STATUS_OK;
156 : }
157 4 : drvError_t ret = DRV_ERROR_NONE;
158 4 : unsigned int hostpid = 0;
159 4 : unsigned int cpType = DEVDRV_PROCESS_CPTYPE_MAX;
160 4 : const int pid = static_cast<int>(getpid());
161 14 : for (uint32_t i = 0; i < QUERY_BIND_HOST_PID_TIME / QUERY_BIND_HOST_PID_INTERVBALE; i++) {
162 13 : ret = drvQueryProcessHostPid(pid, nullptr, nullptr, &hostpid, &cpType);
163 13 : if ((i % QUERY_BIND_HOST_PID_LOG_INTERVAL) == 0U) {
164 4 : BQS_LOG_RUN_INFO(
165 : "Query process host pid end, ret=%d, hostpid=%u, expect=%u, cpType=%u", static_cast<int32_t>(ret),
166 : hostpid, selfHostPid, cpType);
167 : }
168 13 : if (ret == DRV_ERROR_NO_PROCESS) {
169 10 : BQS_LOG_INFO("call drvQueryProcessHostPid trg again");
170 10 : (void)usleep(QUERY_BIND_HOST_PID_INTERVBALE);
171 10 : continue;
172 : }
173 3 : if (ret != DRV_ERROR_NONE) {
174 1 : BQS_LOG_ERROR("call drvQueryProcessHostPid failed, ret[%d]", static_cast<int32_t>(ret));
175 1 : return bqs::BQS_STATUS_DRIVER_ERROR;
176 : }
177 2 : BQS_LOG_INFO("call drvQueryProcessHostPid result, hostpid[%d], cpType[%d]", hostpid, cpType);
178 2 : if (selfHostPid == static_cast<uint32_t>(hostpid)) {
179 1 : BQS_LOG_RUN_INFO("call drvQueryProcessHostPid success, hostpid[%d]", hostpid);
180 1 : return bqs::BQS_STATUS_OK;
181 : } else {
182 1 : BQS_LOG_ERROR(
183 : "CheckBindHostPid failed, hostpid not right. ret[%d], pid[%d], hostpid[%d], cpType[%d]",
184 : static_cast<int32_t>(ret), pid, hostpid, cpType);
185 1 : return bqs::BQS_STATUS_DRIVER_ERROR;
186 : }
187 : }
188 1 : BQS_LOG_ERROR(
189 : "CheckBindHostPid failed, try timeout. ret[%d], pid[%d], hostpid[%d], cpType[%d]", static_cast<int32_t>(ret),
190 : pid, hostpid, cpType);
191 1 : return bqs::BQS_STATUS_DRIVER_ERROR;
192 : }
193 :
194 1 : void QueueScheduleInterface::ReportAbnormal() const
195 : {
196 1 : if (queueSchedule_ != nullptr) {
197 1 : queueSchedule_->ReportAbnormal();
198 : }
199 1 : }
200 : } // namespace bqs
|