blob: dd5bdae7dc5fa8d84a3eed67f34b7f0b76b264fc [file] [log] [blame]
Mike Kellyb5fdf382019-06-11 16:35:25 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#define LOG_TAG "ArmnnDriver"
7
8#include "ArmnnPreparedModel_1_2.hpp"
9#include "Utils.hpp"
10
11#include <boost/format.hpp>
12#include <log/log.h>
13#include <OperationsUtils.h>
14#include <ExecutionBurstServer.h>
15#include <ValidateHal.h>
16
17#include <cassert>
18#include <cinttypes>
19
20using namespace android;
21using namespace android::hardware;
22
Mike Kellyb5fdf382019-06-11 16:35:25 +010023namespace {
24
Mike Kelly44381512019-07-08 17:37:35 +010025static const Timing g_NoTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX};
Mike Kellyb5fdf382019-06-11 16:35:25 +010026using namespace armnn_driver;
Mike Kelly44381512019-07-08 17:37:35 +010027using TimePoint = std::chrono::steady_clock::time_point;
28
29TimePoint Now()
30{
31 return std::chrono::steady_clock::now();
32}
33
34unsigned long MicrosecondsDuration(TimePoint endPoint, TimePoint startPoint)
35{
36 return static_cast<unsigned long>(std::chrono::duration_cast<std::chrono::microseconds>(
37 endPoint - startPoint).count());
38}
Mike Kellyb5fdf382019-06-11 16:35:25 +010039
Mike Kelly65c42dc2019-07-22 14:06:00 +010040void NotifyCallbackAndCheck(const ::android::sp<V1_0::IExecutionCallback>& callback,
Kevin Mayec1e5b82020-02-26 17:00:39 +000041 V1_0::ErrorStatus errorStatus,
Mike Kelly65c42dc2019-07-22 14:06:00 +010042 std::vector<OutputShape>,
43 const Timing,
Mike Kellyb5fdf382019-06-11 16:35:25 +010044 std::string callingFunction)
45{
46 Return<void> returned = callback->notify(errorStatus);
47 // This check is required, if the callback fails and it isn't checked it will bring down the service
48 if (!returned.isOk())
49 {
50 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
51 callingFunction.c_str(), returned.description().c_str());
52 }
53}
54
Mike Kelly65c42dc2019-07-22 14:06:00 +010055void NotifyCallbackAndCheck(const ::android::sp<V1_2::IExecutionCallback>& callback,
Kevin Mayec1e5b82020-02-26 17:00:39 +000056 V1_0::ErrorStatus errorStatus,
Mike Kelly65c42dc2019-07-22 14:06:00 +010057 std::vector<OutputShape> outputShapes,
58 const Timing timing,
Mike Kellyb5fdf382019-06-11 16:35:25 +010059 std::string callingFunction)
60{
Mike Kelly65c42dc2019-07-22 14:06:00 +010061 Return<void> returned = callback->notify_1_2(errorStatus, outputShapes, timing);
Mike Kellyb5fdf382019-06-11 16:35:25 +010062 // This check is required, if the callback fails and it isn't checked it will bring down the service
63 if (!returned.isOk())
64 {
65 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
66 callingFunction.c_str(), returned.description().c_str());
67 }
68}
69
70bool ValidateRequestArgument(const RequestArgument& requestArg, const armnn::TensorInfo& tensorInfo)
71{
72 if (requestArg.dimensions.size() != 0)
73 {
74 if (requestArg.dimensions.size() != tensorInfo.GetNumDimensions())
75 {
76 ALOGE("Mismatched dimensions (request argument: %zu, expected: %u)",
77 requestArg.dimensions.size(), tensorInfo.GetNumDimensions());
78 return false;
79 }
80
81 for (unsigned int d = 0; d < tensorInfo.GetNumDimensions(); ++d)
82 {
Finn Williamsa4983ce2020-07-23 12:55:12 +010083 if (requestArg.dimensions[d] != 0 && requestArg.dimensions[d] != tensorInfo.GetShape()[d])
Mike Kellyb5fdf382019-06-11 16:35:25 +010084 {
85 ALOGE("Mismatched size for dimension %d (request argument: %u, expected %u)",
86 d, requestArg.dimensions[d], tensorInfo.GetShape()[d]);
87 return false;
88 }
89 }
90 }
91
92 return true;
93}
94
95armnn::Tensor GetTensorForRequestArgument(const RequestArgument& requestArg,
96 const armnn::TensorInfo& tensorInfo,
97 const std::vector<::android::nn::RunTimePoolInfo>& requestPools)
98{
99 if (!ValidateRequestArgument(requestArg, tensorInfo))
100 {
101 return armnn::Tensor();
102 }
103
104 return armnn::Tensor(tensorInfo, GetMemoryFromPool(requestArg.location, requestPools));
105}
106
107inline std::string BuildTensorName(const char* tensorNamePrefix, std::size_t index)
108{
109 return tensorNamePrefix + std::to_string(index);
110}
111
112} // anonymous namespace
113
114using namespace android::hardware;
115
116namespace armnn_driver
117{
118
119template<typename HalVersion>
Derek Lamberti4de83c52020-03-17 13:40:18 +0000120RequestThread<ArmnnPreparedModel_1_2, HalVersion, CallbackContext_1_2>
Mike Kelly65c42dc2019-07-22 14:06:00 +0100121 ArmnnPreparedModel_1_2<HalVersion>::m_RequestThread;
Mike Kellyb5fdf382019-06-11 16:35:25 +0100122
123template<typename HalVersion>
124template<typename TensorBindingCollection>
125void ArmnnPreparedModel_1_2<HalVersion>::DumpTensorsIfRequired(char const* tensorNamePrefix,
126 const TensorBindingCollection& tensorBindings)
127{
128 if (!m_RequestInputsAndOutputsDumpDir.empty())
129 {
130 const std::string requestName = boost::str(boost::format("%1%_%2%.dump") % m_NetworkId % m_RequestCount);
131 for (std::size_t i = 0u; i < tensorBindings.size(); ++i)
132 {
133 DumpTensor(m_RequestInputsAndOutputsDumpDir,
134 requestName,
135 BuildTensorName(tensorNamePrefix, i),
136 tensorBindings[i].second);
137 }
138 }
139}
140
141template<typename HalVersion>
142ArmnnPreparedModel_1_2<HalVersion>::ArmnnPreparedModel_1_2(armnn::NetworkId networkId,
143 armnn::IRuntime* runtime,
144 const V1_2::Model& model,
145 const std::string& requestInputsAndOutputsDumpDir,
146 const bool gpuProfilingEnabled)
147 : m_NetworkId(networkId)
148 , m_Runtime(runtime)
149 , m_Model(model)
150 , m_RequestCount(0)
151 , m_RequestInputsAndOutputsDumpDir(requestInputsAndOutputsDumpDir)
152 , m_GpuProfilingEnabled(gpuProfilingEnabled)
153{
154 // Enable profiling if required.
155 m_Runtime->GetProfiler(m_NetworkId)->EnableProfiling(m_GpuProfilingEnabled);
156}
157
158template<typename HalVersion>
159ArmnnPreparedModel_1_2<HalVersion>::~ArmnnPreparedModel_1_2()
160{
161 // Get a hold of the profiler used by this model.
162 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
163
164 // Unload the network associated with this model.
165 m_Runtime->UnloadNetwork(m_NetworkId);
166
167 // Dump the profiling info to a file if required.
168 DumpJsonProfilingIfRequired(m_GpuProfilingEnabled, m_RequestInputsAndOutputsDumpDir, m_NetworkId, profiler.get());
169}
170
171template<typename HalVersion>
Kevin Mayec1e5b82020-02-26 17:00:39 +0000172Return <V1_0::ErrorStatus> ArmnnPreparedModel_1_2<HalVersion>::execute(const V1_0::Request& request,
Mike Kellyb5fdf382019-06-11 16:35:25 +0100173 const ::android::sp<V1_0::IExecutionCallback>& callback)
174{
Mike Kelly65c42dc2019-07-22 14:06:00 +0100175 if (callback.get() == nullptr)
176 {
177 ALOGE("ArmnnPreparedModel_1_2::execute invalid callback passed");
Kevin Mayec1e5b82020-02-26 17:00:39 +0000178 return V1_0::ErrorStatus::INVALID_ARGUMENT;
Mike Kelly65c42dc2019-07-22 14:06:00 +0100179 }
180
Kevin Mayec1e5b82020-02-26 17:00:39 +0000181 auto cb = [callback](V1_0::ErrorStatus errorStatus,
Mike Kelly65c42dc2019-07-22 14:06:00 +0100182 std::vector<OutputShape> outputShapes,
183 const Timing& timing,
184 std::string callingFunction)
185 {
186 NotifyCallbackAndCheck(callback, errorStatus, outputShapes, timing, callingFunction);
187 };
188
189 return Execute(request, MeasureTiming::NO, cb);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100190}
191
192template<typename HalVersion>
Kevin Mayec1e5b82020-02-26 17:00:39 +0000193Return <V1_0::ErrorStatus> ArmnnPreparedModel_1_2<HalVersion>::execute_1_2(
194 const V1_0::Request& request,
195 MeasureTiming measureTiming,
196 const sp<V1_2::IExecutionCallback>& callback)
Mike Kellyb5fdf382019-06-11 16:35:25 +0100197{
Mike Kelly65c42dc2019-07-22 14:06:00 +0100198 if (callback.get() == nullptr)
199 {
200 ALOGE("ArmnnPreparedModel_1_2::execute_1_2 invalid callback passed");
Kevin Mayec1e5b82020-02-26 17:00:39 +0000201 return V1_0::ErrorStatus::INVALID_ARGUMENT;
Mike Kelly65c42dc2019-07-22 14:06:00 +0100202 }
203
Kevin Mayec1e5b82020-02-26 17:00:39 +0000204 auto cb = [callback](V1_0::ErrorStatus errorStatus,
Mike Kelly65c42dc2019-07-22 14:06:00 +0100205 std::vector<OutputShape> outputShapes,
206 const Timing& timing,
207 std::string callingFunction)
208 {
209 NotifyCallbackAndCheck(callback, errorStatus, outputShapes, timing, callingFunction);
210 };
211
212 return Execute(request, measureTiming, cb);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100213}
214
Derek Lamberti4de83c52020-03-17 13:40:18 +0000215template<typename HalVersion>
216Return<V1_0::ErrorStatus> ArmnnPreparedModel_1_2<HalVersion>::PrepareMemoryForInputs(
217 armnn::InputTensors& inputs,
218 const V1_0::Request& request,
219 const std::vector<android::nn::RunTimePoolInfo>& memPools)
220{
221 inputs.reserve(request.inputs.size());
222 for (unsigned int i = 0; i < request.inputs.size(); i++)
223 {
224 const auto& inputArg = request.inputs[i];
225
226 const armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
227 const armnn::Tensor inputTensor = GetTensorForRequestArgument(inputArg, inputTensorInfo, memPools);
228
229 if (inputTensor.GetMemoryArea() == nullptr)
230 {
231 ALOGE("Cannot execute request. Error converting request input %u to tensor", i);
232 return V1_0::ErrorStatus::GENERAL_FAILURE;
233 }
234
235 inputs.emplace_back(i, inputTensor);
236 }
237
238 return V1_0::ErrorStatus::NONE;
239}
240
241template<typename HalVersion>
242Return<V1_0::ErrorStatus> ArmnnPreparedModel_1_2<HalVersion>::PrepareMemoryForOutputs(
243 armnn::OutputTensors& outputs,
244 std::vector<OutputShape> &outputShapes,
245 const V1_0::Request& request,
246 const std::vector<android::nn::RunTimePoolInfo>& memPools)
247{
248 outputs.reserve(request.outputs.size());
249 for (unsigned int i = 0; i < request.outputs.size(); i++)
250 {
251 const auto& outputArg = request.outputs[i];
252
253 const armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
254 const armnn::Tensor outputTensor = GetTensorForRequestArgument(outputArg, outputTensorInfo, memPools);
255 if (outputTensor.GetMemoryArea() == nullptr)
256 {
257 ALOGE("Cannot execute request. Error converting request output %u to tensor", i);
258 return V1_0::ErrorStatus::GENERAL_FAILURE;
259 }
260
261 const size_t outputSize = outputTensorInfo.GetNumBytes();
Finn Williamsa4983ce2020-07-23 12:55:12 +0100262
263 if (outputArg.location.length < outputSize)
264 {
265 ALOGW("ArmnnPreparedModel_1_2::Execute failed: outputArg.location.length < outputSize");
266 return V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
267 }
268
Derek Lamberti4de83c52020-03-17 13:40:18 +0000269 const size_t bufferSize = memPools.at(outputArg.location.poolIndex).getHidlMemory().size();
270 if (bufferSize < outputSize)
271 {
Finn Williamsa4983ce2020-07-23 12:55:12 +0100272 ALOGW("ArmnnPreparedModel_1_2::Execute failed: bufferSize < outputSize");
Derek Lamberti4de83c52020-03-17 13:40:18 +0000273 return V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
274 }
275
276 outputs.emplace_back(i, outputTensor);
277 outputShapes[i] = ComputeShape(outputTensorInfo);
278 }
279
280 return V1_0::ErrorStatus::NONE;
281}
282
283template<typename HalVersion>
284Return<V1_0::ErrorStatus> ArmnnPreparedModel_1_2<HalVersion>::PrepareMemoryForIO(
285 armnn::InputTensors& inputs,
286 armnn::OutputTensors& outputs,
287 std::vector<android::nn::RunTimePoolInfo>& memPools,
288 const V1_0::Request& request,
289 CallbackAsync_1_2 callback)
290{
291 if (!setRunTimePoolInfosFromHidlMemories(&memPools, request.pools))
292 {
293 callback(V1_0::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_2::execute");
294 return V1_0::ErrorStatus::GENERAL_FAILURE;
295 }
296
297 // add the inputs and outputs with their data
298 try
299 {
300 if (PrepareMemoryForInputs(inputs, request, memPools) != V1_0::ErrorStatus::NONE)
301 {
302 callback(V1_0::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_2::execute");
303 return V1_0::ErrorStatus::GENERAL_FAILURE;
304 }
305
306 std::vector<OutputShape> outputShapes(request.outputs.size());
307
308 auto errorStatus = PrepareMemoryForOutputs(outputs, outputShapes, request, memPools);
309 if (errorStatus != V1_0::ErrorStatus::NONE)
310 {
311 callback(errorStatus,
312 outputShapes,
313 g_NoTiming,
314 "ArmnnPreparedModel_1_2::Execute");
315 return errorStatus;
316 }
317 }
318 catch (armnn::Exception& e)
319 {
320 ALOGW("armnn::Exception caught while preparing for EnqueueWorkload: %s", e.what());
321 callback(V1_0::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_2::execute");
322 return V1_0::ErrorStatus::GENERAL_FAILURE;
323 }
324 catch (std::exception& e)
325 {
326 ALOGE("std::exception caught while preparing for EnqueueWorkload: %s", e.what());
327 callback(V1_0::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_2::execute");
328 return V1_0::ErrorStatus::GENERAL_FAILURE;
329 }
330
331 return V1_0::ErrorStatus::NONE;
332}
333
Mike Kellyb5fdf382019-06-11 16:35:25 +0100334template<typename HalVersion>
Kevin Mayec1e5b82020-02-26 17:00:39 +0000335Return<void> ArmnnPreparedModel_1_2<HalVersion>::executeSynchronously(const V1_0::Request& request,
Mike Kelly44381512019-07-08 17:37:35 +0100336 MeasureTiming measureTiming,
337 executeSynchronously_cb cb)
Mike Kellyb5fdf382019-06-11 16:35:25 +0100338{
339 ALOGV("ArmnnPreparedModel_1_2::executeSynchronously(): %s", GetModelSummary(m_Model).c_str());
340 m_RequestCount++;
341
342 if (cb == nullptr)
343 {
344 ALOGE("ArmnnPreparedModel_1_2::executeSynchronously invalid callback passed");
345 return Void();
346 }
347
Derek Lamberti4de83c52020-03-17 13:40:18 +0000348 TimePoint driverStart;
Mike Kelly44381512019-07-08 17:37:35 +0100349
350 if (measureTiming == MeasureTiming::YES)
351 {
352 driverStart = Now();
353 }
354
Mike Kellyb5fdf382019-06-11 16:35:25 +0100355 if (!android::nn::validateRequest(request, m_Model))
356 {
Mike Kelly44381512019-07-08 17:37:35 +0100357 ALOGE("ArmnnPreparedModel_1_2::executeSynchronously invalid request model");
Kevin Mayec1e5b82020-02-26 17:00:39 +0000358 cb(V1_0::ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100359 return Void();
360 }
361
Derek Lamberti4de83c52020-03-17 13:40:18 +0000362 auto cbWrapper = [cb](V1_0::ErrorStatus errorStatus,
363 std::vector<OutputShape> outputShapes,
364 const Timing& timing,
365 std::string)
366 {
367 cb(errorStatus, outputShapes, timing);
368 };
Mike Kellyb5fdf382019-06-11 16:35:25 +0100369
370 // map the memory pool into shared pointers
371 // use a shared memory pools vector on the heap, as it is passed to the request thread
Derek Lamberti4de83c52020-03-17 13:40:18 +0000372 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
Mike Kellyb5fdf382019-06-11 16:35:25 +0100373
Derek Lamberti4de83c52020-03-17 13:40:18 +0000374 // allocate the tensors on the heap, as they are passed to the request thread
375 auto inputs = std::make_shared<armnn::InputTensors>();
376 auto outputs = std::make_shared<armnn::OutputTensors>();
377
378 auto prepareStatus = PrepareMemoryForIO(*inputs, *outputs, *memPools, request, cbWrapper);
379 if (prepareStatus != V1_0::ErrorStatus::NONE)
Mike Kellyb5fdf382019-06-11 16:35:25 +0100380 {
Kevin May7bdaac52020-02-10 12:10:07 +0000381 return Void();
382 }
383
Mike Kellyb5fdf382019-06-11 16:35:25 +0100384 ALOGV("ArmnnPreparedModel_1_2::executeSynchronously() before Execution");
385
Derek Lamberti4de83c52020-03-17 13:40:18 +0000386 CallbackContext_1_2 cbCtx;
387 cbCtx.callback = cbWrapper;
388 cbCtx.ctx.measureTimings = measureTiming;
389 cbCtx.ctx.driverStart = driverStart;
390 ExecuteGraph(memPools, *inputs, *outputs, cbCtx);
391
392 return Void();
393}
394
395template<typename HalVersion>
396template<typename CallbackContext>
397bool ArmnnPreparedModel_1_2<HalVersion>::ExecuteGraph(
398 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
399 armnn::InputTensors& inputTensors,
400 armnn::OutputTensors& outputTensors,
401 CallbackContext cb)
402{
403 ALOGV("ArmnnPreparedModel_1_2::ExecuteGraph(...)");
404
405 TimePoint driverEnd, deviceStart, deviceEnd;
406
407 DumpTensorsIfRequired("Input", inputTensors);
408
409 std::vector<OutputShape> outputShapes(outputTensors.size());
410 for (unsigned int i = 0; i < outputTensors.size(); i++)
411 {
412 std::pair<int, armnn::Tensor> outputTensorPair = outputTensors[i];
413 const armnn::Tensor outputTensor = outputTensorPair.second;
414 const armnn::TensorInfo outputTensorInfo = outputTensor.GetInfo();
415
416 outputShapes[i] = ComputeShape(outputTensorInfo);
417 }
418
Mike Kellyb5fdf382019-06-11 16:35:25 +0100419 // run it
420 try
421 {
Derek Lamberti4de83c52020-03-17 13:40:18 +0000422 if (cb.ctx.measureTimings == MeasureTiming::YES)
Mike Kelly44381512019-07-08 17:37:35 +0100423 {
424 deviceStart = Now();
425 }
426
Derek Lamberti4de83c52020-03-17 13:40:18 +0000427 armnn::Status status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100428
Derek Lamberti4de83c52020-03-17 13:40:18 +0000429 if (cb.ctx.measureTimings == MeasureTiming::YES)
Mike Kelly44381512019-07-08 17:37:35 +0100430 {
431 deviceEnd = Now();
432 }
Mike Kellyb5fdf382019-06-11 16:35:25 +0100433 if (status != armnn::Status::Success)
434 {
435 ALOGW("EnqueueWorkload failed");
Derek Lamberti4de83c52020-03-17 13:40:18 +0000436 cb.callback(V1_0::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming,
437 "ArmnnPreparedModel_1_2::ExecuteGraph");
438 return false;
Mike Kellyb5fdf382019-06-11 16:35:25 +0100439 }
440 }
Kevin May7bdaac52020-02-10 12:10:07 +0000441 catch (armnn::Exception& e)
442 {
Derek Lamberti4de83c52020-03-17 13:40:18 +0000443 ALOGW("armnn:Exception caught from EnqueueWorkload: %s", e.what());
444 cb.callback(V1_0::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_2::ExecuteGraph");
445 return false;
Kevin May7bdaac52020-02-10 12:10:07 +0000446 }
Derek Lambertib9cb8442019-11-28 13:34:48 +0000447 catch (std::exception& e)
Mike Kellyb5fdf382019-06-11 16:35:25 +0100448 {
Kevin May7bdaac52020-02-10 12:10:07 +0000449 ALOGE("std::exception caught from EnqueueWorkload: %s", e.what());
Derek Lamberti4de83c52020-03-17 13:40:18 +0000450 cb.callback(V1_0::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_2::ExecuteGraph");
451 return false;
Mike Kellyb5fdf382019-06-11 16:35:25 +0100452 }
453
Derek Lamberti4de83c52020-03-17 13:40:18 +0000454 CommitPools(*pMemPools);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100455
Derek Lamberti4de83c52020-03-17 13:40:18 +0000456 DumpTensorsIfRequired("Output", outputTensors);
Kevin Mayec1e5b82020-02-26 17:00:39 +0000457
Derek Lamberti4de83c52020-03-17 13:40:18 +0000458 if (cb.ctx.measureTimings == MeasureTiming::YES)
Mike Kelly44381512019-07-08 17:37:35 +0100459 {
460 driverEnd = Now();
461 Timing timing;
462 timing.timeOnDevice = MicrosecondsDuration(deviceEnd, deviceStart);
Derek Lamberti4de83c52020-03-17 13:40:18 +0000463 timing.timeInDriver = MicrosecondsDuration(driverEnd, cb.ctx.driverStart);
464 ALOGV("ArmnnPreparedModel_1_2::execute timing - Device = %lu Driver = %lu", timing.timeOnDevice,
465 timing.timeInDriver);
466 cb.callback(V1_0::ErrorStatus::NONE, outputShapes, timing, "ArmnnPreparedModel_1_2::ExecuteGraph");
467 } else {
468 cb.callback(V1_0::ErrorStatus::NONE, outputShapes, g_NoTiming, "ArmnnPreparedModel_1_2::ExecuteGraph");
Mike Kelly44381512019-07-08 17:37:35 +0100469 }
Derek Lamberti4de83c52020-03-17 13:40:18 +0000470
471 return true;
Mike Kellyb5fdf382019-06-11 16:35:25 +0100472}
473
Derek Lamberti4de83c52020-03-17 13:40:18 +0000474template<typename HalVersion>
475bool ArmnnPreparedModel_1_2<HalVersion>::ExecuteWithDummyInputs()
476{
477 std::vector<std::vector<char>> storage;
478 armnn::InputTensors inputTensors;
Kevin May42477c12020-03-26 13:34:14 +0000479 for (unsigned int i = 0; i < getMainModel(m_Model).inputIndexes.size(); i++)
Derek Lamberti4de83c52020-03-17 13:40:18 +0000480 {
481 const armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
482 storage.emplace_back(inputTensorInfo.GetNumBytes());
483 const armnn::ConstTensor inputTensor(inputTensorInfo, storage.back().data());
484
485 inputTensors.emplace_back(i, inputTensor);
486 }
487
488 armnn::OutputTensors outputTensors;
Kevin May42477c12020-03-26 13:34:14 +0000489 for (unsigned int i = 0; i < getMainModel(m_Model).outputIndexes.size(); i++)
Derek Lamberti4de83c52020-03-17 13:40:18 +0000490 {
491 const armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
492 storage.emplace_back(outputTensorInfo.GetNumBytes());
493 const armnn::Tensor outputTensor(outputTensorInfo, storage.back().data());
494
495 outputTensors.emplace_back(i, outputTensor);
496 }
497
498 auto nullCallback = [](V1_0::ErrorStatus, std::vector<OutputShape>, const Timing&, std::string) {};
499 CallbackContext_1_2 callbackContext;
500 callbackContext.callback = nullCallback;
501 callbackContext.ctx.measureTimings = MeasureTiming::NO;
502 auto memPools = std::make_shared<std::vector<::android::nn::RunTimePoolInfo>>();
503 return ExecuteGraph(memPools,
504 inputTensors,
505 outputTensors,
506 callbackContext);
507}
508
509template<typename HalVersion>
510Return <V1_0::ErrorStatus> ArmnnPreparedModel_1_2<HalVersion>::Execute(const V1_0::Request& request,
511 MeasureTiming measureTiming,
512 CallbackAsync_1_2 callback)
513{
514 ExecutionContext_1_2 ctx;
515 if (measureTiming == MeasureTiming::YES)
516 {
517 ctx.measureTimings = measureTiming;
518 ctx.driverStart = Now();
519 }
520
521 ALOGV("ArmnnPreparedModel_1_2::execute(): %s", GetModelSummary(m_Model).c_str());
522 m_RequestCount++;
523
524 if (!android::nn::validateRequest(request, m_Model))
525 {
526 callback(V1_0::ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming, "ArmnnPreparedModel_1_2::execute");
527 return V1_0::ErrorStatus::INVALID_ARGUMENT;
528 }
529
530 if (!m_RequestInputsAndOutputsDumpDir.empty())
531 {
532 ALOGD("Dumping inputs and outputs for request %" PRIuPTR, reinterpret_cast<std::uintptr_t>(&callback));
533 }
534
535 // map the memory pool into shared pointers
536 // use a shared memory pools vector on the heap, as it is passed to the request thread
537 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
538
539 // allocate the tensors on the heap, as they are passed to the request thread
540 auto inputTensors = std::make_shared<armnn::InputTensors>();
541 auto outputTensors = std::make_shared<armnn::OutputTensors>();
542
543 auto prepareStatus = PrepareMemoryForIO(*inputTensors, *outputTensors, *memPools, request, callback);
544 switch(prepareStatus)
545 {
546 case V1_0::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
547 return V1_0::ErrorStatus::NONE;
548 case V1_0::ErrorStatus::GENERAL_FAILURE:
549 return V1_0::ErrorStatus::GENERAL_FAILURE;
550 default:
551 {}
552 }
553
554 ALOGV("ArmnnPreparedModel_1_2::execute(...) before PostMsg");
555
556 // post the request for asynchronous execution
557 CallbackContext_1_2 cb;
558 cb.callback = callback;
559 cb.ctx = ctx;
560 m_RequestThread.PostMsg(this, memPools, inputTensors, outputTensors, cb);
561 ALOGV("ArmnnPreparedModel_1_2::execute(...) after PostMsg");
562 return V1_0::ErrorStatus::NONE;
563}
564
Mike Kellyb5fdf382019-06-11 16:35:25 +0100565template<typename HalVersion>
566Return<void> ArmnnPreparedModel_1_2<HalVersion>::configureExecutionBurst(
Derek Lamberti4de83c52020-03-17 13:40:18 +0000567 const sp<V1_2::IBurstCallback>& callback,
568 const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
569 const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
570 V1_2::IPreparedModel::configureExecutionBurst_cb cb)
Mike Kellyb5fdf382019-06-11 16:35:25 +0100571{
572 ALOGV("ArmnnPreparedModel_1_2::configureExecutionBurst");
Mike Kelly65c42dc2019-07-22 14:06:00 +0100573 const sp<V1_2::IBurstContext> burst = ExecutionBurstServer::create(callback,
574 requestChannel,
575 resultChannel,
Kevin May42477c12020-03-26 13:34:14 +0000576 this);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100577
Mike Kelly44381512019-07-08 17:37:35 +0100578 if (burst == nullptr)
579 {
Kevin Mayec1e5b82020-02-26 17:00:39 +0000580 cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
Mike Kelly44381512019-07-08 17:37:35 +0100581 }
582 else
583 {
Kevin Mayec1e5b82020-02-26 17:00:39 +0000584 cb(V1_0::ErrorStatus::NONE, burst);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100585 }
586 return Void();
587}
588
Kevin May42477c12020-03-26 13:34:14 +0000589#if defined(ARMNN_ANDROID_NN_V1_2) || defined(ARMNN_ANDROID_NN_V1_3)
Mike Kellyb5fdf382019-06-11 16:35:25 +0100590template class ArmnnPreparedModel_1_2<hal_1_2::HalPolicy>;
Derek Lamberti4de83c52020-03-17 13:40:18 +0000591template bool ArmnnPreparedModel_1_2<hal_1_2::HalPolicy>::ExecuteGraph<CallbackContext_1_2>(
592 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
593 armnn::InputTensors& pInputTensors,
594 armnn::OutputTensors& pOutputTensors,
595 CallbackContext_1_2 cb);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100596#endif
597
598} // namespace armnn_driver