blob: 38f1bc20087a1f9eaebbc4134d2cc593a3028cb7 [file] [log] [blame]
telsoa015307bc12018-03-09 13:51:08 +00001//
Mike Kellye2d611e2021-10-14 12:35:58 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
David Beck93e48982018-09-05 13:05:09 +01003// SPDX-License-Identifier: MIT
telsoa015307bc12018-03-09 13:51:08 +00004//
5
6#define LOG_TAG "ArmnnDriver"
7
8#include "ArmnnPreparedModel.hpp"
9#include "Utils.hpp"
10
telsoa015307bc12018-03-09 13:51:08 +000011#include <log/log.h>
12#include <OperationsUtils.h>
surmeh01deb3bdb2018-07-05 12:06:04 +010013#include <ValidateHal.h>
Kevin Mayec1e5b82020-02-26 17:00:39 +000014
telsoa015307bc12018-03-09 13:51:08 +000015#include <cinttypes>
16
Sadik Armagan188675f2021-02-12 17:16:42 +000017#ifdef ARMNN_ANDROID_S
18#include <LegacyUtils.h>
19#endif
20
telsoa015307bc12018-03-09 13:51:08 +000021using namespace android;
22
23namespace
24{
25using namespace armnn_driver;
26
Kevin Mayec1e5b82020-02-26 17:00:39 +000027void NotifyCallbackAndCheck(const ::android::sp<V1_0::IExecutionCallback>& callback, V1_0::ErrorStatus errorStatus,
telsoa015307bc12018-03-09 13:51:08 +000028 std::string callingFunction)
29{
30 Return<void> returned = callback->notify(errorStatus);
31 // This check is required, if the callback fails and it isn't checked it will bring down the service
32 if (!returned.isOk())
33 {
34 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
35 callingFunction.c_str(), returned.description().c_str());
36 }
37}
38
Sadik Armagan188675f2021-02-12 17:16:42 +000039bool ValidateRequestArgument(const V1_0::RequestArgument& requestArg, const armnn::TensorInfo& tensorInfo)
telsoa015307bc12018-03-09 13:51:08 +000040{
41 if (requestArg.dimensions.size() != 0)
42 {
43 if (requestArg.dimensions.size() != tensorInfo.GetNumDimensions())
44 {
45 ALOGE("Mismatched dimensions (request argument: %zu, expected: %u)",
46 requestArg.dimensions.size(), tensorInfo.GetNumDimensions());
47 return false;
48 }
49
50 for (unsigned int d = 0; d < tensorInfo.GetNumDimensions(); ++d)
51 {
Finn Williamsa4983ce2020-07-23 12:55:12 +010052 if (requestArg.dimensions[d] != 0 && requestArg.dimensions[d] != tensorInfo.GetShape()[d])
telsoa015307bc12018-03-09 13:51:08 +000053 {
54 ALOGE("Mismatched size for dimension %d (request argument: %u, expected %u)",
55 d, requestArg.dimensions[d], tensorInfo.GetShape()[d]);
56 return false;
57 }
58 }
59 }
60
61 return true;
62}
63
Sadik Armagan188675f2021-02-12 17:16:42 +000064armnn::Tensor GetTensorForRequestArgument(const V1_0::RequestArgument& requestArg,
telsoa015307bc12018-03-09 13:51:08 +000065 const armnn::TensorInfo& tensorInfo,
66 const std::vector<::android::nn::RunTimePoolInfo>& requestPools)
67{
68 if (!ValidateRequestArgument(requestArg, tensorInfo))
69 {
70 return armnn::Tensor();
71 }
72
73 return armnn::Tensor(tensorInfo, GetMemoryFromPool(requestArg.location, requestPools));
74}
75
76inline std::string BuildTensorName(const char* tensorNamePrefix, std::size_t index)
77{
78 return tensorNamePrefix + std::to_string(index);
79}
80
Matteo Martincighe48bdff2018-09-03 13:50:50 +010081} // anonymous namespace
telsoa015307bc12018-03-09 13:51:08 +000082
telsoa01ce3e84a2018-08-31 09:31:35 +010083using namespace android::hardware;
84
telsoa015307bc12018-03-09 13:51:08 +000085namespace armnn_driver
86{
Matteo Martincighe48bdff2018-09-03 13:50:50 +010087template<typename HalVersion>
Derek Lamberti4de83c52020-03-17 13:40:18 +000088RequestThread<ArmnnPreparedModel, HalVersion, CallbackContext_1_0>
89 ArmnnPreparedModel<HalVersion>::m_RequestThread;
telsoa015307bc12018-03-09 13:51:08 +000090
Matteo Martincighe48bdff2018-09-03 13:50:50 +010091template<typename HalVersion>
Finn Williamsfdf2eae2021-07-08 13:07:19 +010092std::unique_ptr<armnn::Threadpool> ArmnnPreparedModel<HalVersion>::m_Threadpool(nullptr);
93
94template<typename HalVersion>
telsoa015307bc12018-03-09 13:51:08 +000095template <typename TensorBindingCollection>
Matteo Martincighe48bdff2018-09-03 13:50:50 +010096void ArmnnPreparedModel<HalVersion>::DumpTensorsIfRequired(char const* tensorNamePrefix,
97 const TensorBindingCollection& tensorBindings)
telsoa015307bc12018-03-09 13:51:08 +000098{
99 if (!m_RequestInputsAndOutputsDumpDir.empty())
100 {
Colm Donelan08d9a1c2020-09-09 17:56:55 +0100101 const std::string requestName = std::to_string(m_NetworkId) + "_" + std::to_string(m_RequestCount) + ".dump";
telsoa015307bc12018-03-09 13:51:08 +0000102 for (std::size_t i = 0u; i < tensorBindings.size(); ++i)
103 {
104 DumpTensor(m_RequestInputsAndOutputsDumpDir,
105 requestName,
106 BuildTensorName(tensorNamePrefix, i),
107 tensorBindings[i].second);
108 }
109 }
110}
111
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100112template<typename HalVersion>
113ArmnnPreparedModel<HalVersion>::ArmnnPreparedModel(armnn::NetworkId networkId,
114 armnn::IRuntime* runtime,
115 const HalModel& model,
116 const std::string& requestInputsAndOutputsDumpDir,
Finn Williamsd8fb5402021-05-19 20:52:00 +0100117 const bool gpuProfilingEnabled,
Finn Williamsca3a3e02021-06-11 15:04:02 +0100118 const bool asyncModelExecutionEnabled,
119 const unsigned int numberOfThreads)
telsoa01ce3e84a2018-08-31 09:31:35 +0100120 : m_NetworkId(networkId)
121 , m_Runtime(runtime)
122 , m_Model(model)
123 , m_RequestCount(0)
124 , m_RequestInputsAndOutputsDumpDir(requestInputsAndOutputsDumpDir)
125 , m_GpuProfilingEnabled(gpuProfilingEnabled)
Finn Williamsd8fb5402021-05-19 20:52:00 +0100126 , m_AsyncModelExecutionEnabled(asyncModelExecutionEnabled)
telsoa015307bc12018-03-09 13:51:08 +0000127{
telsoa01ce3e84a2018-08-31 09:31:35 +0100128 // Enable profiling if required.
129 m_Runtime->GetProfiler(m_NetworkId)->EnableProfiling(m_GpuProfilingEnabled);
Finn Williamsd8fb5402021-05-19 20:52:00 +0100130
Finn Williamsfdf2eae2021-07-08 13:07:19 +0100131 if (m_AsyncModelExecutionEnabled)
Finn Williamsd8fb5402021-05-19 20:52:00 +0100132 {
Finn Williamsca3a3e02021-06-11 15:04:02 +0100133 std::vector<std::shared_ptr<armnn::IWorkingMemHandle>> memHandles;
Finn Williamsd27c13b2021-06-25 10:06:09 +0100134 for (unsigned int i=0; i < numberOfThreads; ++i)
Finn Williamsca3a3e02021-06-11 15:04:02 +0100135 {
136 memHandles.emplace_back(m_Runtime->CreateWorkingMemHandle(networkId));
137 }
138
Finn Williamsfdf2eae2021-07-08 13:07:19 +0100139 if (!m_Threadpool)
140 {
141 m_Threadpool = std::make_unique<armnn::Threadpool>(numberOfThreads, runtime, memHandles);
142 }
143 else
144 {
145 m_Threadpool->LoadMemHandles(memHandles);
146 }
147
Finn Williamsca3a3e02021-06-11 15:04:02 +0100148 m_WorkingMemHandle = memHandles.back();
Finn Williamsd8fb5402021-05-19 20:52:00 +0100149 }
telsoa015307bc12018-03-09 13:51:08 +0000150}
151
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100152template<typename HalVersion>
153ArmnnPreparedModel<HalVersion>::~ArmnnPreparedModel()
telsoa015307bc12018-03-09 13:51:08 +0000154{
telsoa01ce3e84a2018-08-31 09:31:35 +0100155 // Get a hold of the profiler used by this model.
156 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
Colm Donelan12396f72022-02-15 14:59:08 +0000157 if (profiler && m_GpuProfilingEnabled)
158 {
159 // Dump the profiling info to a file if required.
160 DumpJsonProfilingIfRequired(m_GpuProfilingEnabled, m_RequestInputsAndOutputsDumpDir, m_NetworkId,
161 profiler.get());
162 }
telsoa01ce3e84a2018-08-31 09:31:35 +0100163
164 // Unload the network associated with this model.
telsoa015307bc12018-03-09 13:51:08 +0000165 m_Runtime->UnloadNetwork(m_NetworkId);
telsoa01ce3e84a2018-08-31 09:31:35 +0100166
Finn Williamsfdf2eae2021-07-08 13:07:19 +0100167 // Unload the network memhandles from the threadpool
168 if (m_AsyncModelExecutionEnabled)
169 {
170 m_Threadpool->UnloadMemHandles(m_NetworkId);
171 }
telsoa015307bc12018-03-09 13:51:08 +0000172}
173
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100174template<typename HalVersion>
Kevin Mayec1e5b82020-02-26 17:00:39 +0000175Return<V1_0::ErrorStatus> ArmnnPreparedModel<HalVersion>::execute(
176 const V1_0::Request& request,
177 const ::android::sp<V1_0::IExecutionCallback>& callback)
telsoa015307bc12018-03-09 13:51:08 +0000178{
179 ALOGV("ArmnnPreparedModel::execute(): %s", GetModelSummary(m_Model).c_str());
180 m_RequestCount++;
181
182 if (callback.get() == nullptr) {
183 ALOGE("ArmnnPreparedModel::execute invalid callback passed");
Kevin Mayec1e5b82020-02-26 17:00:39 +0000184 return V1_0::ErrorStatus::INVALID_ARGUMENT;
telsoa015307bc12018-03-09 13:51:08 +0000185 }
186
187 if (!android::nn::validateRequest(request, m_Model))
188 {
Kevin Mayec1e5b82020-02-26 17:00:39 +0000189 NotifyCallbackAndCheck(callback, V1_0::ErrorStatus::INVALID_ARGUMENT, "ArmnnPreparedModel::execute");
190 return V1_0::ErrorStatus::INVALID_ARGUMENT;
telsoa015307bc12018-03-09 13:51:08 +0000191 }
192
193 if (!m_RequestInputsAndOutputsDumpDir.empty())
194 {
195 ALOGD("Dumping inputs and outputs for request %" PRIuPTR, reinterpret_cast<std::uintptr_t>(callback.get()));
196 }
197
198 // allocate the tensors on the heap, as they are passed to the request thread
199 auto pInputTensors = std::make_shared<armnn::InputTensors>();
200 auto pOutputTensors = std::make_shared<armnn::OutputTensors>();
201
202 // map the memory pool into shared pointers
203 // use a shared memory pools vector on the heap, as it is passed to the request thread
204 auto pMemPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
Sadik Armagan188675f2021-02-12 17:16:42 +0000205#if !defined(ARMNN_ANDROID_S)
telsoa015307bc12018-03-09 13:51:08 +0000206 if (!setRunTimePoolInfosFromHidlMemories(pMemPools.get(), request.pools))
Sadik Armagan188675f2021-02-12 17:16:42 +0000207#else
208 if (!setRunTimePoolInfosFromCanonicalMemories(pMemPools.get(), uncheckedConvert(request.pools)))
209#endif
telsoa015307bc12018-03-09 13:51:08 +0000210 {
Kevin Mayec1e5b82020-02-26 17:00:39 +0000211 NotifyCallbackAndCheck(callback, V1_0::ErrorStatus::GENERAL_FAILURE, "ArmnnPreparedModel::execute");
212 return V1_0::ErrorStatus::GENERAL_FAILURE;
telsoa015307bc12018-03-09 13:51:08 +0000213 }
telsoa015307bc12018-03-09 13:51:08 +0000214 // add the inputs and outputs with their data
215 try
216 {
217 pInputTensors->reserve(request.inputs.size());
218 for (unsigned int i = 0; i < request.inputs.size(); i++)
219 {
220 const auto& inputArg = request.inputs[i];
221
Cathal Corbette27d4e82021-10-28 12:28:35 +0100222 armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
223 // pInputTensors (of type InputTensors) is composed of a vector of ConstTensors.
224 // Therefore, set all TensorInfo isConstant parameters of input Tensors to true.
225 inputTensorInfo.SetConstant();
telsoa015307bc12018-03-09 13:51:08 +0000226 const armnn::Tensor inputTensor = GetTensorForRequestArgument(inputArg, inputTensorInfo, *pMemPools);
227 if (inputTensor.GetMemoryArea() == nullptr)
228 {
229 ALOGE("Cannot execute request. Error converting request input %u to tensor", i);
Kevin Mayec1e5b82020-02-26 17:00:39 +0000230 return V1_0::ErrorStatus::GENERAL_FAILURE;
telsoa015307bc12018-03-09 13:51:08 +0000231 }
232
233 pInputTensors->emplace_back(i, inputTensor);
234 }
235
236 pOutputTensors->reserve(request.outputs.size());
237 for (unsigned int i = 0; i < request.outputs.size(); i++)
238 {
239 const auto& outputArg = request.outputs[i];
240
241 const armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
242 const armnn::Tensor outputTensor = GetTensorForRequestArgument(outputArg, outputTensorInfo, *pMemPools);
243 if (outputTensor.GetMemoryArea() == nullptr)
244 {
245 ALOGE("Cannot execute request. Error converting request output %u to tensor", i);
Kevin Mayec1e5b82020-02-26 17:00:39 +0000246 return V1_0::ErrorStatus::GENERAL_FAILURE;
telsoa015307bc12018-03-09 13:51:08 +0000247 }
248
249 pOutputTensors->emplace_back(i, outputTensor);
250 }
251 }
Kevin May7bdaac52020-02-10 12:10:07 +0000252 catch (armnn::Exception& e)
253 {
254 ALOGW("armnn::Exception caught while preparing for EnqueueWorkload: %s", e.what());
Kevin Mayec1e5b82020-02-26 17:00:39 +0000255 NotifyCallbackAndCheck(callback, V1_0::ErrorStatus::GENERAL_FAILURE, "ArmnnPreparedModel::execute");
256 return V1_0::ErrorStatus::GENERAL_FAILURE;
Kevin May7bdaac52020-02-10 12:10:07 +0000257 }
Derek Lambertib9cb8442019-11-28 13:34:48 +0000258 catch (std::exception& e)
telsoa015307bc12018-03-09 13:51:08 +0000259 {
Kevin May7bdaac52020-02-10 12:10:07 +0000260 ALOGE("std::exception caught while preparing for EnqueueWorkload: %s", e.what());
Kevin Mayec1e5b82020-02-26 17:00:39 +0000261 NotifyCallbackAndCheck(callback, V1_0::ErrorStatus::GENERAL_FAILURE, "ArmnnPreparedModel::execute");
262 return V1_0::ErrorStatus::GENERAL_FAILURE;
telsoa015307bc12018-03-09 13:51:08 +0000263 }
264
Kevin Mayec1e5b82020-02-26 17:00:39 +0000265 auto cb = [callback](V1_0::ErrorStatus errorStatus, std::string callingFunction)
Mike Kelly65c42dc2019-07-22 14:06:00 +0100266 {
267 NotifyCallbackAndCheck(callback, errorStatus, callingFunction);
268 };
269
Derek Lamberti4de83c52020-03-17 13:40:18 +0000270 CallbackContext_1_0 armnnCb;
Mike Kelly65c42dc2019-07-22 14:06:00 +0100271 armnnCb.callback = cb;
Finn Williamsd8fb5402021-05-19 20:52:00 +0100272
273 if (m_AsyncModelExecutionEnabled)
274 {
275 ALOGV("ArmnnPreparedModel::execute(...) before ScheduleGraphForExecution");
276 ScheduleGraphForExecution(pMemPools, pInputTensors, pOutputTensors, armnnCb);
277 ALOGV("ArmnnPreparedModel::execute(...) after ScheduleGraphForExecution");
278 return V1_0::ErrorStatus::NONE;
279 }
280
Mike Kelly65c42dc2019-07-22 14:06:00 +0100281 // post the request for asynchronous execution
Finn Williamsd8fb5402021-05-19 20:52:00 +0100282 ALOGV("ArmnnPreparedModel::execute(...) before PostMsg");
Mike Kelly65c42dc2019-07-22 14:06:00 +0100283 m_RequestThread.PostMsg(this, pMemPools, pInputTensors, pOutputTensors, armnnCb);
284 ALOGV("ArmnnPreparedModel::execute(...) after PostMsg");
Kevin Mayec1e5b82020-02-26 17:00:39 +0000285 return V1_0::ErrorStatus::NONE; // successfully queued
telsoa015307bc12018-03-09 13:51:08 +0000286}
287
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100288template<typename HalVersion>
289void ArmnnPreparedModel<HalVersion>::ExecuteGraph(
290 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
Derek Lamberti4de83c52020-03-17 13:40:18 +0000291 armnn::InputTensors& inputTensors,
292 armnn::OutputTensors& outputTensors,
293 CallbackContext_1_0 cb)
telsoa015307bc12018-03-09 13:51:08 +0000294{
295 ALOGV("ArmnnPreparedModel::ExecuteGraph(...)");
296
Derek Lamberti4de83c52020-03-17 13:40:18 +0000297 DumpTensorsIfRequired("Input", inputTensors);
telsoa015307bc12018-03-09 13:51:08 +0000298
299 // run it
300 try
301 {
Finn Williamsd8fb5402021-05-19 20:52:00 +0100302 armnn::Status status;
303 if (m_AsyncModelExecutionEnabled)
304 {
305 ALOGW("ArmnnPreparedModel::ExecuteGraph m_AsyncModelExecutionEnabled true");
306 status = m_Runtime->Execute(*m_WorkingMemHandle, inputTensors, outputTensors);
307 }
308 else
309 {
310 ALOGW("ArmnnPreparedModel::ExecuteGraph m_AsyncModelExecutionEnabled false");
David Monahan80696032022-02-02 12:17:46 +0000311 status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Finn Williamsd8fb5402021-05-19 20:52:00 +0100312 }
313
Matthew Bentham16196e22019-04-01 17:17:58 +0100314 if (status != armnn::Status::Success)
315 {
316 ALOGW("EnqueueWorkload failed");
Kevin Mayec1e5b82020-02-26 17:00:39 +0000317 cb.callback(V1_0::ErrorStatus::GENERAL_FAILURE, "ArmnnPreparedModel::ExecuteGraph");
Matthew Bentham16196e22019-04-01 17:17:58 +0100318 return;
319 }
telsoa015307bc12018-03-09 13:51:08 +0000320 }
Kevin May7bdaac52020-02-10 12:10:07 +0000321 catch (armnn::Exception& e)
322 {
323 ALOGW("armnn::Exception caught from EnqueueWorkload: %s", e.what());
Kevin Mayec1e5b82020-02-26 17:00:39 +0000324 cb.callback(V1_0::ErrorStatus::GENERAL_FAILURE, "ArmnnPreparedModel::ExecuteGraph");
Kevin May7bdaac52020-02-10 12:10:07 +0000325 return;
326 }
Derek Lambertib9cb8442019-11-28 13:34:48 +0000327 catch (std::exception& e)
telsoa015307bc12018-03-09 13:51:08 +0000328 {
Kevin May7bdaac52020-02-10 12:10:07 +0000329 ALOGE("std::exception caught from EnqueueWorkload: %s", e.what());
Kevin Mayec1e5b82020-02-26 17:00:39 +0000330 cb.callback(V1_0::ErrorStatus::GENERAL_FAILURE, "ArmnnPreparedModel::ExecuteGraph");
telsoa015307bc12018-03-09 13:51:08 +0000331 return;
332 }
333
Derek Lamberti4de83c52020-03-17 13:40:18 +0000334 DumpTensorsIfRequired("Output", outputTensors);
telsoa015307bc12018-03-09 13:51:08 +0000335
336 // Commit output buffers.
337 // Note that we update *all* pools, even if they aren't actually used as outputs -
338 // this is simpler and is what the CpuExecutor does.
339 for (android::nn::RunTimePoolInfo& pool : *pMemPools)
340 {
Kevin Mayec1e5b82020-02-26 17:00:39 +0000341 // Type android::nn::RunTimePoolInfo has changed between Android P & Q and Android R, where
342 // update() has been removed and flush() added.
Sadik Armagan188675f2021-02-12 17:16:42 +0000343 #if defined(ARMNN_ANDROID_R) || defined(ARMNN_ANDROID_S) // Use the new Android implementation.
Kevin Mayec1e5b82020-02-26 17:00:39 +0000344 pool.flush();
345 #else
346 pool.update();
347 #endif
telsoa015307bc12018-03-09 13:51:08 +0000348 }
349
Kevin Mayec1e5b82020-02-26 17:00:39 +0000350 cb.callback(V1_0::ErrorStatus::NONE, "ExecuteGraph");
telsoa015307bc12018-03-09 13:51:08 +0000351}
352
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100353template<typename HalVersion>
Matthew Bentham16196e22019-04-01 17:17:58 +0100354bool ArmnnPreparedModel<HalVersion>::ExecuteWithDummyInputs()
telsoa015307bc12018-03-09 13:51:08 +0000355{
356 std::vector<std::vector<char>> storage;
357 armnn::InputTensors inputTensors;
Kevin May42477c12020-03-26 13:34:14 +0000358 for (unsigned int i = 0; i < getMainModel(m_Model).inputIndexes.size(); i++)
telsoa015307bc12018-03-09 13:51:08 +0000359 {
Cathal Corbette27d4e82021-10-28 12:28:35 +0100360 armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
361 // pInputTensors (of type InputTensors) is composed of a vector of ConstTensors.
362 // Therefore, set all TensorInfo isConstant parameters of input Tensors to true.
363 inputTensorInfo.SetConstant();
364
telsoa015307bc12018-03-09 13:51:08 +0000365 storage.emplace_back(inputTensorInfo.GetNumBytes());
366 const armnn::ConstTensor inputTensor(inputTensorInfo, storage.back().data());
367
368 inputTensors.emplace_back(i, inputTensor);
369 }
370
371 armnn::OutputTensors outputTensors;
Kevin May42477c12020-03-26 13:34:14 +0000372 for (unsigned int i = 0; i < getMainModel(m_Model).outputIndexes.size(); i++)
telsoa015307bc12018-03-09 13:51:08 +0000373 {
374 const armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
375 storage.emplace_back(outputTensorInfo.GetNumBytes());
376 const armnn::Tensor outputTensor(outputTensorInfo, storage.back().data());
377
378 outputTensors.emplace_back(i, outputTensor);
379 }
380
381 try
382 {
Finn Williams8fde84b2021-05-31 14:57:15 +0100383 armnn::Status status;
384 if (m_AsyncModelExecutionEnabled)
385 {
386 ALOGW("ArmnnPreparedModel::ExecuteGraph m_AsyncModelExecutionEnabled true");
387 status = m_Runtime->Execute(*m_WorkingMemHandle, inputTensors, outputTensors);
388 }
389 else
390 {
391 ALOGW("ArmnnPreparedModel::ExecuteGraph m_AsyncModelExecutionEnabled false");
David Monahan80696032022-02-02 12:17:46 +0000392 status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Finn Williams8fde84b2021-05-31 14:57:15 +0100393 }
Matthew Bentham16196e22019-04-01 17:17:58 +0100394 if (status != armnn::Status::Success)
395 {
396 ALOGW("ExecuteWithDummyInputs: EnqueueWorkload failed");
397 return false;
398 }
telsoa015307bc12018-03-09 13:51:08 +0000399 }
Kevin May7bdaac52020-02-10 12:10:07 +0000400 catch (armnn::Exception& e)
401 {
402 ALOGW("ExecuteWithDummyInputs: armnn::Exception caught from EnqueueWorkload: %s", e.what());
403 return false;
404 }
Derek Lambertib9cb8442019-11-28 13:34:48 +0000405 catch (std::exception& e)
telsoa015307bc12018-03-09 13:51:08 +0000406 {
Kevin May7bdaac52020-02-10 12:10:07 +0000407 ALOGE("ExecuteWithDummyInputs: std::exception caught from EnqueueWorkload: %s", e.what());
Matthew Bentham16196e22019-04-01 17:17:58 +0100408 return false;
telsoa015307bc12018-03-09 13:51:08 +0000409 }
Matthew Bentham16196e22019-04-01 17:17:58 +0100410 return true;
telsoa015307bc12018-03-09 13:51:08 +0000411}
412
Finn Williamsd8fb5402021-05-19 20:52:00 +0100413/// Schedule the graph prepared from the request for execution
414template<typename HalVersion>
415template<typename CallbackContext>
416void ArmnnPreparedModel<HalVersion>::ScheduleGraphForExecution(
417 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
418 std::shared_ptr<armnn::InputTensors>& inputTensors,
419 std::shared_ptr<armnn::OutputTensors>& outputTensors,
420 CallbackContext callbackContext)
421{
422 ALOGV("ArmnnPreparedModel::ScheduleGraphForExecution(...)");
423
424 DumpTensorsIfRequired("Input", *inputTensors);
425
426
427 auto tpCb = std::make_shared<
428 ArmnnThreadPoolCallback<CallbackContext_1_0>>(this,
429 pMemPools,
430 inputTensors,
431 outputTensors,
432 callbackContext);
433
Finn Williamsca3a3e02021-06-11 15:04:02 +0100434 m_Threadpool->Schedule(m_NetworkId,
435 *tpCb->m_InputTensors,
436 *tpCb->m_OutputTensors,
437 armnn::QosExecPriority::Medium,
438 tpCb);
Finn Williamsd8fb5402021-05-19 20:52:00 +0100439 ALOGV("ArmnnPreparedModel::ScheduleGraphForExecution end");
440}
441
442template<typename HalVersion>
443template <typename CallbackContext>
444void ArmnnPreparedModel<HalVersion>::ArmnnThreadPoolCallback<CallbackContext>::Notify(
445 armnn::Status status, armnn::InferenceTimingPair timeTaken)
446{
447 armnn::IgnoreUnused(status, timeTaken);
448 ALOGV("ArmnnPreparedModel::ArmnnThreadPoolCallback_1_2 Notify");
449
450 m_Model->DumpTensorsIfRequired("Output", *m_OutputTensors);
451
452 // Commit output buffers.
453 // Note that we update *all* pools, even if they aren't actually used as outputs -
454 // this is simpler and is what the CpuExecutor does.
455 for (android::nn::RunTimePoolInfo& pool : *m_MemPools)
456 {
457 // Type android::nn::RunTimePoolInfo has changed between Android P & Q and Android R, where
458 // update() has been removed and flush() added.
459 #if defined(ARMNN_ANDROID_R) || defined(ARMNN_ANDROID_S) // Use the new Android implementation.
460 pool.flush();
461 #else
462 pool.update();
463 #endif
464 }
465
466 m_CallbackContext.callback(V1_0::ErrorStatus::NONE, "ArmnnPreparedModel::ArmnnThreadPoolCallback_1_2 Notify");
467 return;
468}
469
arovir01b0717b52018-09-05 17:03:25 +0100470///
471/// Class template specializations
472///
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100473
arovir01b0717b52018-09-05 17:03:25 +0100474template class ArmnnPreparedModel<hal_1_0::HalPolicy>;
Finn Williamsd8fb5402021-05-19 20:52:00 +0100475template void ArmnnPreparedModel<hal_1_0::HalPolicy>::ScheduleGraphForExecution<CallbackContext_1_0>(
476 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
477 std::shared_ptr<armnn::InputTensors>& inputTensors,
478 std::shared_ptr<armnn::OutputTensors>& outputTensors,
479 CallbackContext_1_0 callbackContext);
arovir01b0717b52018-09-05 17:03:25 +0100480
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100481#ifdef ARMNN_ANDROID_NN_V1_1
arovir01b0717b52018-09-05 17:03:25 +0100482template class ArmnnPreparedModel<hal_1_1::HalPolicy>;
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100483#endif
484
Mike Kellyb5fdf382019-06-11 16:35:25 +0100485#ifdef ARMNN_ANDROID_NN_V1_2
486template class ArmnnPreparedModel<hal_1_1::HalPolicy>;
487template class ArmnnPreparedModel<hal_1_2::HalPolicy>;
488#endif
Kevin May42477c12020-03-26 13:34:14 +0000489
490#ifdef ARMNN_ANDROID_NN_V1_3
491template class ArmnnPreparedModel<hal_1_1::HalPolicy>;
492template class ArmnnPreparedModel<hal_1_2::HalPolicy>;
493template class ArmnnPreparedModel<hal_1_3::HalPolicy>;
494#endif
Nikhil Raj77605822018-09-03 11:25:56 +0100495} // namespace armnn_driver