1*523fa7a6SAndroid Build Coastguard Worker /*
2*523fa7a6SAndroid Build Coastguard Worker * Copyright (c) Qualcomm Innovation Center, Inc.
3*523fa7a6SAndroid Build Coastguard Worker * All rights reserved.
4*523fa7a6SAndroid Build Coastguard Worker *
5*523fa7a6SAndroid Build Coastguard Worker * This source code is licensed under the BSD-style license found in the
6*523fa7a6SAndroid Build Coastguard Worker * LICENSE file in the root directory of this source tree.
7*523fa7a6SAndroid Build Coastguard Worker */
8*523fa7a6SAndroid Build Coastguard Worker
9*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/aot/ir/qcir_utils.h>
10*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/qc_binary_info_generated.h>
11*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/QnnManager.h>
12*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/SharedBuffer.h>
13*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/Utils.h>
14*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/backends/QnnBackendCommon.h>
15*523fa7a6SAndroid Build Coastguard Worker #include <executorch/backends/qualcomm/runtime/backends/QnnImplementation.h>
16*523fa7a6SAndroid Build Coastguard Worker #include <executorch/extension/tensor/tensor.h>
17*523fa7a6SAndroid Build Coastguard Worker #include <algorithm>
18*523fa7a6SAndroid Build Coastguard Worker #include <cstdlib>
19*523fa7a6SAndroid Build Coastguard Worker #include <cstring>
20*523fa7a6SAndroid Build Coastguard Worker #include <fstream>
21*523fa7a6SAndroid Build Coastguard Worker #include <string>
22*523fa7a6SAndroid Build Coastguard Worker
23*523fa7a6SAndroid Build Coastguard Worker namespace executorch {
24*523fa7a6SAndroid Build Coastguard Worker namespace backends {
25*523fa7a6SAndroid Build Coastguard Worker namespace qnn {
26*523fa7a6SAndroid Build Coastguard Worker
27*523fa7a6SAndroid Build Coastguard Worker using executorch::runtime::Error;
28*523fa7a6SAndroid Build Coastguard Worker
CompareExportedInput(const std::shared_ptr<TensorWrapper> & a,const std::shared_ptr<TensorWrapper> & b)29*523fa7a6SAndroid Build Coastguard Worker bool CompareExportedInput(
30*523fa7a6SAndroid Build Coastguard Worker const std::shared_ptr<TensorWrapper>& a,
31*523fa7a6SAndroid Build Coastguard Worker const std::shared_ptr<TensorWrapper>& b) {
32*523fa7a6SAndroid Build Coastguard Worker // Using the order of the nodes as external_id in AOT
33*523fa7a6SAndroid Build Coastguard Worker // to extract the right arg from *args at runtime
34*523fa7a6SAndroid Build Coastguard Worker int numA = std::stoi(a->GetName().substr(a->GetName().find('_') + 1));
35*523fa7a6SAndroid Build Coastguard Worker int numB = std::stoi(b->GetName().substr(b->GetName().find('_') + 1));
36*523fa7a6SAndroid Build Coastguard Worker return numA < numB;
37*523fa7a6SAndroid Build Coastguard Worker }
38*523fa7a6SAndroid Build Coastguard Worker
~QnnManager()39*523fa7a6SAndroid Build Coastguard Worker QnnManager::~QnnManager() {
40*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_.reset(new BackendConfigParameters());
41*523fa7a6SAndroid Build Coastguard Worker logger_.reset();
42*523fa7a6SAndroid Build Coastguard Worker qnn_loaded_backend_.TerminateAllBackends();
43*523fa7a6SAndroid Build Coastguard Worker }
44*523fa7a6SAndroid Build Coastguard Worker
QnnManager(const QnnExecuTorchOptions * options,const QnnExecuTorchContextBinary & qnn_executorch_context_binary)45*523fa7a6SAndroid Build Coastguard Worker QnnManager::QnnManager(
46*523fa7a6SAndroid Build Coastguard Worker const QnnExecuTorchOptions* options,
47*523fa7a6SAndroid Build Coastguard Worker const QnnExecuTorchContextBinary& qnn_executorch_context_binary)
48*523fa7a6SAndroid Build Coastguard Worker : qnn_context_blob_(qnn_executorch_context_binary),
49*523fa7a6SAndroid Build Coastguard Worker qnn_loaded_backend_(""),
50*523fa7a6SAndroid Build Coastguard Worker // options' life cycle is decided by compiler specs which is
51*523fa7a6SAndroid Build Coastguard Worker // kept by executorch runtime framework
52*523fa7a6SAndroid Build Coastguard Worker // please pay attention to any potential seg fault
53*523fa7a6SAndroid Build Coastguard Worker options_(options) {
54*523fa7a6SAndroid Build Coastguard Worker QnnExecuTorchBackendType backend_type =
55*523fa7a6SAndroid Build Coastguard Worker options->backend_options()->backend_type();
56*523fa7a6SAndroid Build Coastguard Worker std::string library_path = options->library_path()->str();
57*523fa7a6SAndroid Build Coastguard Worker
58*523fa7a6SAndroid Build Coastguard Worker if (options->log_level() >= QnnExecuTorchLogLevel::kLogLevelInfo) {
59*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
60*523fa7a6SAndroid Build Coastguard Worker "soc_model in soc_info: %s",
61*523fa7a6SAndroid Build Coastguard Worker EnumNameQcomChipset(options_->soc_info()->soc_model()));
62*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
63*523fa7a6SAndroid Build Coastguard Worker "backend_type: %s", EnumNameQnnExecuTorchBackendType(backend_type));
64*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO("graph_name: %s", options_->graph_name()->c_str());
65*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO("library_path: %s", library_path.c_str());
66*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO("dump intermediate outputs: %s", IsTensorDump());
67*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
68*523fa7a6SAndroid Build Coastguard Worker "log_level: %s", EnumNameQnnExecuTorchLogLevel(options_->log_level()));
69*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
70*523fa7a6SAndroid Build Coastguard Worker "profile_level: %s",
71*523fa7a6SAndroid Build Coastguard Worker EnumNameQnnExecuTorchProfileLevel(options_->profile_level()));
72*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
73*523fa7a6SAndroid Build Coastguard Worker "the size of qnn context binary: %d",
74*523fa7a6SAndroid Build Coastguard Worker qnn_executorch_context_binary.nbytes);
75*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
76*523fa7a6SAndroid Build Coastguard Worker "Is on-device graph construction: %d", options->online_prepare());
77*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
78*523fa7a6SAndroid Build Coastguard Worker "Enable shared buffer: %d", options->shared_buffer());
79*523fa7a6SAndroid Build Coastguard Worker }
80*523fa7a6SAndroid Build Coastguard Worker
81*523fa7a6SAndroid Build Coastguard Worker if (library_path.empty()) {
82*523fa7a6SAndroid Build Coastguard Worker switch (backend_type) {
83*523fa7a6SAndroid Build Coastguard Worker case QnnExecuTorchBackendType::kHtpBackend:
84*523fa7a6SAndroid Build Coastguard Worker library_path = htp_library_name_;
85*523fa7a6SAndroid Build Coastguard Worker break;
86*523fa7a6SAndroid Build Coastguard Worker case QnnExecuTorchBackendType::kDspBackend:
87*523fa7a6SAndroid Build Coastguard Worker library_path = dsp_library_name_;
88*523fa7a6SAndroid Build Coastguard Worker break;
89*523fa7a6SAndroid Build Coastguard Worker case QnnExecuTorchBackendType::kGpuBackend:
90*523fa7a6SAndroid Build Coastguard Worker library_path = gpu_library_name_;
91*523fa7a6SAndroid Build Coastguard Worker break;
92*523fa7a6SAndroid Build Coastguard Worker default:
93*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_ERROR("Unknown backend type: %d", backend_type);
94*523fa7a6SAndroid Build Coastguard Worker break;
95*523fa7a6SAndroid Build Coastguard Worker }
96*523fa7a6SAndroid Build Coastguard Worker }
97*523fa7a6SAndroid Build Coastguard Worker qnn_loaded_backend_ = QnnImplementation(library_path);
98*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_ = std::make_unique<BackendConfigParameters>();
99*523fa7a6SAndroid Build Coastguard Worker }
100*523fa7a6SAndroid Build Coastguard Worker
LoadQnnLibrary()101*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::LoadQnnLibrary() {
102*523fa7a6SAndroid Build Coastguard Worker Error ret = qnn_loaded_backend_.Load(nullptr);
103*523fa7a6SAndroid Build Coastguard Worker return ret;
104*523fa7a6SAndroid Build Coastguard Worker }
105*523fa7a6SAndroid Build Coastguard Worker
PreRegisterMem()106*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::PreRegisterMem() {
107*523fa7a6SAndroid Build Coastguard Worker SharedBuffer& shared_buffer_manager = SharedBuffer::GetSharedBufferManager();
108*523fa7a6SAndroid Build Coastguard Worker for (const auto info : shared_buffer_manager.GetCustomMemTensorInfoSet()) {
109*523fa7a6SAndroid Build Coastguard Worker void* unaligned_custom_mem_base =
110*523fa7a6SAndroid Build Coastguard Worker shared_buffer_manager.GetUnAlignedAddr(info.custom_mem);
111*523fa7a6SAndroid Build Coastguard Worker
112*523fa7a6SAndroid Build Coastguard Worker size_t tensor_offset = (static_cast<char*>(info.custom_mem) -
113*523fa7a6SAndroid Build Coastguard Worker static_cast<char*>(unaligned_custom_mem_base)) +
114*523fa7a6SAndroid Build Coastguard Worker info.pos;
115*523fa7a6SAndroid Build Coastguard Worker size_t total_custom_mem_size =
116*523fa7a6SAndroid Build Coastguard Worker shared_buffer_manager.GetAllocatedSize(info.custom_mem);
117*523fa7a6SAndroid Build Coastguard Worker
118*523fa7a6SAndroid Build Coastguard Worker int32_t mem_fd = shared_buffer_manager.MemToFd(unaligned_custom_mem_base);
119*523fa7a6SAndroid Build Coastguard Worker if (mem_fd == -1) {
120*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_WARN(
121*523fa7a6SAndroid Build Coastguard Worker "PreRegisterMem failed to get file descriptor.",
122*523fa7a6SAndroid Build Coastguard Worker "custom_mem: %p",
123*523fa7a6SAndroid Build Coastguard Worker "tensor_addr: %p",
124*523fa7a6SAndroid Build Coastguard Worker "pos: %uz",
125*523fa7a6SAndroid Build Coastguard Worker "tensor_bytes: %uz",
126*523fa7a6SAndroid Build Coastguard Worker "shape: %p",
127*523fa7a6SAndroid Build Coastguard Worker "rank: %zu",
128*523fa7a6SAndroid Build Coastguard Worker "qnn_dtype: %X",
129*523fa7a6SAndroid Build Coastguard Worker info.custom_mem,
130*523fa7a6SAndroid Build Coastguard Worker info.tensor_addr,
131*523fa7a6SAndroid Build Coastguard Worker info.pos,
132*523fa7a6SAndroid Build Coastguard Worker info.tensor_bytes,
133*523fa7a6SAndroid Build Coastguard Worker info.shape,
134*523fa7a6SAndroid Build Coastguard Worker info.rank,
135*523fa7a6SAndroid Build Coastguard Worker info.dtype);
136*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
137*523fa7a6SAndroid Build Coastguard Worker }
138*523fa7a6SAndroid Build Coastguard Worker
139*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
140*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_mem_manager_ptr_->PreRegisterCustomMemHandle(
141*523fa7a6SAndroid Build Coastguard Worker mem_fd,
142*523fa7a6SAndroid Build Coastguard Worker unaligned_custom_mem_base,
143*523fa7a6SAndroid Build Coastguard Worker total_custom_mem_size,
144*523fa7a6SAndroid Build Coastguard Worker tensor_offset,
145*523fa7a6SAndroid Build Coastguard Worker info) == Error::Ok,
146*523fa7a6SAndroid Build Coastguard Worker Internal,
147*523fa7a6SAndroid Build Coastguard Worker "Fail to register to shared memory.");
148*523fa7a6SAndroid Build Coastguard Worker }
149*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
150*523fa7a6SAndroid Build Coastguard Worker }
151*523fa7a6SAndroid Build Coastguard Worker
RegisterMem(void * data_ptr,const std::shared_ptr<TensorWrapper> & tensor_wrapper)152*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::RegisterMem(
153*523fa7a6SAndroid Build Coastguard Worker void* data_ptr,
154*523fa7a6SAndroid Build Coastguard Worker const std::shared_ptr<TensorWrapper>& tensor_wrapper) {
155*523fa7a6SAndroid Build Coastguard Worker SharedBuffer& shared_buffer_manager = SharedBuffer::GetSharedBufferManager();
156*523fa7a6SAndroid Build Coastguard Worker // Not enable shared buffer
157*523fa7a6SAndroid Build Coastguard Worker if (!options_->shared_buffer())
158*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
159*523fa7a6SAndroid Build Coastguard Worker
160*523fa7a6SAndroid Build Coastguard Worker if (backend_params_ptr_->qnn_mem_manager_ptr_ == nullptr) {
161*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_WARN(
162*523fa7a6SAndroid Build Coastguard Worker "Backend %s doesn't supported shared buffer.",
163*523fa7a6SAndroid Build Coastguard Worker EnumNameQnnExecuTorchBackendType(
164*523fa7a6SAndroid Build Coastguard Worker options_->backend_options()->backend_type()));
165*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
166*523fa7a6SAndroid Build Coastguard Worker }
167*523fa7a6SAndroid Build Coastguard Worker
168*523fa7a6SAndroid Build Coastguard Worker void* custom_mem_base = shared_buffer_manager.GetCustomMemBase(data_ptr);
169*523fa7a6SAndroid Build Coastguard Worker if (custom_mem_base != nullptr) {
170*523fa7a6SAndroid Build Coastguard Worker return RegisterCustomMem(data_ptr, custom_mem_base, tensor_wrapper);
171*523fa7a6SAndroid Build Coastguard Worker }
172*523fa7a6SAndroid Build Coastguard Worker return RegisterIonMem(data_ptr, tensor_wrapper);
173*523fa7a6SAndroid Build Coastguard Worker }
174*523fa7a6SAndroid Build Coastguard Worker
RegisterIonMem(void * data_ptr,const std::shared_ptr<TensorWrapper> & tensor_wrapper)175*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::RegisterIonMem(
176*523fa7a6SAndroid Build Coastguard Worker void* data_ptr,
177*523fa7a6SAndroid Build Coastguard Worker const std::shared_ptr<TensorWrapper>& tensor_wrapper) {
178*523fa7a6SAndroid Build Coastguard Worker SharedBuffer& shared_buffer_manager = SharedBuffer::GetSharedBufferManager();
179*523fa7a6SAndroid Build Coastguard Worker if (!shared_buffer_manager.IsAllocated(data_ptr)) {
180*523fa7a6SAndroid Build Coastguard Worker // It means two scenarios here:
181*523fa7a6SAndroid Build Coastguard Worker // 1. the input and output partitioned graph
182*523fa7a6SAndroid Build Coastguard Worker // 2. Actually, user doesn't allocate shared buffer with
183*523fa7a6SAndroid Build Coastguard Worker // QnnExecuTorchAllocCustomMem API
184*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
185*523fa7a6SAndroid Build Coastguard Worker } else if (backend_params_ptr_->qnn_mem_manager_ptr_->IsRegistered(
186*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetMemHandle(), data_ptr)) {
187*523fa7a6SAndroid Build Coastguard Worker if (options_->log_level() >= QnnExecuTorchLogLevel::kLogLevelInfo)
188*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
189*523fa7a6SAndroid Build Coastguard Worker "Tensor name %s has been registered shared memory.",
190*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetName().c_str());
191*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
192*523fa7a6SAndroid Build Coastguard Worker }
193*523fa7a6SAndroid Build Coastguard Worker
194*523fa7a6SAndroid Build Coastguard Worker int32_t mem_fd = shared_buffer_manager.MemToFd(data_ptr);
195*523fa7a6SAndroid Build Coastguard Worker if (mem_fd == -1) {
196*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_WARN(
197*523fa7a6SAndroid Build Coastguard Worker "Tensor name %s is failed to get file descriptor.",
198*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetName().c_str());
199*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
200*523fa7a6SAndroid Build Coastguard Worker }
201*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
202*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_mem_manager_ptr_->RegisterIonMem(
203*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper, mem_fd, data_ptr) == Error::Ok,
204*523fa7a6SAndroid Build Coastguard Worker Internal,
205*523fa7a6SAndroid Build Coastguard Worker "Fail to register to shared memory.");
206*523fa7a6SAndroid Build Coastguard Worker
207*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
208*523fa7a6SAndroid Build Coastguard Worker }
209*523fa7a6SAndroid Build Coastguard Worker
RegisterCustomMem(void * data_ptr,void * custom_mem_base,const std::shared_ptr<TensorWrapper> & tensor_wrapper)210*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::RegisterCustomMem(
211*523fa7a6SAndroid Build Coastguard Worker void* data_ptr,
212*523fa7a6SAndroid Build Coastguard Worker void* custom_mem_base,
213*523fa7a6SAndroid Build Coastguard Worker const std::shared_ptr<TensorWrapper>& tensor_wrapper) {
214*523fa7a6SAndroid Build Coastguard Worker if (backend_params_ptr_->qnn_mem_manager_ptr_->IsRegistered(
215*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetMemHandle(), data_ptr)) {
216*523fa7a6SAndroid Build Coastguard Worker if (options_->log_level() >= QnnExecuTorchLogLevel::kLogLevelInfo)
217*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
218*523fa7a6SAndroid Build Coastguard Worker "Tensor name %s has been registered shared memory.",
219*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetName().c_str());
220*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
221*523fa7a6SAndroid Build Coastguard Worker }
222*523fa7a6SAndroid Build Coastguard Worker
223*523fa7a6SAndroid Build Coastguard Worker CustomMemTensorInfo info{
224*523fa7a6SAndroid Build Coastguard Worker custom_mem_base,
225*523fa7a6SAndroid Build Coastguard Worker data_ptr,
226*523fa7a6SAndroid Build Coastguard Worker static_cast<size_t>(
227*523fa7a6SAndroid Build Coastguard Worker static_cast<char*>(data_ptr) - static_cast<char*>(custom_mem_base)),
228*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetBytes(),
229*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetDims(),
230*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetRank(),
231*523fa7a6SAndroid Build Coastguard Worker qnn_dtype_to_scalar_type_[tensor_wrapper->GetDataType()]};
232*523fa7a6SAndroid Build Coastguard Worker
233*523fa7a6SAndroid Build Coastguard Worker Qnn_MemHandle_t pre_registered_handle =
234*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_mem_manager_ptr_->GetPreRegisteredHandle(info);
235*523fa7a6SAndroid Build Coastguard Worker if (pre_registered_handle != nullptr) {
236*523fa7a6SAndroid Build Coastguard Worker if (options_->log_level() >= QnnExecuTorchLogLevel::kLogLevelInfo) {
237*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
238*523fa7a6SAndroid Build Coastguard Worker "Tensor name %s found a pre-registered memHandle.",
239*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetName().c_str());
240*523fa7a6SAndroid Build Coastguard Worker }
241*523fa7a6SAndroid Build Coastguard Worker return backend_params_ptr_->qnn_mem_manager_ptr_->SetMemHandle(
242*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper, data_ptr, pre_registered_handle);
243*523fa7a6SAndroid Build Coastguard Worker }
244*523fa7a6SAndroid Build Coastguard Worker
245*523fa7a6SAndroid Build Coastguard Worker SharedBuffer& shared_buffer_manager = SharedBuffer::GetSharedBufferManager();
246*523fa7a6SAndroid Build Coastguard Worker void* unaligned_custom_mem_base =
247*523fa7a6SAndroid Build Coastguard Worker shared_buffer_manager.GetUnAlignedAddr(custom_mem_base);
248*523fa7a6SAndroid Build Coastguard Worker
249*523fa7a6SAndroid Build Coastguard Worker size_t tensor_offset = static_cast<char*>(custom_mem_base) -
250*523fa7a6SAndroid Build Coastguard Worker static_cast<char*>(unaligned_custom_mem_base) + info.pos;
251*523fa7a6SAndroid Build Coastguard Worker size_t total_custom_mem_size =
252*523fa7a6SAndroid Build Coastguard Worker shared_buffer_manager.GetAllocatedSize(custom_mem_base);
253*523fa7a6SAndroid Build Coastguard Worker
254*523fa7a6SAndroid Build Coastguard Worker int32_t mem_fd = shared_buffer_manager.MemToFd(unaligned_custom_mem_base);
255*523fa7a6SAndroid Build Coastguard Worker if (mem_fd == -1) {
256*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_WARN(
257*523fa7a6SAndroid Build Coastguard Worker "Tensor name %s failed to get file descriptor.",
258*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetName().c_str());
259*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
260*523fa7a6SAndroid Build Coastguard Worker }
261*523fa7a6SAndroid Build Coastguard Worker
262*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
263*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_mem_manager_ptr_->RegisterCustomMem(
264*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper,
265*523fa7a6SAndroid Build Coastguard Worker mem_fd,
266*523fa7a6SAndroid Build Coastguard Worker data_ptr,
267*523fa7a6SAndroid Build Coastguard Worker unaligned_custom_mem_base,
268*523fa7a6SAndroid Build Coastguard Worker total_custom_mem_size,
269*523fa7a6SAndroid Build Coastguard Worker tensor_offset) == Error::Ok,
270*523fa7a6SAndroid Build Coastguard Worker Internal,
271*523fa7a6SAndroid Build Coastguard Worker "Fail to register to shared memory.");
272*523fa7a6SAndroid Build Coastguard Worker
273*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
274*523fa7a6SAndroid Build Coastguard Worker }
275*523fa7a6SAndroid Build Coastguard Worker
Init()276*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::Init() {
277*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
278*523fa7a6SAndroid Build Coastguard Worker LoadQnnLibrary() == Error::Ok, Internal, "Fail to load Qnn library");
279*523fa7a6SAndroid Build Coastguard Worker logger_ = std::make_unique<QnnLogger>(
280*523fa7a6SAndroid Build Coastguard Worker qnn_loaded_backend_, LoggingCallback, options_->log_level());
281*523fa7a6SAndroid Build Coastguard Worker if (backend_params_ptr_->backend_init_state_ ==
282*523fa7a6SAndroid Build Coastguard Worker BackendInitializeState::UNINITIALIZED) {
283*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO(
284*523fa7a6SAndroid Build Coastguard Worker "Initialize Qnn backend "
285*523fa7a6SAndroid Build Coastguard Worker "parameters for Qnn executorch backend type %d",
286*523fa7a6SAndroid Build Coastguard Worker options_->backend_options()->backend_type());
287*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_ = QnnBackendFactory().Create(
288*523fa7a6SAndroid Build Coastguard Worker qnn_loaded_backend_, logger_.get(), qnn_context_blob_, options_);
289*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
290*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_ != nullptr, Internal, "Failed to load Qnn backend.")
291*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
292*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_backend_cache_ptr_->Configure() == Error::Ok,
293*523fa7a6SAndroid Build Coastguard Worker Internal,
294*523fa7a6SAndroid Build Coastguard Worker "Fail to configure Qnn backend cache");
295*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
296*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_backend_ptr_->Configure() == Error::Ok,
297*523fa7a6SAndroid Build Coastguard Worker Internal,
298*523fa7a6SAndroid Build Coastguard Worker "Fail to configure Qnn backend");
299*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
300*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_device_ptr_->Configure() == Error::Ok,
301*523fa7a6SAndroid Build Coastguard Worker Internal,
302*523fa7a6SAndroid Build Coastguard Worker "Fail to configure Qnn device");
303*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
304*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_context_ptr_->Configure() == Error::Ok,
305*523fa7a6SAndroid Build Coastguard Worker Internal,
306*523fa7a6SAndroid Build Coastguard Worker "Fail to configure Qnn context");
307*523fa7a6SAndroid Build Coastguard Worker for (const std::string& graph_name :
308*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_context_ptr_->GetGraphNames()) {
309*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
310*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_graph_ptr_->Configure(graph_name) ==
311*523fa7a6SAndroid Build Coastguard Worker Error::Ok,
312*523fa7a6SAndroid Build Coastguard Worker Internal,
313*523fa7a6SAndroid Build Coastguard Worker "Fail to configure Qnn graph");
314*523fa7a6SAndroid Build Coastguard Worker }
315*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->backend_init_state_ =
316*523fa7a6SAndroid Build Coastguard Worker BackendInitializeState::INITIALIZED;
317*523fa7a6SAndroid Build Coastguard Worker }
318*523fa7a6SAndroid Build Coastguard Worker
319*523fa7a6SAndroid Build Coastguard Worker #if defined(__aarch64__)
320*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
321*523fa7a6SAndroid Build Coastguard Worker PreRegisterMem() == Error::Ok,
322*523fa7a6SAndroid Build Coastguard Worker Internal,
323*523fa7a6SAndroid Build Coastguard Worker "Fail to pre register custom memory handle");
324*523fa7a6SAndroid Build Coastguard Worker #endif
325*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
326*523fa7a6SAndroid Build Coastguard Worker }
327*523fa7a6SAndroid Build Coastguard Worker
AllocateTensor(const std::string & graph_name)328*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::AllocateTensor(const std::string& graph_name) {
329*523fa7a6SAndroid Build Coastguard Worker std::vector<Qnn_Tensor_t> input_tensors =
330*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_context_ptr_->GetGraphInputs(graph_name);
331*523fa7a6SAndroid Build Coastguard Worker std::vector<Qnn_Tensor_t> output_tensors =
332*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_context_ptr_->GetGraphOutputs(graph_name);
333*523fa7a6SAndroid Build Coastguard Worker
334*523fa7a6SAndroid Build Coastguard Worker for (auto& tensor : input_tensors) {
335*523fa7a6SAndroid Build Coastguard Worker std::shared_ptr<TensorWrapper> tensor_wrapper = CreateTensorWrapper(tensor);
336*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->UpdateQnnTensorMeta(tensor);
337*523fa7a6SAndroid Build Coastguard Worker input_tensors_[graph_name].emplace_back(std::move(tensor_wrapper));
338*523fa7a6SAndroid Build Coastguard Worker }
339*523fa7a6SAndroid Build Coastguard Worker if (!options_->is_from_context_binary()) {
340*523fa7a6SAndroid Build Coastguard Worker std::sort(
341*523fa7a6SAndroid Build Coastguard Worker input_tensors_[graph_name].begin(),
342*523fa7a6SAndroid Build Coastguard Worker input_tensors_[graph_name].end(),
343*523fa7a6SAndroid Build Coastguard Worker CompareExportedInput);
344*523fa7a6SAndroid Build Coastguard Worker }
345*523fa7a6SAndroid Build Coastguard Worker for (size_t i = 0; i < output_tensors.size(); ++i) {
346*523fa7a6SAndroid Build Coastguard Worker std::shared_ptr<TensorWrapper> tensor_wrapper =
347*523fa7a6SAndroid Build Coastguard Worker CreateTensorWrapper(output_tensors[i]);
348*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->UpdateQnnTensorMeta(output_tensors[i]);
349*523fa7a6SAndroid Build Coastguard Worker const std::string& tensor_name = tensor_wrapper->GetName();
350*523fa7a6SAndroid Build Coastguard Worker // this is required by identifying shared buffer mechanism
351*523fa7a6SAndroid Build Coastguard Worker // info might be missed if context binary came from qnn_converter
352*523fa7a6SAndroid Build Coastguard Worker if (options_->is_from_context_binary() &&
353*523fa7a6SAndroid Build Coastguard Worker tensor_name.find("output_") == std::string::npos) {
354*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->SetName("output_" + tensor_name);
355*523fa7a6SAndroid Build Coastguard Worker }
356*523fa7a6SAndroid Build Coastguard Worker if (IsTensorDump()) {
357*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->AllocateDataBuffer();
358*523fa7a6SAndroid Build Coastguard Worker }
359*523fa7a6SAndroid Build Coastguard Worker output_tensors_[graph_name].emplace_back(std::move(tensor_wrapper));
360*523fa7a6SAndroid Build Coastguard Worker }
361*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
362*523fa7a6SAndroid Build Coastguard Worker }
363*523fa7a6SAndroid Build Coastguard Worker
AllocateTensor(const std::string & graph_name,std::vector<std::shared_ptr<TensorWrapper>> & inputs,std::vector<std::shared_ptr<TensorWrapper>> & outputs)364*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::AllocateTensor(
365*523fa7a6SAndroid Build Coastguard Worker const std::string& graph_name,
366*523fa7a6SAndroid Build Coastguard Worker std::vector<std::shared_ptr<TensorWrapper>>& inputs,
367*523fa7a6SAndroid Build Coastguard Worker std::vector<std::shared_ptr<TensorWrapper>>& outputs) {
368*523fa7a6SAndroid Build Coastguard Worker input_tensors_[graph_name] = std::move(inputs);
369*523fa7a6SAndroid Build Coastguard Worker // TODO: suuport per-tensor dump in online prepare mode
370*523fa7a6SAndroid Build Coastguard Worker // should be achievable with some pre-process
371*523fa7a6SAndroid Build Coastguard Worker if (!options_->is_from_context_binary()) {
372*523fa7a6SAndroid Build Coastguard Worker std::sort(
373*523fa7a6SAndroid Build Coastguard Worker input_tensors_[graph_name].begin(),
374*523fa7a6SAndroid Build Coastguard Worker input_tensors_[graph_name].end(),
375*523fa7a6SAndroid Build Coastguard Worker CompareExportedInput);
376*523fa7a6SAndroid Build Coastguard Worker }
377*523fa7a6SAndroid Build Coastguard Worker output_tensors_[graph_name] = std::move(outputs);
378*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
379*523fa7a6SAndroid Build Coastguard Worker }
380*523fa7a6SAndroid Build Coastguard Worker
Execute(const std::string & graph_name,const std::vector<Qnn_Tensor_t> & input_tensor_structs,std::vector<Qnn_Tensor_t> & output_tensor_structs,executorch::runtime::EventTracer * event_tracer)381*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::Execute(
382*523fa7a6SAndroid Build Coastguard Worker const std::string& graph_name,
383*523fa7a6SAndroid Build Coastguard Worker const std::vector<Qnn_Tensor_t>& input_tensor_structs,
384*523fa7a6SAndroid Build Coastguard Worker std::vector<Qnn_Tensor_t>& output_tensor_structs,
385*523fa7a6SAndroid Build Coastguard Worker executorch::runtime::EventTracer* event_tracer) {
386*523fa7a6SAndroid Build Coastguard Worker Qnn_ErrorHandle_t error = QNN_SUCCESS;
387*523fa7a6SAndroid Build Coastguard Worker
388*523fa7a6SAndroid Build Coastguard Worker error = backend_params_ptr_->qnn_graph_ptr_->GraphExecute(
389*523fa7a6SAndroid Build Coastguard Worker graph_name, input_tensor_structs, output_tensor_structs);
390*523fa7a6SAndroid Build Coastguard Worker
391*523fa7a6SAndroid Build Coastguard Worker if (error != QNN_SUCCESS) {
392*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_ERROR(
393*523fa7a6SAndroid Build Coastguard Worker "qnn_graph_execute failed. Error %d", QNN_GET_ERROR_CODE(error));
394*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
395*523fa7a6SAndroid Build Coastguard Worker }
396*523fa7a6SAndroid Build Coastguard Worker if (IsTensorDump()) {
397*523fa7a6SAndroid Build Coastguard Worker // TODO: Need to handle the graph which is partitioned.
398*523fa7a6SAndroid Build Coastguard Worker // Maybe we could use graph name.
399*523fa7a6SAndroid Build Coastguard Worker for (std::size_t out_idx = 0; out_idx < output_tensor_structs.size();
400*523fa7a6SAndroid Build Coastguard Worker ++out_idx) {
401*523fa7a6SAndroid Build Coastguard Worker const Qnn_Tensor_t& output_tensor = output_tensor_structs[out_idx];
402*523fa7a6SAndroid Build Coastguard Worker std::vector<executorch::aten::SizesType> sizes(
403*523fa7a6SAndroid Build Coastguard Worker QNN_VER_PTR(output_tensor)->dimensions,
404*523fa7a6SAndroid Build Coastguard Worker QNN_VER_PTR(output_tensor)->dimensions +
405*523fa7a6SAndroid Build Coastguard Worker QNN_VER_PTR(output_tensor)->rank);
406*523fa7a6SAndroid Build Coastguard Worker
407*523fa7a6SAndroid Build Coastguard Worker auto dump_tensor = executorch::extension::from_blob(
408*523fa7a6SAndroid Build Coastguard Worker QNN_VER_PTR(output_tensor)->clientBuf.data,
409*523fa7a6SAndroid Build Coastguard Worker sizes,
410*523fa7a6SAndroid Build Coastguard Worker qnn_dtype_to_scalar_type_[QNN_VER_PTR(output_tensor)->dataType]);
411*523fa7a6SAndroid Build Coastguard Worker
412*523fa7a6SAndroid Build Coastguard Worker executorch::runtime::event_tracer_log_output_delegate<
413*523fa7a6SAndroid Build Coastguard Worker executorch::aten::Tensor>(
414*523fa7a6SAndroid Build Coastguard Worker event_tracer,
415*523fa7a6SAndroid Build Coastguard Worker QNN_VER_PTR(output_tensor)->name,
416*523fa7a6SAndroid Build Coastguard Worker /*delegate_debug_id=*/
417*523fa7a6SAndroid Build Coastguard Worker static_cast<executorch::runtime::DebugHandle>(-1),
418*523fa7a6SAndroid Build Coastguard Worker *dump_tensor);
419*523fa7a6SAndroid Build Coastguard Worker }
420*523fa7a6SAndroid Build Coastguard Worker }
421*523fa7a6SAndroid Build Coastguard Worker
422*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
423*523fa7a6SAndroid Build Coastguard Worker }
424*523fa7a6SAndroid Build Coastguard Worker
ProfileExecuteData(const std::string & graph_name,executorch::runtime::EventTracer * event_tracer)425*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::ProfileExecuteData(
426*523fa7a6SAndroid Build Coastguard Worker const std::string& graph_name,
427*523fa7a6SAndroid Build Coastguard Worker executorch::runtime::EventTracer* event_tracer) {
428*523fa7a6SAndroid Build Coastguard Worker Qnn_ErrorHandle_t error = QNN_SUCCESS;
429*523fa7a6SAndroid Build Coastguard Worker if (options_->profile_level() != QnnExecuTorchProfileLevel::kProfileOff) {
430*523fa7a6SAndroid Build Coastguard Worker error = backend_params_ptr_->qnn_graph_ptr_->ProfileExecuteData(
431*523fa7a6SAndroid Build Coastguard Worker graph_name, event_tracer);
432*523fa7a6SAndroid Build Coastguard Worker if (error != QNN_SUCCESS) {
433*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_ERROR(
434*523fa7a6SAndroid Build Coastguard Worker " Failed to profile. Error %d", QNN_GET_ERROR_CODE(error));
435*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
436*523fa7a6SAndroid Build Coastguard Worker }
437*523fa7a6SAndroid Build Coastguard Worker }
438*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
439*523fa7a6SAndroid Build Coastguard Worker }
440*523fa7a6SAndroid Build Coastguard Worker
Destroy()441*523fa7a6SAndroid Build Coastguard Worker void QnnManager::Destroy() {
442*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_INFO("Destroy Qnn backend parameters");
443*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_.reset(new BackendConfigParameters());
444*523fa7a6SAndroid Build Coastguard Worker logger_.reset();
445*523fa7a6SAndroid Build Coastguard Worker
446*523fa7a6SAndroid Build Coastguard Worker qnn_loaded_backend_.TerminateAllBackends();
447*523fa7a6SAndroid Build Coastguard Worker }
448*523fa7a6SAndroid Build Coastguard Worker
IsNodeSupportedByBackend(std::vector<std::shared_ptr<OpWrapper>> & op_wrappers)449*523fa7a6SAndroid Build Coastguard Worker bool QnnManager::IsNodeSupportedByBackend(
450*523fa7a6SAndroid Build Coastguard Worker std::vector<std::shared_ptr<OpWrapper>>& op_wrappers) {
451*523fa7a6SAndroid Build Coastguard Worker Qnn_ErrorHandle_t error = QNN_SUCCESS;
452*523fa7a6SAndroid Build Coastguard Worker
453*523fa7a6SAndroid Build Coastguard Worker for (std::shared_ptr<OpWrapper>& op_wrapper : op_wrappers) {
454*523fa7a6SAndroid Build Coastguard Worker for (const auto& param : op_wrapper->GetParams()) {
455*523fa7a6SAndroid Build Coastguard Worker // unused?
456*523fa7a6SAndroid Build Coastguard Worker // auto* p_tensor_param = dynamic_cast<TensorParamWrapper*>(param.get());
457*523fa7a6SAndroid Build Coastguard Worker if (param->PopulateQnnParam() != Error::Ok) {
458*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_WARN(
459*523fa7a6SAndroid Build Coastguard Worker "Qnn Backend op validation failed "
460*523fa7a6SAndroid Build Coastguard Worker "with PopulateQnnParam: %d",
461*523fa7a6SAndroid Build Coastguard Worker QNN_GET_ERROR_CODE(error));
462*523fa7a6SAndroid Build Coastguard Worker return false;
463*523fa7a6SAndroid Build Coastguard Worker }
464*523fa7a6SAndroid Build Coastguard Worker }
465*523fa7a6SAndroid Build Coastguard Worker
466*523fa7a6SAndroid Build Coastguard Worker error = backend_params_ptr_->qnn_backend_ptr_->BackendValidateOpConfig(
467*523fa7a6SAndroid Build Coastguard Worker op_wrapper->GetOpConfig());
468*523fa7a6SAndroid Build Coastguard Worker if (error != QNN_SUCCESS) {
469*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_WARN(
470*523fa7a6SAndroid Build Coastguard Worker "Qnn Backend op validation failed with error: %d",
471*523fa7a6SAndroid Build Coastguard Worker QNN_GET_ERROR_CODE(error));
472*523fa7a6SAndroid Build Coastguard Worker
473*523fa7a6SAndroid Build Coastguard Worker return false;
474*523fa7a6SAndroid Build Coastguard Worker }
475*523fa7a6SAndroid Build Coastguard Worker }
476*523fa7a6SAndroid Build Coastguard Worker return true;
477*523fa7a6SAndroid Build Coastguard Worker }
478*523fa7a6SAndroid Build Coastguard Worker
GetContextBinary(QnnExecuTorchContextBinary & qnn_executorch_context_binary)479*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::GetContextBinary(
480*523fa7a6SAndroid Build Coastguard Worker QnnExecuTorchContextBinary& qnn_executorch_context_binary) {
481*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
482*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_context_ptr_->GetContextBinary(
483*523fa7a6SAndroid Build Coastguard Worker qnn_executorch_context_binary) == Error::Ok,
484*523fa7a6SAndroid Build Coastguard Worker Internal,
485*523fa7a6SAndroid Build Coastguard Worker "Fail to get context binary.");
486*523fa7a6SAndroid Build Coastguard Worker
487*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
488*523fa7a6SAndroid Build Coastguard Worker }
489*523fa7a6SAndroid Build Coastguard Worker
CompileQcir()490*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::CompileQcir() {
491*523fa7a6SAndroid Build Coastguard Worker flatbuffers::Verifier verifier_binary_info(
492*523fa7a6SAndroid Build Coastguard Worker static_cast<const uint8_t* const>(qnn_context_blob_.buffer),
493*523fa7a6SAndroid Build Coastguard Worker qnn_context_blob_.nbytes);
494*523fa7a6SAndroid Build Coastguard Worker if (!qnn_delegate::VerifyBinaryInfoBuffer(verifier_binary_info)) {
495*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_ERROR("Fail to verify binary info");
496*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
497*523fa7a6SAndroid Build Coastguard Worker }
498*523fa7a6SAndroid Build Coastguard Worker
499*523fa7a6SAndroid Build Coastguard Worker auto binary_info = qnn_delegate::GetBinaryInfo(qnn_context_blob_.buffer);
500*523fa7a6SAndroid Build Coastguard Worker flatbuffers::Verifier verifier_qcir(
501*523fa7a6SAndroid Build Coastguard Worker binary_info->data()->data(), binary_info->data()->size());
502*523fa7a6SAndroid Build Coastguard Worker if (!qcir::VerifyContextBuffer(verifier_qcir)) {
503*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_ERROR("Fail to verify qcir format");
504*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
505*523fa7a6SAndroid Build Coastguard Worker }
506*523fa7a6SAndroid Build Coastguard Worker
507*523fa7a6SAndroid Build Coastguard Worker auto context = qcir::GetContext(binary_info->data()->data());
508*523fa7a6SAndroid Build Coastguard Worker for (const auto& graph : *context->graphs()) {
509*523fa7a6SAndroid Build Coastguard Worker // qcir tensors to TensorWrapper
510*523fa7a6SAndroid Build Coastguard Worker std::vector<std::shared_ptr<TensorWrapper>> graph_inputs, graph_outputs,
511*523fa7a6SAndroid Build Coastguard Worker tensors;
512*523fa7a6SAndroid Build Coastguard Worker for (const auto& tensor : *graph->tensors()) {
513*523fa7a6SAndroid Build Coastguard Worker tensors.emplace_back(CreateTensorWrapper(ToTensor(tensor)));
514*523fa7a6SAndroid Build Coastguard Worker if (tensor->type() == qcir::TensorType::WRITE) {
515*523fa7a6SAndroid Build Coastguard Worker graph_inputs.push_back(tensors.back());
516*523fa7a6SAndroid Build Coastguard Worker } else if (tensor->type() == qcir::TensorType::READ) {
517*523fa7a6SAndroid Build Coastguard Worker graph_outputs.push_back(tensors.back());
518*523fa7a6SAndroid Build Coastguard Worker }
519*523fa7a6SAndroid Build Coastguard Worker }
520*523fa7a6SAndroid Build Coastguard Worker std::vector<std::shared_ptr<OpWrapper>> op_wrappers;
521*523fa7a6SAndroid Build Coastguard Worker // qcir graph node to OpWrapper
522*523fa7a6SAndroid Build Coastguard Worker for (const auto& node : *graph->nodes()) {
523*523fa7a6SAndroid Build Coastguard Worker std::shared_ptr<OpWrapper> op = std::make_shared<OpWrapper>(
524*523fa7a6SAndroid Build Coastguard Worker node->name()->str(),
525*523fa7a6SAndroid Build Coastguard Worker node->package_name()->str(),
526*523fa7a6SAndroid Build Coastguard Worker node->type_name()->str());
527*523fa7a6SAndroid Build Coastguard Worker
528*523fa7a6SAndroid Build Coastguard Worker // qcir input tensors to OpWrapper input tensors
529*523fa7a6SAndroid Build Coastguard Worker std::vector<std::shared_ptr<TensorWrapper>> inputs;
530*523fa7a6SAndroid Build Coastguard Worker for (uint32_t index : *node->inputs()) {
531*523fa7a6SAndroid Build Coastguard Worker inputs.push_back(tensors[index]);
532*523fa7a6SAndroid Build Coastguard Worker }
533*523fa7a6SAndroid Build Coastguard Worker op->AddInputTensors(inputs);
534*523fa7a6SAndroid Build Coastguard Worker
535*523fa7a6SAndroid Build Coastguard Worker // qcir output tensors to OpWrapper output tensors
536*523fa7a6SAndroid Build Coastguard Worker std::vector<std::shared_ptr<TensorWrapper>> outputs;
537*523fa7a6SAndroid Build Coastguard Worker for (uint32_t index : *node->outputs()) {
538*523fa7a6SAndroid Build Coastguard Worker outputs.push_back(tensors[index]);
539*523fa7a6SAndroid Build Coastguard Worker }
540*523fa7a6SAndroid Build Coastguard Worker op->AddOutputTensors(outputs);
541*523fa7a6SAndroid Build Coastguard Worker
542*523fa7a6SAndroid Build Coastguard Worker // qcir operator param to OpWrapper param
543*523fa7a6SAndroid Build Coastguard Worker for (uint32_t index : *node->params()) {
544*523fa7a6SAndroid Build Coastguard Worker const auto& tensor = graph->tensors()->Get(index);
545*523fa7a6SAndroid Build Coastguard Worker std::string name = tensor->name()->str();
546*523fa7a6SAndroid Build Coastguard Worker Qnn_DataType_t dtype = ToDataType(tensor->dtype());
547*523fa7a6SAndroid Build Coastguard Worker if (tensor->shape()->size() != 0) {
548*523fa7a6SAndroid Build Coastguard Worker // add tensor param
549*523fa7a6SAndroid Build Coastguard Worker op->AddTensorParam(
550*523fa7a6SAndroid Build Coastguard Worker name,
551*523fa7a6SAndroid Build Coastguard Worker dtype,
552*523fa7a6SAndroid Build Coastguard Worker tensor->shape()->size(),
553*523fa7a6SAndroid Build Coastguard Worker tensor->shape()->data(),
554*523fa7a6SAndroid Build Coastguard Worker tensor->data()->data());
555*523fa7a6SAndroid Build Coastguard Worker } else {
556*523fa7a6SAndroid Build Coastguard Worker // add scalar param
557*523fa7a6SAndroid Build Coastguard Worker switch (dtype) {
558*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_INT_32:
559*523fa7a6SAndroid Build Coastguard Worker op->AddScalarParam(
560*523fa7a6SAndroid Build Coastguard Worker name,
561*523fa7a6SAndroid Build Coastguard Worker dtype,
562*523fa7a6SAndroid Build Coastguard Worker *reinterpret_cast<const int32_t*>(tensor->data()->Data()));
563*523fa7a6SAndroid Build Coastguard Worker break;
564*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_INT_16:
565*523fa7a6SAndroid Build Coastguard Worker op->AddScalarParam(
566*523fa7a6SAndroid Build Coastguard Worker name,
567*523fa7a6SAndroid Build Coastguard Worker dtype,
568*523fa7a6SAndroid Build Coastguard Worker *reinterpret_cast<const int16_t*>(tensor->data()->Data()));
569*523fa7a6SAndroid Build Coastguard Worker break;
570*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_INT_8:
571*523fa7a6SAndroid Build Coastguard Worker op->AddScalarParam(
572*523fa7a6SAndroid Build Coastguard Worker name, dtype, static_cast<int8_t>(*tensor->data()->Data()));
573*523fa7a6SAndroid Build Coastguard Worker break;
574*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_UINT_32:
575*523fa7a6SAndroid Build Coastguard Worker op->AddScalarParam(
576*523fa7a6SAndroid Build Coastguard Worker name,
577*523fa7a6SAndroid Build Coastguard Worker dtype,
578*523fa7a6SAndroid Build Coastguard Worker *reinterpret_cast<const uint32_t*>(tensor->data()->Data()));
579*523fa7a6SAndroid Build Coastguard Worker break;
580*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_UINT_16:
581*523fa7a6SAndroid Build Coastguard Worker op->AddScalarParam(
582*523fa7a6SAndroid Build Coastguard Worker name,
583*523fa7a6SAndroid Build Coastguard Worker dtype,
584*523fa7a6SAndroid Build Coastguard Worker *reinterpret_cast<const uint16_t*>(tensor->data()->Data()));
585*523fa7a6SAndroid Build Coastguard Worker break;
586*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_UINT_8:
587*523fa7a6SAndroid Build Coastguard Worker op->AddScalarParam(name, dtype, *tensor->data()->Data());
588*523fa7a6SAndroid Build Coastguard Worker break;
589*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_FLOAT_32:
590*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_FLOAT_16:
591*523fa7a6SAndroid Build Coastguard Worker op->AddScalarParam(
592*523fa7a6SAndroid Build Coastguard Worker name,
593*523fa7a6SAndroid Build Coastguard Worker dtype,
594*523fa7a6SAndroid Build Coastguard Worker *reinterpret_cast<const float*>(tensor->data()->Data()));
595*523fa7a6SAndroid Build Coastguard Worker break;
596*523fa7a6SAndroid Build Coastguard Worker case Qnn_DataType_t::QNN_DATATYPE_BOOL_8:
597*523fa7a6SAndroid Build Coastguard Worker op->AddScalarParam(name, dtype, *tensor->data()->Data());
598*523fa7a6SAndroid Build Coastguard Worker break;
599*523fa7a6SAndroid Build Coastguard Worker default:
600*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_ERROR(
601*523fa7a6SAndroid Build Coastguard Worker "Invalid scalar type: %s", tensor->name()->c_str());
602*523fa7a6SAndroid Build Coastguard Worker break;
603*523fa7a6SAndroid Build Coastguard Worker }
604*523fa7a6SAndroid Build Coastguard Worker }
605*523fa7a6SAndroid Build Coastguard Worker }
606*523fa7a6SAndroid Build Coastguard Worker op_wrappers.push_back(std::move(op));
607*523fa7a6SAndroid Build Coastguard Worker }
608*523fa7a6SAndroid Build Coastguard Worker
609*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
610*523fa7a6SAndroid Build Coastguard Worker Compile(graph->name()->str(), op_wrappers) == Error::Ok,
611*523fa7a6SAndroid Build Coastguard Worker Internal,
612*523fa7a6SAndroid Build Coastguard Worker "Fail to compile graph from qcir with graph_name: %s",
613*523fa7a6SAndroid Build Coastguard Worker graph->name()->str().c_str());
614*523fa7a6SAndroid Build Coastguard Worker
615*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
616*523fa7a6SAndroid Build Coastguard Worker AllocateTensor(graph->name()->str(), graph_inputs, graph_outputs) ==
617*523fa7a6SAndroid Build Coastguard Worker Error::Ok,
618*523fa7a6SAndroid Build Coastguard Worker Internal,
619*523fa7a6SAndroid Build Coastguard Worker "Fail to allocate tensor for qcir with graph_name: %s",
620*523fa7a6SAndroid Build Coastguard Worker graph->name()->str().c_str());
621*523fa7a6SAndroid Build Coastguard Worker }
622*523fa7a6SAndroid Build Coastguard Worker
623*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
624*523fa7a6SAndroid Build Coastguard Worker }
625*523fa7a6SAndroid Build Coastguard Worker
Compile(const std::string & graph_name,std::vector<std::shared_ptr<OpWrapper>> & op_wrappers)626*523fa7a6SAndroid Build Coastguard Worker Error QnnManager::Compile(
627*523fa7a6SAndroid Build Coastguard Worker const std::string& graph_name,
628*523fa7a6SAndroid Build Coastguard Worker std::vector<std::shared_ptr<OpWrapper>>& op_wrappers) {
629*523fa7a6SAndroid Build Coastguard Worker Qnn_ErrorHandle_t error = QNN_SUCCESS;
630*523fa7a6SAndroid Build Coastguard Worker
631*523fa7a6SAndroid Build Coastguard Worker for (std::shared_ptr<OpWrapper>& op_wrapper : op_wrappers) {
632*523fa7a6SAndroid Build Coastguard Worker for (const auto& tensor_wrapper : op_wrapper->GetInputTensors()) {
633*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
634*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_graph_ptr_->EnsureTensorInQnnGraph(
635*523fa7a6SAndroid Build Coastguard Worker graph_name, tensor_wrapper) == Error::Ok,
636*523fa7a6SAndroid Build Coastguard Worker Internal,
637*523fa7a6SAndroid Build Coastguard Worker "Tensor name %s isn't added to Qnn Graph",
638*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetName().c_str());
639*523fa7a6SAndroid Build Coastguard Worker }
640*523fa7a6SAndroid Build Coastguard Worker
641*523fa7a6SAndroid Build Coastguard Worker for (const auto& tensor_wrapper : op_wrapper->GetOutputTensors()) {
642*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
643*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_graph_ptr_->EnsureTensorInQnnGraph(
644*523fa7a6SAndroid Build Coastguard Worker graph_name, tensor_wrapper) == Error::Ok,
645*523fa7a6SAndroid Build Coastguard Worker Internal,
646*523fa7a6SAndroid Build Coastguard Worker "Tensor name %s isn't added to Qnn Graph",
647*523fa7a6SAndroid Build Coastguard Worker tensor_wrapper->GetName().c_str());
648*523fa7a6SAndroid Build Coastguard Worker }
649*523fa7a6SAndroid Build Coastguard Worker
650*523fa7a6SAndroid Build Coastguard Worker for (const auto& param : op_wrapper->GetParams()) {
651*523fa7a6SAndroid Build Coastguard Worker auto* p_tensor_param = dynamic_cast<TensorParamWrapper*>(param.get());
652*523fa7a6SAndroid Build Coastguard Worker if (p_tensor_param != nullptr) {
653*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
654*523fa7a6SAndroid Build Coastguard Worker backend_params_ptr_->qnn_graph_ptr_->EnsureTensorInQnnGraph(
655*523fa7a6SAndroid Build Coastguard Worker graph_name, p_tensor_param->GetTensorWrapper()) == Error::Ok,
656*523fa7a6SAndroid Build Coastguard Worker Internal,
657*523fa7a6SAndroid Build Coastguard Worker "Param tensor name %s isn't added to Qnn Graph",
658*523fa7a6SAndroid Build Coastguard Worker p_tensor_param->GetName().c_str());
659*523fa7a6SAndroid Build Coastguard Worker }
660*523fa7a6SAndroid Build Coastguard Worker ET_CHECK_OR_RETURN_ERROR(
661*523fa7a6SAndroid Build Coastguard Worker param->PopulateQnnParam() == Error::Ok,
662*523fa7a6SAndroid Build Coastguard Worker Internal,
663*523fa7a6SAndroid Build Coastguard Worker "Fail to configure Qnn backend");
664*523fa7a6SAndroid Build Coastguard Worker }
665*523fa7a6SAndroid Build Coastguard Worker
666*523fa7a6SAndroid Build Coastguard Worker error = backend_params_ptr_->qnn_graph_ptr_->GraphAddNode(
667*523fa7a6SAndroid Build Coastguard Worker graph_name, op_wrapper->GetOpConfig());
668*523fa7a6SAndroid Build Coastguard Worker if (error != QNN_SUCCESS) {
669*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_ERROR(
670*523fa7a6SAndroid Build Coastguard Worker "Failed to add node to Qnn Graph with error: %d",
671*523fa7a6SAndroid Build Coastguard Worker QNN_GET_ERROR_CODE(error));
672*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
673*523fa7a6SAndroid Build Coastguard Worker }
674*523fa7a6SAndroid Build Coastguard Worker }
675*523fa7a6SAndroid Build Coastguard Worker
676*523fa7a6SAndroid Build Coastguard Worker error = backend_params_ptr_->qnn_graph_ptr_->GraphFinalize(graph_name);
677*523fa7a6SAndroid Build Coastguard Worker if (error != QNN_SUCCESS) {
678*523fa7a6SAndroid Build Coastguard Worker QNN_EXECUTORCH_LOG_ERROR(
679*523fa7a6SAndroid Build Coastguard Worker "Failed to finalize Qnn Graph with error: %d",
680*523fa7a6SAndroid Build Coastguard Worker QNN_GET_ERROR_CODE(error));
681*523fa7a6SAndroid Build Coastguard Worker return Error::Internal;
682*523fa7a6SAndroid Build Coastguard Worker }
683*523fa7a6SAndroid Build Coastguard Worker
684*523fa7a6SAndroid Build Coastguard Worker return Error::Ok;
685*523fa7a6SAndroid Build Coastguard Worker }
686*523fa7a6SAndroid Build Coastguard Worker
GetBinarySignature()687*523fa7a6SAndroid Build Coastguard Worker std::string QnnManager::GetBinarySignature() {
688*523fa7a6SAndroid Build Coastguard Worker flatbuffers::Verifier verifier(
689*523fa7a6SAndroid Build Coastguard Worker static_cast<const uint8_t* const>(qnn_context_blob_.buffer),
690*523fa7a6SAndroid Build Coastguard Worker qnn_context_blob_.nbytes);
691*523fa7a6SAndroid Build Coastguard Worker return VerifyBinaryInfoBuffer(verifier)
692*523fa7a6SAndroid Build Coastguard Worker ? GetBinaryInfo(qnn_context_blob_.buffer)->signature()->str()
693*523fa7a6SAndroid Build Coastguard Worker : "";
694*523fa7a6SAndroid Build Coastguard Worker }
695*523fa7a6SAndroid Build Coastguard Worker
696*523fa7a6SAndroid Build Coastguard Worker } // namespace qnn
697*523fa7a6SAndroid Build Coastguard Worker } // namespace backends
698*523fa7a6SAndroid Build Coastguard Worker } // namespace executorch
QnnExecuTorchAllocCustomMem(size_t bytes,size_t alignment)699*523fa7a6SAndroid Build Coastguard Worker void* QnnExecuTorchAllocCustomMem(size_t bytes, size_t alignment) {
700*523fa7a6SAndroid Build Coastguard Worker void* buffer_ptr =
701*523fa7a6SAndroid Build Coastguard Worker executorch::backends::qnn::SharedBuffer::GetSharedBufferManager()
702*523fa7a6SAndroid Build Coastguard Worker .AllocMem(bytes, alignment);
703*523fa7a6SAndroid Build Coastguard Worker return buffer_ptr;
704*523fa7a6SAndroid Build Coastguard Worker }
705*523fa7a6SAndroid Build Coastguard Worker
QnnExecuTorchFreeCustomMem(void * buffer_ptr)706*523fa7a6SAndroid Build Coastguard Worker void QnnExecuTorchFreeCustomMem(void* buffer_ptr) {
707*523fa7a6SAndroid Build Coastguard Worker executorch::backends::qnn::SharedBuffer::GetSharedBufferManager().FreeMem(
708*523fa7a6SAndroid Build Coastguard Worker buffer_ptr);
709*523fa7a6SAndroid Build Coastguard Worker }
710*523fa7a6SAndroid Build Coastguard Worker
QnnExecuTorchAddCustomMemTensorAddr(void * tensor_addr,void * custom_mem)711*523fa7a6SAndroid Build Coastguard Worker void QnnExecuTorchAddCustomMemTensorAddr(void* tensor_addr, void* custom_mem) {
712*523fa7a6SAndroid Build Coastguard Worker executorch::backends::qnn::SharedBuffer::GetSharedBufferManager()
713*523fa7a6SAndroid Build Coastguard Worker .AddCusomMemTensorAddr(tensor_addr, custom_mem);
714*523fa7a6SAndroid Build Coastguard Worker }
715*523fa7a6SAndroid Build Coastguard Worker
QnnExecuTorchAddCustomMemTensorInfo(const CustomMemTensorInfo & info)716*523fa7a6SAndroid Build Coastguard Worker void QnnExecuTorchAddCustomMemTensorInfo(const CustomMemTensorInfo& info) {
717*523fa7a6SAndroid Build Coastguard Worker executorch::backends::qnn::SharedBuffer::GetSharedBufferManager()
718*523fa7a6SAndroid Build Coastguard Worker .AddCusomMemTensorInfo(info);
719*523fa7a6SAndroid Build Coastguard Worker }
720