blob: 353bdafdc6ddabaec732fd77d7791a252bc86fe2 [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
Guus Sliepencef0c082023-05-23 20:34:42 +0000346 if (fenceNativeHandle->numFds != 1)
347 {
348 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
349 return Void();
350 }
351
Sadik Armagand7be72e2020-04-23 12:56:05 +0100352 if (sync_wait(fenceNativeHandle->data[0], -1) < 0)
353 {
354 ALOGE("ArmnnPreparedModel_1_3::executeFenced sync fence failed.");
Kevin DuBois23e678a2020-11-20 14:54:05 -0800355 cb(V1_3::ErrorStatus::GENERAL_FAILURE, hidl_handle(nullptr), nullptr);
Sadik Armagand7be72e2020-04-23 12:56:05 +0100356 return Void();
357 }
358 }
359
360 TimePoint fenceExecutionStart;
Kevin DuBois23e678a2020-11-20 14:54:05 -0800361 if (measureTiming == V1_2::MeasureTiming::YES)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100362 {
363 fenceExecutionStart = Now();
364 }
365
366 // map the memory pool into shared pointers
367 // use a shared memory pools vector on the heap, as it is passed to the request thread
368 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
369
370 // allocate the tensors on the heap, as they are passed to the request thread
371 auto inputs = std::make_shared<armnn::InputTensors>();
372 auto outputs = std::make_shared<armnn::OutputTensors>();
373
374 auto [status, outShapes, timings, message] = PrepareMemoryForIO(*inputs, *outputs, *memPools, request);
375 if (status != V1_3::ErrorStatus::NONE)
376 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800377 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Sadik Armagand7be72e2020-04-23 12:56:05 +0100378 return Void();
379 }
380
381 ALOGV("ArmnnPreparedModel_1_3::executeFenced(...) before ExecuteGraph");
382
383 // call it with nullCallback for now as we will report the error status from here..
Kevin DuBois23e678a2020-11-20 14:54:05 -0800384 auto nullCallback = [](V1_3::ErrorStatus, std::vector<V1_2::OutputShape>, const V1_2::Timing&, std::string) {};
Sadik Armagand7be72e2020-04-23 12:56:05 +0100385 CallbackContext_1_3 cbCtx;
386 cbCtx.callback = nullCallback;
387 cbCtx.ctx = ctx;
388
389 auto errorStatus = ExecuteGraph(memPools, *inputs, *outputs, cbCtx);
390 if (errorStatus != V1_3::ErrorStatus::NONE)
391 {
392 cb(errorStatus, hidl_handle(nullptr), nullptr);
393 return Void();
394 }
395 ALOGV("ArmnnPreparedModel_1_3::executeFenced(...) after ExecuteGraph");
396
Kevin DuBois23e678a2020-11-20 14:54:05 -0800397 V1_2::Timing timing = g_NoTiming;
398 V1_2::Timing fenceTiming = g_NoTiming;
399 if (measureTiming == V1_2::MeasureTiming::YES)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100400 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100401 fenceTiming.timeOnDevice = MicrosecondsDuration(ctx.deviceEnd, ctx.deviceStart);
Kevin May949a69e2020-04-24 10:21:40 +0100402 fenceTiming.timeInDriver = MicrosecondsDuration(ctx.driverEnd, fenceExecutionStart);
Kevin DuBois17c424b2020-11-20 14:18:03 -0800403 ALOGV("ArmnnPreparedModel_1_3::fenceFinishExecutionTiming - Device = %" PRIu64 " Driver = %" PRIu64,
Sadik Armagand7be72e2020-04-23 12:56:05 +0100404 fenceTiming.timeOnDevice, fenceTiming.timeInDriver);
405 }
406
407 sp<ArmnnFencedExecutionCallback> armnnFencedExecutionCallback =
Kevin DuBois23e678a2020-11-20 14:54:05 -0800408 new ArmnnFencedExecutionCallback(V1_3::ErrorStatus::NONE, timing, fenceTiming);
409 cb(V1_3::ErrorStatus::NONE, hidl_handle(nullptr), armnnFencedExecutionCallback);
Kevin May42477c12020-03-26 13:34:14 +0000410 return Void();
411}
412
413template<typename HalVersion>
414Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForInputs(
415 armnn::InputTensors& inputs,
416 const V1_3::Request& request,
417 const std::vector<android::nn::RunTimePoolInfo>& memPools)
418{
419 inputs.reserve(request.inputs.size());
420 for (unsigned int i = 0; i < request.inputs.size(); i++)
421 {
422 const auto& inputArg = request.inputs[i];
423
424 const armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
425 const armnn::Tensor inputTensor = GetTensorForRequestArgument(inputArg, inputTensorInfo, memPools);
426
Renato Grottesi6592f1a2022-12-14 17:04:16 +0000427 uint32_t poolIndex = inputArg.location.poolIndex;
428 if (poolIndex >= memPools.size())
429 {
430 ALOGE("Cannot execute request. Error converting request input %u to tensor: wrong poolIndex", i);
431 return V1_3::ErrorStatus::GENERAL_FAILURE;
432 }
433
434 uint8_t* inputTensorBegin = static_cast<uint8_t*>(inputTensor.GetMemoryArea());
435 if (inputTensorBegin == nullptr)
Kevin May42477c12020-03-26 13:34:14 +0000436 {
437 ALOGE("Cannot execute request. Error converting request input %u to tensor", i);
438 return V1_3::ErrorStatus::GENERAL_FAILURE;
439 }
440
Renato Grottesi6592f1a2022-12-14 17:04:16 +0000441 const size_t inputTensorSize = inputTensorInfo.GetNumBytes();
442 uint8_t* memoryPoolBegin = memPools[poolIndex].getBuffer();
443 uint32_t memoryPoolSize = memPools[poolIndex].getSize();
444 bool inputTensorIsOutOfMemoryRage = (inputTensorBegin + inputTensorSize) > (memoryPoolBegin + memoryPoolSize);
445
446 if (inputTensorIsOutOfMemoryRage)
447 {
448 ALOGE("Cannot execute request. Error converting request input %u to tensor: out of Memory Pool", i);
449 return V1_3::ErrorStatus::GENERAL_FAILURE;
450 }
451
Kevin May42477c12020-03-26 13:34:14 +0000452 inputs.emplace_back(i, inputTensor);
453 }
454
455 return V1_3::ErrorStatus::NONE;
456}
457
458template<typename HalVersion>
459Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForOutputs(
460 armnn::OutputTensors& outputs,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800461 std::vector<V1_2::OutputShape> &outputShapes,
Kevin May42477c12020-03-26 13:34:14 +0000462 const V1_3::Request& request,
463 const std::vector<android::nn::RunTimePoolInfo>& memPools)
464{
465 outputs.reserve(request.outputs.size());
466 for (unsigned int i = 0; i < request.outputs.size(); i++)
467 {
468 const auto& outputArg = request.outputs[i];
469
Finn Williamsa4983ce2020-07-23 12:55:12 +0100470 armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
Kevin May42477c12020-03-26 13:34:14 +0000471 const armnn::Tensor outputTensor = GetTensorForRequestArgument(outputArg, outputTensorInfo, memPools);
Renato Grottesi6592f1a2022-12-14 17:04:16 +0000472 uint8_t* outputTensorBegin = static_cast<uint8_t*>(outputTensor.GetMemoryArea());
473 if (outputTensorBegin == nullptr)
Kevin May42477c12020-03-26 13:34:14 +0000474 {
475 ALOGE("Cannot execute request. Error converting request output %u to tensor", i);
476 return V1_3::ErrorStatus::GENERAL_FAILURE;
477 }
478
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100479 const size_t outputSize = outputTensorInfo.GetNumBytes();
Renato Grottesi6592f1a2022-12-14 17:04:16 +0000480 uint32_t poolIndex = outputArg.location.poolIndex;
481 if (poolIndex >= memPools.size())
482 {
483 ALOGE("Cannot execute request. Error converting request output %u to tensor: wrong poolIndex", i);
484 return V1_3::ErrorStatus::GENERAL_FAILURE;
485 }
486
487 uint8_t* memoryPoolBegin = memPools[poolIndex].getBuffer();
488 uint32_t memoryPoolSize = memPools[poolIndex].getSize();
489 bool outputTensorIsOutOfMemoryRage = (outputTensorBegin + outputSize) > (memoryPoolBegin + memoryPoolSize);
490 if (outputTensorIsOutOfMemoryRage)
491 {
492 ALOGE("Cannot execute request. Error converting request output %u to tensor: out of Memory Pool", i);
493 return V1_3::ErrorStatus::GENERAL_FAILURE;
494 }
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100495
Finn Williamsa4983ce2020-07-23 12:55:12 +0100496 unsigned int count = 0;
497 std::for_each(outputArg.dimensions.begin(), outputArg.dimensions.end(), [&](auto dim)
498 {
499 if (dim != 0)
500 {
501 outputTensorInfo.GetShape()[count] = dim;
502 }
503 else
504 {
505 outputTensorInfo.GetShape()[count] = outputArg.dimensions.size();
506 }
507
508 count++;
509 });
510
Finn Williamsa4983ce2020-07-23 12:55:12 +0100511 outputs.emplace_back(i, outputTensor);
512 outputShapes[i] = ComputeShape(outputTensorInfo);
513
514 if (outputArg.location.length < outputSize)
515 {
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100516 ALOGW("ArmnnPreparedModel_1_3::Execute failed outputArg.location.length (%s) < outputSize (%s)",
517 std::to_string(outputArg.location.length).c_str(), std::to_string(outputSize).c_str());
Finn Williamsa4983ce2020-07-23 12:55:12 +0100518 outputShapes[i].isSufficient = false;
519 return V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
520 }
521
Kevin DuBoisbbcff192020-11-20 14:36:59 -0800522 const size_t bufferSize = memPools.at(outputArg.location.poolIndex).getSize();
Kevin May42477c12020-03-26 13:34:14 +0000523 if (bufferSize < outputSize)
524 {
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100525 ALOGW("ArmnnPreparedModel_1_3::Execute failed bufferSize (%s) < outputSize (%s)",
526 std::to_string(bufferSize).c_str(), std::to_string(outputSize).c_str());
Finn Williamsa4983ce2020-07-23 12:55:12 +0100527 outputShapes[i].isSufficient = false;
Kevin May42477c12020-03-26 13:34:14 +0000528 return V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
529 }
Kevin May42477c12020-03-26 13:34:14 +0000530 }
531
532 return V1_3::ErrorStatus::NONE;
533}
534
535template<typename HalVersion>
Kevin DuBois23e678a2020-11-20 14:54:05 -0800536std::tuple<V1_3::ErrorStatus, hidl_vec<V1_2::OutputShape>, V1_2::Timing, std::string>
Kevin May42477c12020-03-26 13:34:14 +0000537 ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForIO(armnn::InputTensors& inputs,
538 armnn::OutputTensors& outputs,
539 std::vector<android::nn::RunTimePoolInfo>& memPools,
540 const V1_3::Request& request)
541{
Kevin DuBois7bd76002020-11-23 08:20:27 -0800542 if (!setRunTimePoolInfosFromMemoryPools(&memPools, uncheckedConvert(request.pools)))
Kevin May42477c12020-03-26 13:34:14 +0000543 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800544 return {V1_3::ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000545 }
546
547 // add the inputs and outputs with their data
548 try
549 {
550 if (PrepareMemoryForInputs(inputs, request, memPools) != V1_3::ErrorStatus::NONE)
551 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800552 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000553 }
554
Kevin DuBois23e678a2020-11-20 14:54:05 -0800555 std::vector<V1_2::OutputShape> outputShapes(request.outputs.size());
Kevin May42477c12020-03-26 13:34:14 +0000556
557 auto errorStatus = PrepareMemoryForOutputs(outputs, outputShapes, request, memPools);
558 if (errorStatus != V1_3::ErrorStatus::NONE)
559 {
560 return {errorStatus, outputShapes, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
561 }
562 }
563 catch (armnn::Exception& e)
564 {
565 ALOGW("armnn::Exception caught while preparing for EnqueueWorkload: %s", e.what());
Kevin DuBois23e678a2020-11-20 14:54:05 -0800566 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000567 }
568 catch (std::exception& e)
569 {
570 ALOGE("std::exception caught while preparing for EnqueueWorkload: %s", e.what());
Kevin DuBois23e678a2020-11-20 14:54:05 -0800571 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000572 }
573
574 return {V1_3::ErrorStatus::NONE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
575}
576
577template<typename HalVersion>
578template<typename CallbackContext>
579Return<void> ArmnnPreparedModel_1_3<HalVersion>::ExecuteSynchronously(const V1_3::Request& request,
580 CallbackContext cbCtx)
581{
Kevin DuBois23e678a2020-11-20 14:54:05 -0800582 if (cbCtx.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000583 {
584 cbCtx.ctx.driverStart = Now();
585 }
586
587 if (!android::nn::validateRequest(convertToV1_3(request), m_Model))
588 {
589 ALOGE("ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
590 cbCtx.callback(V1_3::ErrorStatus::INVALID_ARGUMENT,
591 {},
592 g_NoTiming,
593 "ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
594 return Void();
595 }
596
597 if (!android::nn::validateRequest(request, m_Model))
598 {
599 ALOGE("ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
600 cbCtx.callback(V1_3::ErrorStatus::INVALID_ARGUMENT,
601 {},
602 g_NoTiming,
603 "ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
Sadik Armaganef8a3932020-04-09 17:21:50 +0100604 return Void();
Kevin May42477c12020-03-26 13:34:14 +0000605 }
606
607
608 // map the memory pool into shared pointers
609 // use a shared memory pools vector on the heap, as it is passed to the request thread
610 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
611
612 // allocate the tensors on the heap, as they are passed to the request thread
613 auto inputs = std::make_shared<armnn::InputTensors>();
614 auto outputs = std::make_shared<armnn::OutputTensors>();
615
616 auto [status, outputShapes, timing, message] = PrepareMemoryForIO(*inputs, *outputs, *memPools, request);
617 if (status != V1_3::ErrorStatus::NONE)
618 {
619 cbCtx.callback(status, outputShapes, timing, message);
Sadik Armaganef8a3932020-04-09 17:21:50 +0100620 return Void();
Kevin May42477c12020-03-26 13:34:14 +0000621 }
622
623 ALOGV("ArmnnPreparedModel_1_3::ExecuteSynchronously() before Execution");
624
625 ExecuteGraph(memPools, *inputs, *outputs, cbCtx);
626 return Void();
627}
628
629template<typename HalVersion>
630Return<void> ArmnnPreparedModel_1_3<HalVersion>::executeSynchronously(const V1_0::Request& request,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800631 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000632 executeSynchronously_cb cb)
633{
634 ALOGV("ArmnnPreparedModel_1_3::executeSynchronously(): %s", GetModelSummary(m_Model).c_str());
635 m_RequestCount++;
636
637 if (cb == nullptr)
638 {
639 ALOGE("ArmnnPreparedModel_1_3::executeSynchronously invalid callback passed");
640 return Void();
641 }
642
643 auto cbWrapper = [cb](V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800644 std::vector<V1_2::OutputShape> outputShapes,
645 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000646 std::string)
647 {
648 cb(convertToV1_0(errorStatus), outputShapes, timing);
649 };
650
651 CallbackContext_1_3 cbCtx;
652 cbCtx.callback = cbWrapper;
653 cbCtx.ctx.measureTimings = measureTiming;
654
655 ExecuteSynchronously(convertToV1_3(request), cbCtx);
656 return Void();
657}
658
659template<typename HalVersion>
Kevin May352d8382020-03-31 15:03:42 +0100660Return<void> ArmnnPreparedModel_1_3<HalVersion>::executeSynchronously_1_3(
661 const V1_3::Request& request,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800662 V1_2::MeasureTiming measureTiming,
Kevin May352d8382020-03-31 15:03:42 +0100663 const V1_3::OptionalTimePoint& deadline,
664 const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
665 executeSynchronously_1_3_cb cb)
Kevin May42477c12020-03-26 13:34:14 +0000666{
667 ALOGV("ArmnnPreparedModel_1_3::executeSynchronously_1_3(): %s", GetModelSummary(m_Model).c_str());
668 m_RequestCount++;
669
670 if (cb == nullptr)
671 {
672 ALOGE("ArmnnPreparedModel_1_3::executeSynchronously_1_3 invalid callback passed");
673 return Void();
674 }
675
Kevin DuBois23e678a2020-11-20 14:54:05 -0800676 if (deadline.getDiscriminator() != V1_3::OptionalTimePoint::hidl_discriminator::none)
Kevin May42477c12020-03-26 13:34:14 +0000677 {
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100678 ALOGW("ArmnnPreparedModel_1_3::executeSynchronously_1_3 parameter deadline is set but not supported.");
Kevin May42477c12020-03-26 13:34:14 +0000679 }
680
Kevin DuBois23e678a2020-11-20 14:54:05 -0800681 if (loopTimeoutDuration.getDiscriminator() != V1_3::OptionalTimeoutDuration::hidl_discriminator::none)
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100682 {
683 ALOGW(
684 "ArmnnPreparedModel_1_3::executeSynchronously_1_3 parameter loopTimeoutDuration is set but not supported.");
Kevin May352d8382020-03-31 15:03:42 +0100685 }
686
Kevin May42477c12020-03-26 13:34:14 +0000687 auto cbWrapper = [cb](V1_3::ErrorStatus errorStatus,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800688 std::vector<V1_2::OutputShape> outputShapes,
689 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000690 std::string)
691 {
692 cb(errorStatus, outputShapes, timing);
693 };
694
695 CallbackContext_1_3 cbCtx;
696 cbCtx.callback = cbWrapper;
697 cbCtx.ctx.measureTimings = measureTiming;
698
699 ExecuteSynchronously(request, cbCtx);
700 return Void();
701}
702
703template<typename HalVersion>
704Return<void> ArmnnPreparedModel_1_3<HalVersion>::configureExecutionBurst(
705 const sp<V1_2::IBurstCallback>& callback,
706 const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
707 const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
708 V1_3::IPreparedModel::configureExecutionBurst_cb cb)
709{
710 ALOGV("ArmnnPreparedModel_1_3::configureExecutionBurst");
711 const sp<V1_2::IBurstContext> burst = ExecutionBurstServer::create(callback,
712 requestChannel,
713 resultChannel,
714 this);
715
716 if (burst == nullptr)
717 {
718 cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
719 }
720 else
721 {
722 cb(V1_0::ErrorStatus::NONE, burst);
723 }
724 return Void();
725}
726
727template<typename HalVersion>
728template<typename CallbackContext>
Sadik Armagand7be72e2020-04-23 12:56:05 +0100729Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::ExecuteGraph(
Kevin May42477c12020-03-26 13:34:14 +0000730 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
731 armnn::InputTensors& inputTensors,
732 armnn::OutputTensors& outputTensors,
733 CallbackContext cb)
734{
735 ALOGV("ArmnnPreparedModel_1_3::ExecuteGraph(...)");
736
Kevin May42477c12020-03-26 13:34:14 +0000737 DumpTensorsIfRequired("Input", inputTensors);
738
Kevin DuBois23e678a2020-11-20 14:54:05 -0800739 std::vector<V1_2::OutputShape> outputShapes(outputTensors.size());
Kevin May42477c12020-03-26 13:34:14 +0000740 for (unsigned int i = 0; i < outputTensors.size(); i++)
741 {
742 std::pair<int, armnn::Tensor> outputTensorPair = outputTensors[i];
743 const armnn::Tensor outputTensor = outputTensorPair.second;
744 const armnn::TensorInfo outputTensorInfo = outputTensor.GetInfo();
745
746 outputShapes[i] = ComputeShape(outputTensorInfo);
747 }
748
749 // run it
750 try
751 {
Kevin DuBois23e678a2020-11-20 14:54:05 -0800752 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000753 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100754 cb.ctx.deviceStart = Now();
Kevin May42477c12020-03-26 13:34:14 +0000755 }
756
757 armnn::Status status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
758
Kevin DuBois23e678a2020-11-20 14:54:05 -0800759 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000760 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100761 cb.ctx.deviceEnd = Now();
Kevin May42477c12020-03-26 13:34:14 +0000762 }
763 if (status != armnn::Status::Success)
764 {
765 ALOGW("EnqueueWorkload failed");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100766 cb.callback(V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
767 return V1_3::ErrorStatus::GENERAL_FAILURE;
Kevin May42477c12020-03-26 13:34:14 +0000768 }
769 }
770 catch (armnn::Exception& e)
771 {
772 ALOGW("armnn: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 catch (std::exception& e)
777 {
778 ALOGE("std::exception caught from EnqueueWorkload: %s", e.what());
779 cb.callback(V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100780 return V1_3::ErrorStatus::GENERAL_FAILURE;
Kevin May42477c12020-03-26 13:34:14 +0000781 }
782
783 CommitPools(*pMemPools);
784
785 DumpTensorsIfRequired("Output", outputTensors);
786
Kevin DuBois23e678a2020-11-20 14:54:05 -0800787 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000788 {
Kevin May949a69e2020-04-24 10:21:40 +0100789 cb.ctx.driverEnd = Now();
Kevin DuBois23e678a2020-11-20 14:54:05 -0800790 V1_2::Timing timing;
Sadik Armagand7be72e2020-04-23 12:56:05 +0100791 timing.timeOnDevice = MicrosecondsDuration(cb.ctx.deviceEnd, cb.ctx.deviceStart);
Kevin May949a69e2020-04-24 10:21:40 +0100792 timing.timeInDriver = MicrosecondsDuration(cb.ctx.driverEnd, cb.ctx.driverStart);
Kevin DuBois17c424b2020-11-20 14:18:03 -0800793 ALOGV("ArmnnPreparedModel_1_3::execute timing - Device = %" PRIu64 " Driver = %" PRIu64, timing.timeOnDevice,
Kevin May42477c12020-03-26 13:34:14 +0000794 timing.timeInDriver);
795 cb.callback(V1_3::ErrorStatus::NONE, outputShapes, timing, "ArmnnPreparedModel_1_3::ExecuteGraph");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100796 } else
797 {
Kevin May42477c12020-03-26 13:34:14 +0000798 cb.callback(V1_3::ErrorStatus::NONE, outputShapes, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
799 }
Sadik Armagand7be72e2020-04-23 12:56:05 +0100800 return V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000801}
802
803template<typename HalVersion>
804bool ArmnnPreparedModel_1_3<HalVersion>::ExecuteWithDummyInputs()
805{
806 std::vector<std::vector<char>> storage;
807 armnn::InputTensors inputTensors;
808 for (unsigned int i = 0; i < getMainModel(m_Model).inputIndexes.size(); i++)
809 {
810 const armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
811 storage.emplace_back(inputTensorInfo.GetNumBytes());
812 const armnn::ConstTensor inputTensor(inputTensorInfo, storage.back().data());
813
814 inputTensors.emplace_back(i, inputTensor);
815 }
816
817 armnn::OutputTensors outputTensors;
818 for (unsigned int i = 0; i < getMainModel(m_Model).outputIndexes.size(); i++)
819 {
820 const armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
821 storage.emplace_back(outputTensorInfo.GetNumBytes());
822 const armnn::Tensor outputTensor(outputTensorInfo, storage.back().data());
823
824 outputTensors.emplace_back(i, outputTensor);
825 }
826
Kevin DuBois23e678a2020-11-20 14:54:05 -0800827 auto nullCallback = [](V1_3::ErrorStatus, std::vector<V1_2::OutputShape>, const V1_2::Timing&, std::string) {};
Kevin May42477c12020-03-26 13:34:14 +0000828 CallbackContext_1_3 callbackContext;
829 callbackContext.callback = nullCallback;
Kevin DuBois23e678a2020-11-20 14:54:05 -0800830 callbackContext.ctx.measureTimings = V1_2::MeasureTiming::NO;
Kevin May42477c12020-03-26 13:34:14 +0000831 auto memPools = std::make_shared<std::vector<::android::nn::RunTimePoolInfo>>();
Sadik Armagand7be72e2020-04-23 12:56:05 +0100832
833 auto errorStatus = ExecuteGraph(memPools,
834 inputTensors,
835 outputTensors,
836 callbackContext);
837 return errorStatus == V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000838}
839
840template<typename HalVersion>
841Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::Execute(const V1_3::Request& request,
Kevin DuBois23e678a2020-11-20 14:54:05 -0800842 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000843 CallbackAsync_1_3 callback)
844{
845 ExecutionContext_1_3 ctx;
Kevin DuBois23e678a2020-11-20 14:54:05 -0800846 if (measureTiming == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000847 {
848 ctx.measureTimings = measureTiming;
849 ctx.driverStart = Now();
850 }
851
852 ALOGV("ArmnnPreparedModel_1_3::execute(): %s", GetModelSummary(m_Model).c_str());
853 m_RequestCount++;
854
855 if (!android::nn::validateRequest(request, m_Model))
856 {
857 callback(V1_3::ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute");
858 return V1_3::ErrorStatus::INVALID_ARGUMENT;
859 }
860
861 if (!m_RequestInputsAndOutputsDumpDir.empty())
862 {
863 ALOGD("Dumping inputs and outputs for request %" PRIuPTR, reinterpret_cast<std::uintptr_t>(&callback));
864 }
865
866 // map the memory pool into shared pointers
867 // use a shared memory pools vector on the heap, as it is passed to the request thread
868 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
869
870 // allocate the tensors on the heap, as they are passed to the request thread
871 auto inputTensors = std::make_shared<armnn::InputTensors>();
872 auto outputTensors = std::make_shared<armnn::OutputTensors>();
873
874 auto [status, outShapes, timing, message] = PrepareMemoryForIO(*inputTensors, *outputTensors,
875 *memPools, request);
876 if (status != V1_3::ErrorStatus::NONE)
877 {
878 callback(status, outShapes, timing, message);
879 }
880
881 switch(status)
882 {
883 case V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
884 return V1_3::ErrorStatus::NONE;
885 case V1_3::ErrorStatus::GENERAL_FAILURE:
886 return V1_3::ErrorStatus::GENERAL_FAILURE;
887 default:
888 {}
889 }
890
891 ALOGV("ArmnnPreparedModel_1_3::execute(...) before PostMsg");
892
893 // post the request for asynchronous execution
894 CallbackContext_1_3 cb;
895 cb.callback = callback;
896 cb.ctx = ctx;
897 m_RequestThread.PostMsg(this, memPools, inputTensors, outputTensors, cb);
898 ALOGV("ArmnnPreparedModel_1_3::execute(...) after PostMsg");
899 return V1_3::ErrorStatus::NONE;
900}
901
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100902template<typename HalVersion>
903V1_3::Priority ArmnnPreparedModel_1_3<HalVersion>::GetModelPriority()
904{
905 return m_ModelPriority;
906}
907
Kevin May42477c12020-03-26 13:34:14 +0000908#ifdef ARMNN_ANDROID_NN_V1_3
909template class ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>;
Sadik Armagand7be72e2020-04-23 12:56:05 +0100910template Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>::ExecuteGraph<CallbackContext_1_3>(
Kevin May42477c12020-03-26 13:34:14 +0000911 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
912 armnn::InputTensors& pInputTensors,
913 armnn::OutputTensors& pOutputTensors,
914 CallbackContext_1_3 cb);
915#endif
916
917} // namespace armnn_driver