blob: bd5261e18c93be8bed693b2ebc2b578b04f26d99 [file] [log] [blame]
Kevin May42477c12020-03-26 13:34:14 +00001//
2// Copyright © 2020 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
Sadik Armagand7be72e2020-04-23 12:56:05 +01005// Note: the ArmnnFencedExecutionCallback and code snippet in the executeFenced() function
6// in this file is based on Android code
7// under the Apache 2.0 license. See comments below for details.
8//
Kevin May42477c12020-03-26 13:34:14 +00009
10#define LOG_TAG "ArmnnDriver"
11
12#include "ArmnnPreparedModel_1_3.hpp"
13#include "Utils.hpp"
14
15#include <Utils.h>
Sadik Armagand7be72e2020-04-23 12:56:05 +010016#include <android/sync.h>
Kevin May42477c12020-03-26 13:34:14 +000017#include <log/log.h>
18#include <OperationsUtils.h>
19#include <ExecutionBurstServer.h>
20#include <ValidateHal.h>
21
22#include <cassert>
23#include <cinttypes>
24
25using namespace android;
26using namespace android::hardware;
27
28namespace {
29
Kevin DuBois23e678a2020-11-20 14:54:05 -080030static const V1_2::Timing g_NoTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX};
Kevin May42477c12020-03-26 13:34:14 +000031using namespace armnn_driver;
32using TimePoint = std::chrono::steady_clock::time_point;
33
34TimePoint Now()
35{
36 return std::chrono::steady_clock::now();
37}
38
39unsigned long MicrosecondsDuration(TimePoint endPoint, TimePoint startPoint)
40{
41 return static_cast<unsigned long>(std::chrono::duration_cast<std::chrono::microseconds>(
42 endPoint - startPoint).count());
43}
44
45void NotifyCallbackAndCheck(const ::android::sp<V1_0::IExecutionCallback>& callback,
46 V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -080047 std::vector<V1_2::OutputShape>,
48 const V1_2::Timing,
Kevin May42477c12020-03-26 13:34:14 +000049 std::string callingFunction)
50{
51 Return<void> returned = callback->notify(convertToV1_0(errorStatus));
52 // This check is required, if the callback fails and it isn't checked it will bring down the service
53 if (!returned.isOk())
54 {
55 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
56 callingFunction.c_str(), returned.description().c_str());
57 }
58}
59
60void NotifyCallbackAndCheck(const ::android::sp<V1_2::IExecutionCallback>& callback,
61 V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -080062 std::vector<V1_2::OutputShape> outputShapes,
63 const V1_2::Timing timing,
Kevin May42477c12020-03-26 13:34:14 +000064 std::string callingFunction)
65{
66 Return<void> returned = callback->notify_1_2(convertToV1_0(errorStatus), outputShapes, timing);
67 // This check is required, if the callback fails and it isn't checked it will bring down the service
68 if (!returned.isOk())
69 {
70 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
71 callingFunction.c_str(), returned.description().c_str());
72 }
73}
74
75void NotifyCallbackAndCheck(const ::android::sp<V1_3::IExecutionCallback>& callback,
76 V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -080077 std::vector<V1_2::OutputShape> outputShapes,
78 const V1_2::Timing timing,
Kevin May42477c12020-03-26 13:34:14 +000079 std::string callingFunction)
80{
81 Return<void> returned = callback->notify_1_3(errorStatus, outputShapes, timing);
82 // This check is required, if the callback fails and it isn't checked it will bring down the service
83 if (!returned.isOk())
84 {
85 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
86 callingFunction.c_str(), returned.description().c_str());
87 }
88}
89
Kevin DuBois23e678a2020-11-20 14:54:05 -080090bool ValidateRequestArgument(const V1_0::RequestArgument& requestArg, const armnn::TensorInfo& tensorInfo)
Kevin May42477c12020-03-26 13:34:14 +000091{
92 if (requestArg.dimensions.size() != 0)
93 {
94 if (requestArg.dimensions.size() != tensorInfo.GetNumDimensions())
95 {
96 ALOGE("Mismatched dimensions (request argument: %zu, expected: %u)",
97 requestArg.dimensions.size(), tensorInfo.GetNumDimensions());
98 return false;
99 }
100
101 for (unsigned int d = 0; d < tensorInfo.GetNumDimensions(); ++d)
102 {
Finn Williamsa4983ce2020-07-23 12:55:12 +0100103 if (requestArg.dimensions[d] != 0 && requestArg.dimensions[d] != tensorInfo.GetShape()[d])
Kevin May42477c12020-03-26 13:34:14 +0000104 {
105 ALOGE("Mismatched size for dimension %d (request argument: %u, expected %u)",
106 d, requestArg.dimensions[d], tensorInfo.GetShape()[d]);
107 return false;
108 }
109 }
110 }
111
112 return true;
113}
114
Kevin DuBois23e678a2020-11-20 14:54:05 -0800115armnn::Tensor GetTensorForRequestArgument(const V1_0::RequestArgument& requestArg,
Kevin May42477c12020-03-26 13:34:14 +0000116 const armnn::TensorInfo& tensorInfo,
117 const std::vector<::android::nn::RunTimePoolInfo>& requestPools)
118{
119 if (!ValidateRequestArgument(requestArg, tensorInfo))
120 {
121 return armnn::Tensor();
122 }
123
124 return armnn::Tensor(tensorInfo, GetMemoryFromPool(requestArg.location, requestPools));
125}
126
127inline std::string BuildTensorName(const char* tensorNamePrefix, std::size_t index)
128{
129 return tensorNamePrefix + std::to_string(index);
130}
131
132} // anonymous namespace
133
134using namespace android::hardware;
135
136namespace armnn_driver
137{
138
139template<typename HalVersion>
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100140RequestThread_1_3<ArmnnPreparedModel_1_3, HalVersion, CallbackContext_1_3>
Kevin May42477c12020-03-26 13:34:14 +0000141 ArmnnPreparedModel_1_3<HalVersion>::m_RequestThread;
142
143template<typename HalVersion>
144template<typename TensorBindingCollection>
145void ArmnnPreparedModel_1_3<HalVersion>::DumpTensorsIfRequired(char const* tensorNamePrefix,
146 const TensorBindingCollection& tensorBindings)
147{
148 if (!m_RequestInputsAndOutputsDumpDir.empty())
149 {
Colm Donelan08d9a1c2020-09-09 17:56:55 +0100150 const std::string requestName = std::to_string(m_NetworkId) + "_" + std::to_string(m_RequestCount) + ".dump";
Kevin May42477c12020-03-26 13:34:14 +0000151 for (std::size_t i = 0u; i < tensorBindings.size(); ++i)
152 {
153 DumpTensor(m_RequestInputsAndOutputsDumpDir,
154 requestName,
155 BuildTensorName(tensorNamePrefix, i),
156 tensorBindings[i].second);
157 }
158 }
159}
160
161template<typename HalVersion>
162ArmnnPreparedModel_1_3<HalVersion>::ArmnnPreparedModel_1_3(armnn::NetworkId networkId,
163 armnn::IRuntime* runtime,
164 const V1_3::Model& model,
165 const std::string& requestInputsAndOutputsDumpDir,
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100166 const bool gpuProfilingEnabled,
167 V1_3::Priority priority)
Kevin May42477c12020-03-26 13:34:14 +0000168 : m_NetworkId(networkId)
169 , m_Runtime(runtime)
170 , m_Model(model)
171 , m_RequestCount(0)
172 , m_RequestInputsAndOutputsDumpDir(requestInputsAndOutputsDumpDir)
173 , m_GpuProfilingEnabled(gpuProfilingEnabled)
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100174 , m_ModelPriority(priority)
Kevin May42477c12020-03-26 13:34:14 +0000175{
176 // Enable profiling if required.
177 m_Runtime->GetProfiler(m_NetworkId)->EnableProfiling(m_GpuProfilingEnabled);
178}
179
180template<typename HalVersion>
181ArmnnPreparedModel_1_3<HalVersion>::~ArmnnPreparedModel_1_3()
182{
183 // Get a hold of the profiler used by this model.
184 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
185
186 // Unload the network associated with this model.
187 m_Runtime->UnloadNetwork(m_NetworkId);
188
189 // Dump the profiling info to a file if required.
190 DumpJsonProfilingIfRequired(m_GpuProfilingEnabled, m_RequestInputsAndOutputsDumpDir, m_NetworkId, profiler.get());
191}
192
193template<typename HalVersion>
194Return <V1_0::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::execute(const V1_0::Request& request,
195 const ::android::sp<V1_0::IExecutionCallback>& callback)
196{
197 if (callback.get() == nullptr)
198 {
199 ALOGE("ArmnnPreparedModel_1_3::execute invalid callback passed");
200 return V1_0::ErrorStatus::INVALID_ARGUMENT;
201 }
202
203 auto cb = [callback](V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800204 std::vector<V1_2::OutputShape> outputShapes,
205 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000206 std::string callingFunction)
207 {
208 NotifyCallbackAndCheck(callback, errorStatus, outputShapes, timing, callingFunction);
209 };
210
211
Kevin DuBois23e678a2020-11-20 14:54:05 -0800212 return convertToV1_0(Execute(convertToV1_3(request), V1_2::MeasureTiming::NO, cb));
Kevin May42477c12020-03-26 13:34:14 +0000213}
214
215template<typename HalVersion>
216Return <V1_0::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::execute_1_2(
217 const V1_0::Request& request,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800218 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000219 const sp<V1_2::IExecutionCallback>& callback)
220{
221 if (callback.get() == nullptr)
222 {
223 ALOGE("ArmnnPreparedModel_1_3::execute_1_2 invalid callback passed");
224 return V1_0::ErrorStatus::INVALID_ARGUMENT;
225 }
226
227 auto cb = [callback](V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800228 std::vector<V1_2::OutputShape> outputShapes,
229 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000230 std::string callingFunction)
231 {
232 NotifyCallbackAndCheck(callback, errorStatus, outputShapes, timing, callingFunction);
233 };
234
235 return convertToV1_0(Execute(convertToV1_3(request), measureTiming, cb));
236}
237
238template<typename HalVersion>
239Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::execute_1_3(
240 const V1_3::Request& request,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800241 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000242 const V1_3::OptionalTimePoint&,
Kevin May352d8382020-03-31 15:03:42 +0100243 const V1_3::OptionalTimeoutDuration&,
Kevin May42477c12020-03-26 13:34:14 +0000244 const sp<V1_3::IExecutionCallback>& callback)
245{
246 if (callback.get() == nullptr)
247 {
248 ALOGE("ArmnnPreparedModel_1_3::execute_1_3 invalid callback passed");
249 return V1_3::ErrorStatus::INVALID_ARGUMENT;
250 }
251
252 auto cb = [callback](V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800253 std::vector<V1_2::OutputShape> outputShapes,
254 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000255 std::string callingFunction)
256 {
257 NotifyCallbackAndCheck(callback, errorStatus, outputShapes, timing, callingFunction);
258 };
259
260 return Execute(request, measureTiming, cb);
261}
262
Sadik Armagand7be72e2020-04-23 12:56:05 +0100263/// This class is inspired by the sample implementation in Android named SampleFencedExecutionCallback.
264/// The original code is licensed under Apache-2.0 and can be found at the following link:
265/// https://android.googlesource.com/platform/frameworks/ml/+/master/nn/driver/sample/SampleDriver.h
266class ArmnnFencedExecutionCallback : public V1_3::IFencedExecutionCallback
267{
268public:
Kevin DuBois23e678a2020-11-20 14:54:05 -0800269 ArmnnFencedExecutionCallback(V1_3::ErrorStatus errorStatus, V1_2::Timing timing, V1_2::Timing fenceTiming)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100270 : m_ErrorStatus(errorStatus), m_Timing(timing), m_FenceTiming(fenceTiming) {}
271 ~ArmnnFencedExecutionCallback() {}
272
273 Return<void> getExecutionInfo(getExecutionInfo_cb callback) override
274 {
275 callback(m_ErrorStatus, m_Timing, m_FenceTiming);
276 return Void();
277 }
278private:
279 V1_3::ErrorStatus m_ErrorStatus;
Kevin DuBois23e678a2020-11-20 14:54:05 -0800280 V1_2::Timing m_Timing;
281 V1_2::Timing m_FenceTiming;
Sadik Armagand7be72e2020-04-23 12:56:05 +0100282};
283
Kevin May42477c12020-03-26 13:34:14 +0000284template<typename HalVersion>
Sadik Armagand7be72e2020-04-23 12:56:05 +0100285Return<void> ArmnnPreparedModel_1_3<HalVersion>::executeFenced(const V1_3::Request& request,
286 const hidl_vec<hidl_handle>& fenceWaitFor,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800287 V1_2::MeasureTiming measureTiming,
288 const V1_3::OptionalTimePoint& deadline,
289 const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
290 const V1_3::OptionalTimeoutDuration&,
Kevin May42477c12020-03-26 13:34:14 +0000291 executeFenced_cb cb)
292{
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100293 ALOGV("ArmnnPreparedModel_1_3::executeFenced(...)");
294 if (cb == nullptr)
295 {
296 ALOGE("ArmnnPreparedModel_1_3::executeFenced invalid callback passed");
Kevin DuBois23e678a2020-11-20 14:54:05 -0800297 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100298 return Void();
299 }
300
Kevin DuBois23e678a2020-11-20 14:54:05 -0800301 if (deadline.getDiscriminator() != V1_3::OptionalTimePoint::hidl_discriminator::none)
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100302 {
303 ALOGW("ArmnnPreparedModel_1_3::executeFenced parameter deadline is set but not supported.");
304 }
305
Kevin DuBois23e678a2020-11-20 14:54:05 -0800306 if (loopTimeoutDuration.getDiscriminator() != V1_3::OptionalTimeoutDuration::hidl_discriminator::none)
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100307 {
308 ALOGW("ArmnnPreparedModel_1_3::executeFenced parameter loopTimeoutDuration is set but not supported.");
309 }
310
Finn Williamsa4983ce2020-07-23 12:55:12 +0100311 if (!android::nn::validateRequest(request, m_Model, /*allowUnspecifiedOutput=*/false))
312 {
313 ALOGV("ArmnnPreparedModel_1_3::executeFenced outputs must be specified for fenced execution ");
Kevin DuBois23e678a2020-11-20 14:54:05 -0800314 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Finn Williamsa4983ce2020-07-23 12:55:12 +0100315 return Void();
316 }
317
Sadik Armagand7be72e2020-04-23 12:56:05 +0100318 ExecutionContext_1_3 ctx;
Kevin DuBois23e678a2020-11-20 14:54:05 -0800319 if (measureTiming == V1_2::MeasureTiming::YES)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100320 {
321 ctx.measureTimings = measureTiming;
322 ctx.driverStart = Now();
323 }
324
325 ALOGV("ArmnnPreparedModel_1_3::executeFenced(): %s", GetModelSummary(m_Model).c_str());
326 m_RequestCount++;
327
Sadik Armagand7be72e2020-04-23 12:56:05 +0100328 if (!m_RequestInputsAndOutputsDumpDir.empty())
329 {
330 ALOGD("Dumping inputs and outputs for request %" PRIuPTR, reinterpret_cast<std::uintptr_t>(&cb));
331 }
332
333 // This code snippet is inspired by the sample implementation in Android named SampleDriver::executeFenced()
334 // function. The original code is licensed under Apache-2.0 and can be found at the following link:
335 // https://android.googlesource.com/platform/frameworks/ml/+/master/nn/driver/sample/SampleDriver.cpp
336 const auto fenceSize = fenceWaitFor.size();
337 for (unsigned int index = 0; index < fenceSize; ++index)
338 {
339 auto fenceNativeHandle = fenceWaitFor[index].getNativeHandle();
340 if (!fenceNativeHandle)
341 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800342 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Sadik Armagand7be72e2020-04-23 12:56:05 +0100343 return Void();
344 }
345
346 if (sync_wait(fenceNativeHandle->data[0], -1) < 0)
347 {
348 ALOGE("ArmnnPreparedModel_1_3::executeFenced sync fence failed.");
Kevin DuBois23e678a2020-11-20 14:54:05 -0800349 cb(V1_3::ErrorStatus::GENERAL_FAILURE, hidl_handle(nullptr), nullptr);
Sadik Armagand7be72e2020-04-23 12:56:05 +0100350 return Void();
351 }
352 }
353
354 TimePoint fenceExecutionStart;
Kevin DuBois23e678a2020-11-20 14:54:05 -0800355 if (measureTiming == V1_2::MeasureTiming::YES)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100356 {
357 fenceExecutionStart = Now();
358 }
359
360 // map the memory pool into shared pointers
361 // use a shared memory pools vector on the heap, as it is passed to the request thread
362 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
363
364 // allocate the tensors on the heap, as they are passed to the request thread
365 auto inputs = std::make_shared<armnn::InputTensors>();
366 auto outputs = std::make_shared<armnn::OutputTensors>();
367
368 auto [status, outShapes, timings, message] = PrepareMemoryForIO(*inputs, *outputs, *memPools, request);
369 if (status != V1_3::ErrorStatus::NONE)
370 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800371 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Sadik Armagand7be72e2020-04-23 12:56:05 +0100372 return Void();
373 }
374
375 ALOGV("ArmnnPreparedModel_1_3::executeFenced(...) before ExecuteGraph");
376
377 // call it with nullCallback for now as we will report the error status from here..
Kevin DuBois23e678a2020-11-20 14:54:05 -0800378 auto nullCallback = [](V1_3::ErrorStatus, std::vector<V1_2::OutputShape>, const V1_2::Timing&, std::string) {};
Sadik Armagand7be72e2020-04-23 12:56:05 +0100379 CallbackContext_1_3 cbCtx;
380 cbCtx.callback = nullCallback;
381 cbCtx.ctx = ctx;
382
383 auto errorStatus = ExecuteGraph(memPools, *inputs, *outputs, cbCtx);
384 if (errorStatus != V1_3::ErrorStatus::NONE)
385 {
386 cb(errorStatus, hidl_handle(nullptr), nullptr);
387 return Void();
388 }
389 ALOGV("ArmnnPreparedModel_1_3::executeFenced(...) after ExecuteGraph");
390
Kevin DuBois23e678a2020-11-20 14:54:05 -0800391 V1_2::Timing timing = g_NoTiming;
392 V1_2::Timing fenceTiming = g_NoTiming;
393 if (measureTiming == V1_2::MeasureTiming::YES)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100394 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100395 fenceTiming.timeOnDevice = MicrosecondsDuration(ctx.deviceEnd, ctx.deviceStart);
Kevin May949a69e2020-04-24 10:21:40 +0100396 fenceTiming.timeInDriver = MicrosecondsDuration(ctx.driverEnd, fenceExecutionStart);
Kevin DuBois17c424b2020-11-20 14:18:03 -0800397 ALOGV("ArmnnPreparedModel_1_3::fenceFinishExecutionTiming - Device = %" PRIu64 " Driver = %" PRIu64,
Sadik Armagand7be72e2020-04-23 12:56:05 +0100398 fenceTiming.timeOnDevice, fenceTiming.timeInDriver);
399 }
400
401 sp<ArmnnFencedExecutionCallback> armnnFencedExecutionCallback =
Kevin DuBois23e678a2020-11-20 14:54:05 -0800402 new ArmnnFencedExecutionCallback(V1_3::ErrorStatus::NONE, timing, fenceTiming);
403 cb(V1_3::ErrorStatus::NONE, hidl_handle(nullptr), armnnFencedExecutionCallback);
Kevin May42477c12020-03-26 13:34:14 +0000404 return Void();
405}
406
407template<typename HalVersion>
408Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForInputs(
409 armnn::InputTensors& inputs,
410 const V1_3::Request& request,
411 const std::vector<android::nn::RunTimePoolInfo>& memPools)
412{
413 inputs.reserve(request.inputs.size());
414 for (unsigned int i = 0; i < request.inputs.size(); i++)
415 {
416 const auto& inputArg = request.inputs[i];
417
418 const armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
419 const armnn::Tensor inputTensor = GetTensorForRequestArgument(inputArg, inputTensorInfo, memPools);
420
Renato Grottesic8713e02022-12-14 17:04:16 +0000421 uint32_t poolIndex = inputArg.location.poolIndex;
422 if (poolIndex >= memPools.size())
423 {
424 ALOGE("Cannot execute request. Error converting request input %u to tensor: wrong poolIndex", i);
425 return V1_3::ErrorStatus::GENERAL_FAILURE;
426 }
427
428 uint8_t* inputTensorBegin = static_cast<uint8_t*>(inputTensor.GetMemoryArea());
429 if (inputTensorBegin == nullptr)
Kevin May42477c12020-03-26 13:34:14 +0000430 {
431 ALOGE("Cannot execute request. Error converting request input %u to tensor", i);
432 return V1_3::ErrorStatus::GENERAL_FAILURE;
433 }
434
Renato Grottesic8713e02022-12-14 17:04:16 +0000435 const size_t inputTensorSize = inputTensorInfo.GetNumBytes();
436 uint8_t* memoryPoolBegin = memPools[poolIndex].getBuffer();
437 uint32_t memoryPoolSize = memPools[poolIndex].getSize();
438 bool inputTensorIsOutOfMemoryRage = (inputTensorBegin + inputTensorSize) > (memoryPoolBegin + memoryPoolSize);
439
440 if (inputTensorIsOutOfMemoryRage)
441 {
442 ALOGE("Cannot execute request. Error converting request input %u to tensor: out of Memory Pool", i);
443 return V1_3::ErrorStatus::GENERAL_FAILURE;
444 }
445
Kevin May42477c12020-03-26 13:34:14 +0000446 inputs.emplace_back(i, inputTensor);
447 }
448
449 return V1_3::ErrorStatus::NONE;
450}
451
452template<typename HalVersion>
453Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForOutputs(
454 armnn::OutputTensors& outputs,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800455 std::vector<V1_2::OutputShape> &outputShapes,
Kevin May42477c12020-03-26 13:34:14 +0000456 const V1_3::Request& request,
457 const std::vector<android::nn::RunTimePoolInfo>& memPools)
458{
459 outputs.reserve(request.outputs.size());
460 for (unsigned int i = 0; i < request.outputs.size(); i++)
461 {
462 const auto& outputArg = request.outputs[i];
463
Finn Williamsa4983ce2020-07-23 12:55:12 +0100464 armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
Kevin May42477c12020-03-26 13:34:14 +0000465 const armnn::Tensor outputTensor = GetTensorForRequestArgument(outputArg, outputTensorInfo, memPools);
Renato Grottesic8713e02022-12-14 17:04:16 +0000466 uint8_t* outputTensorBegin = static_cast<uint8_t*>(outputTensor.GetMemoryArea());
467 if (outputTensorBegin == nullptr)
Kevin May42477c12020-03-26 13:34:14 +0000468 {
469 ALOGE("Cannot execute request. Error converting request output %u to tensor", i);
470 return V1_3::ErrorStatus::GENERAL_FAILURE;
471 }
472
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100473 const size_t outputSize = outputTensorInfo.GetNumBytes();
Renato Grottesic8713e02022-12-14 17:04:16 +0000474 uint32_t poolIndex = outputArg.location.poolIndex;
475 if (poolIndex >= memPools.size())
476 {
477 ALOGE("Cannot execute request. Error converting request output %u to tensor: wrong poolIndex", i);
478 return V1_3::ErrorStatus::GENERAL_FAILURE;
479 }
480
481 uint8_t* memoryPoolBegin = memPools[poolIndex].getBuffer();
482 uint32_t memoryPoolSize = memPools[poolIndex].getSize();
483 bool outputTensorIsOutOfMemoryRage = (outputTensorBegin + outputSize) > (memoryPoolBegin + memoryPoolSize);
484 if (outputTensorIsOutOfMemoryRage)
485 {
486 ALOGE("Cannot execute request. Error converting request output %u to tensor: out of Memory Pool", i);
487 return V1_3::ErrorStatus::GENERAL_FAILURE;
488 }
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100489
Finn Williamsa4983ce2020-07-23 12:55:12 +0100490 unsigned int count = 0;
491 std::for_each(outputArg.dimensions.begin(), outputArg.dimensions.end(), [&](auto dim)
492 {
493 if (dim != 0)
494 {
495 outputTensorInfo.GetShape()[count] = dim;
496 }
497 else
498 {
499 outputTensorInfo.GetShape()[count] = outputArg.dimensions.size();
500 }
501
502 count++;
503 });
504
Finn Williamsa4983ce2020-07-23 12:55:12 +0100505 outputs.emplace_back(i, outputTensor);
506 outputShapes[i] = ComputeShape(outputTensorInfo);
507
508 if (outputArg.location.length < outputSize)
509 {
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100510 ALOGW("ArmnnPreparedModel_1_3::Execute failed outputArg.location.length (%s) < outputSize (%s)",
511 std::to_string(outputArg.location.length).c_str(), std::to_string(outputSize).c_str());
Finn Williamsa4983ce2020-07-23 12:55:12 +0100512 outputShapes[i].isSufficient = false;
513 return V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
514 }
515
Kevin DuBoisbbcff192020-11-20 14:36:59 -0800516 const size_t bufferSize = memPools.at(outputArg.location.poolIndex).getSize();
Kevin May42477c12020-03-26 13:34:14 +0000517 if (bufferSize < outputSize)
518 {
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100519 ALOGW("ArmnnPreparedModel_1_3::Execute failed bufferSize (%s) < outputSize (%s)",
520 std::to_string(bufferSize).c_str(), std::to_string(outputSize).c_str());
Finn Williamsa4983ce2020-07-23 12:55:12 +0100521 outputShapes[i].isSufficient = false;
Kevin May42477c12020-03-26 13:34:14 +0000522 return V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
523 }
Kevin May42477c12020-03-26 13:34:14 +0000524 }
525
526 return V1_3::ErrorStatus::NONE;
527}
528
529template<typename HalVersion>
Kevin DuBois23e678a2020-11-20 14:54:05 -0800530std::tuple<V1_3::ErrorStatus, hidl_vec<V1_2::OutputShape>, V1_2::Timing, std::string>
Kevin May42477c12020-03-26 13:34:14 +0000531 ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForIO(armnn::InputTensors& inputs,
532 armnn::OutputTensors& outputs,
533 std::vector<android::nn::RunTimePoolInfo>& memPools,
534 const V1_3::Request& request)
535{
Kevin DuBois7bd76002020-11-23 08:20:27 -0800536 if (!setRunTimePoolInfosFromMemoryPools(&memPools, uncheckedConvert(request.pools)))
Kevin May42477c12020-03-26 13:34:14 +0000537 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800538 return {V1_3::ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000539 }
540
541 // add the inputs and outputs with their data
542 try
543 {
544 if (PrepareMemoryForInputs(inputs, request, memPools) != V1_3::ErrorStatus::NONE)
545 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800546 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000547 }
548
Kevin DuBois23e678a2020-11-20 14:54:05 -0800549 std::vector<V1_2::OutputShape> outputShapes(request.outputs.size());
Kevin May42477c12020-03-26 13:34:14 +0000550
551 auto errorStatus = PrepareMemoryForOutputs(outputs, outputShapes, request, memPools);
552 if (errorStatus != V1_3::ErrorStatus::NONE)
553 {
554 return {errorStatus, outputShapes, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
555 }
556 }
557 catch (armnn::Exception& e)
558 {
559 ALOGW("armnn::Exception caught while preparing for EnqueueWorkload: %s", e.what());
Kevin DuBois23e678a2020-11-20 14:54:05 -0800560 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000561 }
562 catch (std::exception& e)
563 {
564 ALOGE("std::exception caught while preparing for EnqueueWorkload: %s", e.what());
Kevin DuBois23e678a2020-11-20 14:54:05 -0800565 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000566 }
567
568 return {V1_3::ErrorStatus::NONE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
569}
570
571template<typename HalVersion>
572template<typename CallbackContext>
573Return<void> ArmnnPreparedModel_1_3<HalVersion>::ExecuteSynchronously(const V1_3::Request& request,
574 CallbackContext cbCtx)
575{
Kevin DuBois23e678a2020-11-20 14:54:05 -0800576 if (cbCtx.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000577 {
578 cbCtx.ctx.driverStart = Now();
579 }
580
581 if (!android::nn::validateRequest(convertToV1_3(request), m_Model))
582 {
583 ALOGE("ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
584 cbCtx.callback(V1_3::ErrorStatus::INVALID_ARGUMENT,
585 {},
586 g_NoTiming,
587 "ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
588 return Void();
589 }
590
591 if (!android::nn::validateRequest(request, m_Model))
592 {
593 ALOGE("ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
594 cbCtx.callback(V1_3::ErrorStatus::INVALID_ARGUMENT,
595 {},
596 g_NoTiming,
597 "ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
Sadik Armaganef8a3932020-04-09 17:21:50 +0100598 return Void();
Kevin May42477c12020-03-26 13:34:14 +0000599 }
600
601
602 // map the memory pool into shared pointers
603 // use a shared memory pools vector on the heap, as it is passed to the request thread
604 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
605
606 // allocate the tensors on the heap, as they are passed to the request thread
607 auto inputs = std::make_shared<armnn::InputTensors>();
608 auto outputs = std::make_shared<armnn::OutputTensors>();
609
610 auto [status, outputShapes, timing, message] = PrepareMemoryForIO(*inputs, *outputs, *memPools, request);
611 if (status != V1_3::ErrorStatus::NONE)
612 {
613 cbCtx.callback(status, outputShapes, timing, message);
Sadik Armaganef8a3932020-04-09 17:21:50 +0100614 return Void();
Kevin May42477c12020-03-26 13:34:14 +0000615 }
616
617 ALOGV("ArmnnPreparedModel_1_3::ExecuteSynchronously() before Execution");
618
619 ExecuteGraph(memPools, *inputs, *outputs, cbCtx);
620 return Void();
621}
622
623template<typename HalVersion>
624Return<void> ArmnnPreparedModel_1_3<HalVersion>::executeSynchronously(const V1_0::Request& request,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800625 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000626 executeSynchronously_cb cb)
627{
628 ALOGV("ArmnnPreparedModel_1_3::executeSynchronously(): %s", GetModelSummary(m_Model).c_str());
629 m_RequestCount++;
630
631 if (cb == nullptr)
632 {
633 ALOGE("ArmnnPreparedModel_1_3::executeSynchronously invalid callback passed");
634 return Void();
635 }
636
637 auto cbWrapper = [cb](V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800638 std::vector<V1_2::OutputShape> outputShapes,
639 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000640 std::string)
641 {
642 cb(convertToV1_0(errorStatus), outputShapes, timing);
643 };
644
645 CallbackContext_1_3 cbCtx;
646 cbCtx.callback = cbWrapper;
647 cbCtx.ctx.measureTimings = measureTiming;
648
649 ExecuteSynchronously(convertToV1_3(request), cbCtx);
650 return Void();
651}
652
653template<typename HalVersion>
Kevin May352d8382020-03-31 15:03:42 +0100654Return<void> ArmnnPreparedModel_1_3<HalVersion>::executeSynchronously_1_3(
655 const V1_3::Request& request,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800656 V1_2::MeasureTiming measureTiming,
Kevin May352d8382020-03-31 15:03:42 +0100657 const V1_3::OptionalTimePoint& deadline,
658 const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
659 executeSynchronously_1_3_cb cb)
Kevin May42477c12020-03-26 13:34:14 +0000660{
661 ALOGV("ArmnnPreparedModel_1_3::executeSynchronously_1_3(): %s", GetModelSummary(m_Model).c_str());
662 m_RequestCount++;
663
664 if (cb == nullptr)
665 {
666 ALOGE("ArmnnPreparedModel_1_3::executeSynchronously_1_3 invalid callback passed");
667 return Void();
668 }
669
Kevin DuBois23e678a2020-11-20 14:54:05 -0800670 if (deadline.getDiscriminator() != V1_3::OptionalTimePoint::hidl_discriminator::none)
Kevin May42477c12020-03-26 13:34:14 +0000671 {
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100672 ALOGW("ArmnnPreparedModel_1_3::executeSynchronously_1_3 parameter deadline is set but not supported.");
Kevin May42477c12020-03-26 13:34:14 +0000673 }
674
Kevin DuBois23e678a2020-11-20 14:54:05 -0800675 if (loopTimeoutDuration.getDiscriminator() != V1_3::OptionalTimeoutDuration::hidl_discriminator::none)
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100676 {
677 ALOGW(
678 "ArmnnPreparedModel_1_3::executeSynchronously_1_3 parameter loopTimeoutDuration is set but not supported.");
Kevin May352d8382020-03-31 15:03:42 +0100679 }
680
Kevin May42477c12020-03-26 13:34:14 +0000681 auto cbWrapper = [cb](V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800682 std::vector<V1_2::OutputShape> outputShapes,
683 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000684 std::string)
685 {
686 cb(errorStatus, outputShapes, timing);
687 };
688
689 CallbackContext_1_3 cbCtx;
690 cbCtx.callback = cbWrapper;
691 cbCtx.ctx.measureTimings = measureTiming;
692
693 ExecuteSynchronously(request, cbCtx);
694 return Void();
695}
696
697template<typename HalVersion>
698Return<void> ArmnnPreparedModel_1_3<HalVersion>::configureExecutionBurst(
699 const sp<V1_2::IBurstCallback>& callback,
700 const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
701 const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
702 V1_3::IPreparedModel::configureExecutionBurst_cb cb)
703{
704 ALOGV("ArmnnPreparedModel_1_3::configureExecutionBurst");
705 const sp<V1_2::IBurstContext> burst = ExecutionBurstServer::create(callback,
706 requestChannel,
707 resultChannel,
708 this);
709
710 if (burst == nullptr)
711 {
712 cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
713 }
714 else
715 {
716 cb(V1_0::ErrorStatus::NONE, burst);
717 }
718 return Void();
719}
720
721template<typename HalVersion>
722template<typename CallbackContext>
Sadik Armagand7be72e2020-04-23 12:56:05 +0100723Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::ExecuteGraph(
Kevin May42477c12020-03-26 13:34:14 +0000724 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
725 armnn::InputTensors& inputTensors,
726 armnn::OutputTensors& outputTensors,
727 CallbackContext cb)
728{
729 ALOGV("ArmnnPreparedModel_1_3::ExecuteGraph(...)");
730
Kevin May42477c12020-03-26 13:34:14 +0000731 DumpTensorsIfRequired("Input", inputTensors);
732
Kevin DuBois23e678a2020-11-20 14:54:05 -0800733 std::vector<V1_2::OutputShape> outputShapes(outputTensors.size());
Kevin May42477c12020-03-26 13:34:14 +0000734 for (unsigned int i = 0; i < outputTensors.size(); i++)
735 {
736 std::pair<int, armnn::Tensor> outputTensorPair = outputTensors[i];
737 const armnn::Tensor outputTensor = outputTensorPair.second;
738 const armnn::TensorInfo outputTensorInfo = outputTensor.GetInfo();
739
740 outputShapes[i] = ComputeShape(outputTensorInfo);
741 }
742
743 // run it
744 try
745 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800746 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000747 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100748 cb.ctx.deviceStart = Now();
Kevin May42477c12020-03-26 13:34:14 +0000749 }
750
751 armnn::Status status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
752
Kevin DuBois23e678a2020-11-20 14:54:05 -0800753 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000754 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100755 cb.ctx.deviceEnd = Now();
Kevin May42477c12020-03-26 13:34:14 +0000756 }
757 if (status != armnn::Status::Success)
758 {
759 ALOGW("EnqueueWorkload failed");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100760 cb.callback(V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
761 return V1_3::ErrorStatus::GENERAL_FAILURE;
Kevin May42477c12020-03-26 13:34:14 +0000762 }
763 }
764 catch (armnn::Exception& e)
765 {
766 ALOGW("armnn:Exception caught from EnqueueWorkload: %s", e.what());
767 cb.callback(V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100768 return V1_3::ErrorStatus::GENERAL_FAILURE;
Kevin May42477c12020-03-26 13:34:14 +0000769 }
770 catch (std::exception& e)
771 {
772 ALOGE("std::exception caught from EnqueueWorkload: %s", e.what());
773 cb.callback(V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100774 return V1_3::ErrorStatus::GENERAL_FAILURE;
Kevin May42477c12020-03-26 13:34:14 +0000775 }
776
777 CommitPools(*pMemPools);
778
779 DumpTensorsIfRequired("Output", outputTensors);
780
Kevin DuBois23e678a2020-11-20 14:54:05 -0800781 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000782 {
Kevin May949a69e2020-04-24 10:21:40 +0100783 cb.ctx.driverEnd = Now();
Kevin DuBois23e678a2020-11-20 14:54:05 -0800784 V1_2::Timing timing;
Sadik Armagand7be72e2020-04-23 12:56:05 +0100785 timing.timeOnDevice = MicrosecondsDuration(cb.ctx.deviceEnd, cb.ctx.deviceStart);
Kevin May949a69e2020-04-24 10:21:40 +0100786 timing.timeInDriver = MicrosecondsDuration(cb.ctx.driverEnd, cb.ctx.driverStart);
Kevin DuBois17c424b2020-11-20 14:18:03 -0800787 ALOGV("ArmnnPreparedModel_1_3::execute timing - Device = %" PRIu64 " Driver = %" PRIu64, timing.timeOnDevice,
Kevin May42477c12020-03-26 13:34:14 +0000788 timing.timeInDriver);
789 cb.callback(V1_3::ErrorStatus::NONE, outputShapes, timing, "ArmnnPreparedModel_1_3::ExecuteGraph");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100790 } else
791 {
Kevin May42477c12020-03-26 13:34:14 +0000792 cb.callback(V1_3::ErrorStatus::NONE, outputShapes, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
793 }
Sadik Armagand7be72e2020-04-23 12:56:05 +0100794 return V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000795}
796
797template<typename HalVersion>
798bool ArmnnPreparedModel_1_3<HalVersion>::ExecuteWithDummyInputs()
799{
800 std::vector<std::vector<char>> storage;
801 armnn::InputTensors inputTensors;
802 for (unsigned int i = 0; i < getMainModel(m_Model).inputIndexes.size(); i++)
803 {
804 const armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
805 storage.emplace_back(inputTensorInfo.GetNumBytes());
806 const armnn::ConstTensor inputTensor(inputTensorInfo, storage.back().data());
807
808 inputTensors.emplace_back(i, inputTensor);
809 }
810
811 armnn::OutputTensors outputTensors;
812 for (unsigned int i = 0; i < getMainModel(m_Model).outputIndexes.size(); i++)
813 {
814 const armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
815 storage.emplace_back(outputTensorInfo.GetNumBytes());
816 const armnn::Tensor outputTensor(outputTensorInfo, storage.back().data());
817
818 outputTensors.emplace_back(i, outputTensor);
819 }
820
Kevin DuBois23e678a2020-11-20 14:54:05 -0800821 auto nullCallback = [](V1_3::ErrorStatus, std::vector<V1_2::OutputShape>, const V1_2::Timing&, std::string) {};
Kevin May42477c12020-03-26 13:34:14 +0000822 CallbackContext_1_3 callbackContext;
823 callbackContext.callback = nullCallback;
Kevin DuBois23e678a2020-11-20 14:54:05 -0800824 callbackContext.ctx.measureTimings = V1_2::MeasureTiming::NO;
Kevin May42477c12020-03-26 13:34:14 +0000825 auto memPools = std::make_shared<std::vector<::android::nn::RunTimePoolInfo>>();
Sadik Armagand7be72e2020-04-23 12:56:05 +0100826
827 auto errorStatus = ExecuteGraph(memPools,
828 inputTensors,
829 outputTensors,
830 callbackContext);
831 return errorStatus == V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000832}
833
834template<typename HalVersion>
835Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::Execute(const V1_3::Request& request,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800836 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000837 CallbackAsync_1_3 callback)
838{
839 ExecutionContext_1_3 ctx;
Kevin DuBois23e678a2020-11-20 14:54:05 -0800840 if (measureTiming == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000841 {
842 ctx.measureTimings = measureTiming;
843 ctx.driverStart = Now();
844 }
845
846 ALOGV("ArmnnPreparedModel_1_3::execute(): %s", GetModelSummary(m_Model).c_str());
847 m_RequestCount++;
848
849 if (!android::nn::validateRequest(request, m_Model))
850 {
851 callback(V1_3::ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute");
852 return V1_3::ErrorStatus::INVALID_ARGUMENT;
853 }
854
855 if (!m_RequestInputsAndOutputsDumpDir.empty())
856 {
857 ALOGD("Dumping inputs and outputs for request %" PRIuPTR, reinterpret_cast<std::uintptr_t>(&callback));
858 }
859
860 // map the memory pool into shared pointers
861 // use a shared memory pools vector on the heap, as it is passed to the request thread
862 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
863
864 // allocate the tensors on the heap, as they are passed to the request thread
865 auto inputTensors = std::make_shared<armnn::InputTensors>();
866 auto outputTensors = std::make_shared<armnn::OutputTensors>();
867
868 auto [status, outShapes, timing, message] = PrepareMemoryForIO(*inputTensors, *outputTensors,
869 *memPools, request);
870 if (status != V1_3::ErrorStatus::NONE)
871 {
872 callback(status, outShapes, timing, message);
873 }
874
875 switch(status)
876 {
877 case V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
878 return V1_3::ErrorStatus::NONE;
879 case V1_3::ErrorStatus::GENERAL_FAILURE:
880 return V1_3::ErrorStatus::GENERAL_FAILURE;
881 default:
882 {}
883 }
884
885 ALOGV("ArmnnPreparedModel_1_3::execute(...) before PostMsg");
886
887 // post the request for asynchronous execution
888 CallbackContext_1_3 cb;
889 cb.callback = callback;
890 cb.ctx = ctx;
891 m_RequestThread.PostMsg(this, memPools, inputTensors, outputTensors, cb);
892 ALOGV("ArmnnPreparedModel_1_3::execute(...) after PostMsg");
893 return V1_3::ErrorStatus::NONE;
894}
895
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100896template<typename HalVersion>
897V1_3::Priority ArmnnPreparedModel_1_3<HalVersion>::GetModelPriority()
898{
899 return m_ModelPriority;
900}
901
Kevin May42477c12020-03-26 13:34:14 +0000902#ifdef ARMNN_ANDROID_NN_V1_3
903template class ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>;
Sadik Armagand7be72e2020-04-23 12:56:05 +0100904template Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>::ExecuteGraph<CallbackContext_1_3>(
Kevin May42477c12020-03-26 13:34:14 +0000905 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
906 armnn::InputTensors& pInputTensors,
907 armnn::OutputTensors& pOutputTensors,
908 CallbackContext_1_3 cb);
909#endif
910
911} // namespace armnn_driver