blob: a50323607e60c4bd8a1f5652c58691a891e905a0 [file] [log] [blame]
Kevin May42477c12020-03-26 13:34:14 +00001//
Mike Kellye2d611e2021-10-14 12:35:58 +01002// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
Kevin May42477c12020-03-26 13:34:14 +00003// 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
Kevin May42477c12020-03-26 13:34:14 +000022#include <cinttypes>
23
Sadik Armagan188675f2021-02-12 17:16:42 +000024#ifdef ARMNN_ANDROID_S
25#include <LegacyUtils.h>
26#endif
27
Kevin May42477c12020-03-26 13:34:14 +000028using namespace android;
29using namespace android::hardware;
30
31namespace {
32
Sadik Armagan188675f2021-02-12 17:16:42 +000033static const V1_2::Timing g_NoTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX};
Kevin May42477c12020-03-26 13:34:14 +000034using namespace armnn_driver;
35using TimePoint = std::chrono::steady_clock::time_point;
36
37TimePoint Now()
38{
39 return std::chrono::steady_clock::now();
40}
41
42unsigned long MicrosecondsDuration(TimePoint endPoint, TimePoint startPoint)
43{
44 return static_cast<unsigned long>(std::chrono::duration_cast<std::chrono::microseconds>(
45 endPoint - startPoint).count());
46}
47
48void NotifyCallbackAndCheck(const ::android::sp<V1_0::IExecutionCallback>& callback,
49 V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +000050 std::vector<V1_2::OutputShape>,
51 const V1_2::Timing,
Kevin May42477c12020-03-26 13:34:14 +000052 std::string callingFunction)
53{
54 Return<void> returned = callback->notify(convertToV1_0(errorStatus));
55 // This check is required, if the callback fails and it isn't checked it will bring down the service
56 if (!returned.isOk())
57 {
58 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
59 callingFunction.c_str(), returned.description().c_str());
60 }
61}
62
63void NotifyCallbackAndCheck(const ::android::sp<V1_2::IExecutionCallback>& callback,
64 V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +000065 std::vector<V1_2::OutputShape> outputShapes,
66 const V1_2::Timing timing,
Kevin May42477c12020-03-26 13:34:14 +000067 std::string callingFunction)
68{
69 Return<void> returned = callback->notify_1_2(convertToV1_0(errorStatus), outputShapes, timing);
70 // This check is required, if the callback fails and it isn't checked it will bring down the service
71 if (!returned.isOk())
72 {
73 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
74 callingFunction.c_str(), returned.description().c_str());
75 }
76}
77
78void NotifyCallbackAndCheck(const ::android::sp<V1_3::IExecutionCallback>& callback,
79 V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +000080 std::vector<V1_2::OutputShape> outputShapes,
81 const V1_2::Timing timing,
Kevin May42477c12020-03-26 13:34:14 +000082 std::string callingFunction)
83{
84 Return<void> returned = callback->notify_1_3(errorStatus, outputShapes, timing);
85 // This check is required, if the callback fails and it isn't checked it will bring down the service
86 if (!returned.isOk())
87 {
88 ALOGE("ArmnnDriver::%s: hidl callback failed to return properly: %s",
89 callingFunction.c_str(), returned.description().c_str());
90 }
91}
92
Sadik Armagan188675f2021-02-12 17:16:42 +000093bool ValidateRequestArgument(const V1_0::RequestArgument& requestArg, const armnn::TensorInfo& tensorInfo)
Kevin May42477c12020-03-26 13:34:14 +000094{
95 if (requestArg.dimensions.size() != 0)
96 {
97 if (requestArg.dimensions.size() != tensorInfo.GetNumDimensions())
98 {
99 ALOGE("Mismatched dimensions (request argument: %zu, expected: %u)",
100 requestArg.dimensions.size(), tensorInfo.GetNumDimensions());
101 return false;
102 }
103
104 for (unsigned int d = 0; d < tensorInfo.GetNumDimensions(); ++d)
105 {
Finn Williamsa4983ce2020-07-23 12:55:12 +0100106 if (requestArg.dimensions[d] != 0 && requestArg.dimensions[d] != tensorInfo.GetShape()[d])
Kevin May42477c12020-03-26 13:34:14 +0000107 {
108 ALOGE("Mismatched size for dimension %d (request argument: %u, expected %u)",
109 d, requestArg.dimensions[d], tensorInfo.GetShape()[d]);
110 return false;
111 }
112 }
113 }
114
115 return true;
116}
117
Sadik Armagan188675f2021-02-12 17:16:42 +0000118armnn::Tensor GetTensorForRequestArgument(const V1_0::RequestArgument& requestArg,
Kevin May42477c12020-03-26 13:34:14 +0000119 const armnn::TensorInfo& tensorInfo,
120 const std::vector<::android::nn::RunTimePoolInfo>& requestPools)
121{
122 if (!ValidateRequestArgument(requestArg, tensorInfo))
123 {
124 return armnn::Tensor();
125 }
126
127 return armnn::Tensor(tensorInfo, GetMemoryFromPool(requestArg.location, requestPools));
128}
129
130inline std::string BuildTensorName(const char* tensorNamePrefix, std::size_t index)
131{
132 return tensorNamePrefix + std::to_string(index);
133}
134
135} // anonymous namespace
136
137using namespace android::hardware;
138
139namespace armnn_driver
140{
141
142template<typename HalVersion>
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100143RequestThread_1_3<ArmnnPreparedModel_1_3, HalVersion, CallbackContext_1_3>
Kevin May42477c12020-03-26 13:34:14 +0000144 ArmnnPreparedModel_1_3<HalVersion>::m_RequestThread;
145
146template<typename HalVersion>
Finn Williamsfdf2eae2021-07-08 13:07:19 +0100147std::unique_ptr<armnn::Threadpool> ArmnnPreparedModel_1_3<HalVersion>::m_Threadpool(nullptr);
148
149template<typename HalVersion>
Kevin May42477c12020-03-26 13:34:14 +0000150template<typename TensorBindingCollection>
151void ArmnnPreparedModel_1_3<HalVersion>::DumpTensorsIfRequired(char const* tensorNamePrefix,
152 const TensorBindingCollection& tensorBindings)
153{
154 if (!m_RequestInputsAndOutputsDumpDir.empty())
155 {
Colm Donelan08d9a1c2020-09-09 17:56:55 +0100156 const std::string requestName = std::to_string(m_NetworkId) + "_" + std::to_string(m_RequestCount) + ".dump";
Kevin May42477c12020-03-26 13:34:14 +0000157 for (std::size_t i = 0u; i < tensorBindings.size(); ++i)
158 {
159 DumpTensor(m_RequestInputsAndOutputsDumpDir,
160 requestName,
161 BuildTensorName(tensorNamePrefix, i),
162 tensorBindings[i].second);
163 }
164 }
165}
166
167template<typename HalVersion>
168ArmnnPreparedModel_1_3<HalVersion>::ArmnnPreparedModel_1_3(armnn::NetworkId networkId,
169 armnn::IRuntime* runtime,
170 const V1_3::Model& model,
171 const std::string& requestInputsAndOutputsDumpDir,
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100172 const bool gpuProfilingEnabled,
Finn Williamsd8fb5402021-05-19 20:52:00 +0100173 V1_3::Priority priority,
Finn Williamsca3a3e02021-06-11 15:04:02 +0100174 const bool asyncModelExecutionEnabled,
175 const unsigned int numberOfThreads)
Kevin May42477c12020-03-26 13:34:14 +0000176 : m_NetworkId(networkId)
177 , m_Runtime(runtime)
178 , m_Model(model)
179 , m_RequestCount(0)
180 , m_RequestInputsAndOutputsDumpDir(requestInputsAndOutputsDumpDir)
181 , m_GpuProfilingEnabled(gpuProfilingEnabled)
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100182 , m_ModelPriority(priority)
Finn Williamsd8fb5402021-05-19 20:52:00 +0100183 , m_AsyncModelExecutionEnabled(asyncModelExecutionEnabled)
Kevin May42477c12020-03-26 13:34:14 +0000184{
185 // Enable profiling if required.
186 m_Runtime->GetProfiler(m_NetworkId)->EnableProfiling(m_GpuProfilingEnabled);
Finn Williamsd8fb5402021-05-19 20:52:00 +0100187
Finn Williamsfdf2eae2021-07-08 13:07:19 +0100188 if (m_AsyncModelExecutionEnabled)
Finn Williamsd8fb5402021-05-19 20:52:00 +0100189 {
Finn Williamsca3a3e02021-06-11 15:04:02 +0100190 std::vector<std::shared_ptr<armnn::IWorkingMemHandle>> memHandles;
Finn Williamsd27c13b2021-06-25 10:06:09 +0100191 for (unsigned int i=0; i < numberOfThreads; ++i)
Finn Williamsca3a3e02021-06-11 15:04:02 +0100192 {
193 memHandles.emplace_back(m_Runtime->CreateWorkingMemHandle(networkId));
194 }
195
Finn Williamsfdf2eae2021-07-08 13:07:19 +0100196 if (!m_Threadpool)
197 {
198 m_Threadpool = std::make_unique<armnn::Threadpool>(numberOfThreads, runtime, memHandles);
199 }
200 else
201 {
202 m_Threadpool->LoadMemHandles(memHandles);
203 }
204
Finn Williamsca3a3e02021-06-11 15:04:02 +0100205 m_WorkingMemHandle = memHandles.back();
Finn Williamsd8fb5402021-05-19 20:52:00 +0100206 }
Kevin May42477c12020-03-26 13:34:14 +0000207}
208
209template<typename HalVersion>
210ArmnnPreparedModel_1_3<HalVersion>::~ArmnnPreparedModel_1_3()
211{
212 // Get a hold of the profiler used by this model.
213 std::shared_ptr<armnn::IProfiler> profiler = m_Runtime->GetProfiler(m_NetworkId);
214
215 // Unload the network associated with this model.
216 m_Runtime->UnloadNetwork(m_NetworkId);
217
Finn Williamsfdf2eae2021-07-08 13:07:19 +0100218 // Unload the network memhandles from the threadpool
219 if (m_AsyncModelExecutionEnabled)
220 {
221 m_Threadpool->UnloadMemHandles(m_NetworkId);
222 }
223
Kevin May42477c12020-03-26 13:34:14 +0000224 // Dump the profiling info to a file if required.
225 DumpJsonProfilingIfRequired(m_GpuProfilingEnabled, m_RequestInputsAndOutputsDumpDir, m_NetworkId, profiler.get());
226}
227
228template<typename HalVersion>
229Return <V1_0::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::execute(const V1_0::Request& request,
230 const ::android::sp<V1_0::IExecutionCallback>& callback)
231{
232 if (callback.get() == nullptr)
233 {
234 ALOGE("ArmnnPreparedModel_1_3::execute invalid callback passed");
235 return V1_0::ErrorStatus::INVALID_ARGUMENT;
236 }
237
238 auto cb = [callback](V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +0000239 std::vector<V1_2::OutputShape> outputShapes,
240 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000241 std::string callingFunction)
242 {
243 NotifyCallbackAndCheck(callback, errorStatus, outputShapes, timing, callingFunction);
244 };
245
246
Sadik Armagan188675f2021-02-12 17:16:42 +0000247 return convertToV1_0(Execute(convertToV1_3(request), V1_2::MeasureTiming::NO, cb));
Kevin May42477c12020-03-26 13:34:14 +0000248}
249
250template<typename HalVersion>
251Return <V1_0::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::execute_1_2(
252 const V1_0::Request& request,
Sadik Armagan188675f2021-02-12 17:16:42 +0000253 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000254 const sp<V1_2::IExecutionCallback>& callback)
255{
256 if (callback.get() == nullptr)
257 {
258 ALOGE("ArmnnPreparedModel_1_3::execute_1_2 invalid callback passed");
259 return V1_0::ErrorStatus::INVALID_ARGUMENT;
260 }
261
262 auto cb = [callback](V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +0000263 std::vector<V1_2::OutputShape> outputShapes,
264 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000265 std::string callingFunction)
266 {
267 NotifyCallbackAndCheck(callback, errorStatus, outputShapes, timing, callingFunction);
268 };
269
270 return convertToV1_0(Execute(convertToV1_3(request), measureTiming, cb));
271}
272
273template<typename HalVersion>
274Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::execute_1_3(
275 const V1_3::Request& request,
Sadik Armagan188675f2021-02-12 17:16:42 +0000276 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000277 const V1_3::OptionalTimePoint&,
Kevin May352d8382020-03-31 15:03:42 +0100278 const V1_3::OptionalTimeoutDuration&,
Kevin May42477c12020-03-26 13:34:14 +0000279 const sp<V1_3::IExecutionCallback>& callback)
280{
281 if (callback.get() == nullptr)
282 {
283 ALOGE("ArmnnPreparedModel_1_3::execute_1_3 invalid callback passed");
284 return V1_3::ErrorStatus::INVALID_ARGUMENT;
285 }
286
287 auto cb = [callback](V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +0000288 std::vector<V1_2::OutputShape> outputShapes,
289 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000290 std::string callingFunction)
291 {
292 NotifyCallbackAndCheck(callback, errorStatus, outputShapes, timing, callingFunction);
293 };
294
295 return Execute(request, measureTiming, cb);
296}
297
Sadik Armagand7be72e2020-04-23 12:56:05 +0100298/// This class is inspired by the sample implementation in Android named SampleFencedExecutionCallback.
299/// The original code is licensed under Apache-2.0 and can be found at the following link:
300/// https://android.googlesource.com/platform/frameworks/ml/+/master/nn/driver/sample/SampleDriver.h
301class ArmnnFencedExecutionCallback : public V1_3::IFencedExecutionCallback
302{
303public:
Sadik Armagan188675f2021-02-12 17:16:42 +0000304 ArmnnFencedExecutionCallback(V1_3::ErrorStatus errorStatus, V1_2::Timing timing, V1_2::Timing fenceTiming)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100305 : m_ErrorStatus(errorStatus), m_Timing(timing), m_FenceTiming(fenceTiming) {}
306 ~ArmnnFencedExecutionCallback() {}
307
308 Return<void> getExecutionInfo(getExecutionInfo_cb callback) override
309 {
310 callback(m_ErrorStatus, m_Timing, m_FenceTiming);
311 return Void();
312 }
313private:
314 V1_3::ErrorStatus m_ErrorStatus;
Sadik Armagan188675f2021-02-12 17:16:42 +0000315 V1_2::Timing m_Timing;
316 V1_2::Timing m_FenceTiming;
Sadik Armagand7be72e2020-04-23 12:56:05 +0100317};
318
Kevin May42477c12020-03-26 13:34:14 +0000319template<typename HalVersion>
Sadik Armagand7be72e2020-04-23 12:56:05 +0100320Return<void> ArmnnPreparedModel_1_3<HalVersion>::executeFenced(const V1_3::Request& request,
321 const hidl_vec<hidl_handle>& fenceWaitFor,
Sadik Armagan188675f2021-02-12 17:16:42 +0000322 V1_2::MeasureTiming measureTiming,
323 const V1_3::OptionalTimePoint& deadline,
324 const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
325 const V1_3::OptionalTimeoutDuration&,
Kevin May42477c12020-03-26 13:34:14 +0000326 executeFenced_cb cb)
327{
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100328 ALOGV("ArmnnPreparedModel_1_3::executeFenced(...)");
329 if (cb == nullptr)
330 {
331 ALOGE("ArmnnPreparedModel_1_3::executeFenced invalid callback passed");
Sadik Armagan188675f2021-02-12 17:16:42 +0000332 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100333 return Void();
334 }
335
Sadik Armagan188675f2021-02-12 17:16:42 +0000336 if (deadline.getDiscriminator() != V1_3::OptionalTimePoint::hidl_discriminator::none)
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100337 {
338 ALOGW("ArmnnPreparedModel_1_3::executeFenced parameter deadline is set but not supported.");
339 }
340
Sadik Armagan188675f2021-02-12 17:16:42 +0000341 if (loopTimeoutDuration.getDiscriminator() != V1_3::OptionalTimeoutDuration::hidl_discriminator::none)
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100342 {
343 ALOGW("ArmnnPreparedModel_1_3::executeFenced parameter loopTimeoutDuration is set but not supported.");
344 }
345
Finn Williamsa4983ce2020-07-23 12:55:12 +0100346 if (!android::nn::validateRequest(request, m_Model, /*allowUnspecifiedOutput=*/false))
347 {
348 ALOGV("ArmnnPreparedModel_1_3::executeFenced outputs must be specified for fenced execution ");
Sadik Armagan188675f2021-02-12 17:16:42 +0000349 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Finn Williamsa4983ce2020-07-23 12:55:12 +0100350 return Void();
351 }
352
Sadik Armagand7be72e2020-04-23 12:56:05 +0100353 ExecutionContext_1_3 ctx;
Sadik Armagan188675f2021-02-12 17:16:42 +0000354 if (measureTiming == V1_2::MeasureTiming::YES)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100355 {
356 ctx.measureTimings = measureTiming;
357 ctx.driverStart = Now();
358 }
359
360 ALOGV("ArmnnPreparedModel_1_3::executeFenced(): %s", GetModelSummary(m_Model).c_str());
361 m_RequestCount++;
362
Sadik Armagand7be72e2020-04-23 12:56:05 +0100363 if (!m_RequestInputsAndOutputsDumpDir.empty())
364 {
365 ALOGD("Dumping inputs and outputs for request %" PRIuPTR, reinterpret_cast<std::uintptr_t>(&cb));
366 }
367
368 // This code snippet is inspired by the sample implementation in Android named SampleDriver::executeFenced()
369 // function. The original code is licensed under Apache-2.0 and can be found at the following link:
370 // https://android.googlesource.com/platform/frameworks/ml/+/master/nn/driver/sample/SampleDriver.cpp
371 const auto fenceSize = fenceWaitFor.size();
372 for (unsigned int index = 0; index < fenceSize; ++index)
373 {
374 auto fenceNativeHandle = fenceWaitFor[index].getNativeHandle();
375 if (!fenceNativeHandle)
376 {
Sadik Armagan188675f2021-02-12 17:16:42 +0000377 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Sadik Armagand7be72e2020-04-23 12:56:05 +0100378 return Void();
379 }
380
381 if (sync_wait(fenceNativeHandle->data[0], -1) < 0)
382 {
383 ALOGE("ArmnnPreparedModel_1_3::executeFenced sync fence failed.");
Sadik Armagan188675f2021-02-12 17:16:42 +0000384 cb(V1_3::ErrorStatus::GENERAL_FAILURE, hidl_handle(nullptr), nullptr);
Sadik Armagand7be72e2020-04-23 12:56:05 +0100385 return Void();
386 }
387 }
388
389 TimePoint fenceExecutionStart;
Sadik Armagan188675f2021-02-12 17:16:42 +0000390 if (measureTiming == V1_2::MeasureTiming::YES)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100391 {
392 fenceExecutionStart = Now();
393 }
394
395 // map the memory pool into shared pointers
396 // use a shared memory pools vector on the heap, as it is passed to the request thread
397 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
398
399 // allocate the tensors on the heap, as they are passed to the request thread
400 auto inputs = std::make_shared<armnn::InputTensors>();
401 auto outputs = std::make_shared<armnn::OutputTensors>();
402
403 auto [status, outShapes, timings, message] = PrepareMemoryForIO(*inputs, *outputs, *memPools, request);
404 if (status != V1_3::ErrorStatus::NONE)
405 {
Sadik Armagan188675f2021-02-12 17:16:42 +0000406 cb(V1_3::ErrorStatus::INVALID_ARGUMENT, hidl_handle(nullptr), nullptr);
Sadik Armagand7be72e2020-04-23 12:56:05 +0100407 return Void();
408 }
409
410 ALOGV("ArmnnPreparedModel_1_3::executeFenced(...) before ExecuteGraph");
411
412 // call it with nullCallback for now as we will report the error status from here..
Sadik Armagan188675f2021-02-12 17:16:42 +0000413 auto nullCallback = [](V1_3::ErrorStatus, std::vector<V1_2::OutputShape>, const V1_2::Timing&, std::string) {};
Sadik Armagand7be72e2020-04-23 12:56:05 +0100414 CallbackContext_1_3 cbCtx;
415 cbCtx.callback = nullCallback;
416 cbCtx.ctx = ctx;
417
418 auto errorStatus = ExecuteGraph(memPools, *inputs, *outputs, cbCtx);
419 if (errorStatus != V1_3::ErrorStatus::NONE)
420 {
421 cb(errorStatus, hidl_handle(nullptr), nullptr);
422 return Void();
423 }
424 ALOGV("ArmnnPreparedModel_1_3::executeFenced(...) after ExecuteGraph");
425
Sadik Armagan188675f2021-02-12 17:16:42 +0000426 V1_2::Timing timing = g_NoTiming;
427 V1_2::Timing fenceTiming = g_NoTiming;
428 if (measureTiming == V1_2::MeasureTiming::YES)
Sadik Armagand7be72e2020-04-23 12:56:05 +0100429 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100430 fenceTiming.timeOnDevice = MicrosecondsDuration(ctx.deviceEnd, ctx.deviceStart);
Kevin May949a69e2020-04-24 10:21:40 +0100431 fenceTiming.timeInDriver = MicrosecondsDuration(ctx.driverEnd, fenceExecutionStart);
432 ALOGV("ArmnnPreparedModel_1_3::fenceFinishExecutionTiming - Device = %lu Driver = %lu",
Sadik Armagand7be72e2020-04-23 12:56:05 +0100433 fenceTiming.timeOnDevice, fenceTiming.timeInDriver);
434 }
435
436 sp<ArmnnFencedExecutionCallback> armnnFencedExecutionCallback =
Sadik Armagan188675f2021-02-12 17:16:42 +0000437 new ArmnnFencedExecutionCallback(V1_3::ErrorStatus::NONE, timing, fenceTiming);
438 cb(V1_3::ErrorStatus::NONE, hidl_handle(nullptr), armnnFencedExecutionCallback);
Kevin May42477c12020-03-26 13:34:14 +0000439 return Void();
440}
441
442template<typename HalVersion>
443Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForInputs(
444 armnn::InputTensors& inputs,
445 const V1_3::Request& request,
446 const std::vector<android::nn::RunTimePoolInfo>& memPools)
447{
448 inputs.reserve(request.inputs.size());
449 for (unsigned int i = 0; i < request.inputs.size(); i++)
450 {
451 const auto& inputArg = request.inputs[i];
452
453 const armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
454 const armnn::Tensor inputTensor = GetTensorForRequestArgument(inputArg, inputTensorInfo, memPools);
455
456 if (inputTensor.GetMemoryArea() == nullptr)
457 {
458 ALOGE("Cannot execute request. Error converting request input %u to tensor", i);
459 return V1_3::ErrorStatus::GENERAL_FAILURE;
460 }
461
462 inputs.emplace_back(i, inputTensor);
463 }
464
465 return V1_3::ErrorStatus::NONE;
466}
467
468template<typename HalVersion>
469Return<V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForOutputs(
470 armnn::OutputTensors& outputs,
Sadik Armagan188675f2021-02-12 17:16:42 +0000471 std::vector<V1_2::OutputShape> &outputShapes,
Kevin May42477c12020-03-26 13:34:14 +0000472 const V1_3::Request& request,
473 const std::vector<android::nn::RunTimePoolInfo>& memPools)
474{
475 outputs.reserve(request.outputs.size());
476 for (unsigned int i = 0; i < request.outputs.size(); i++)
477 {
478 const auto& outputArg = request.outputs[i];
479
Finn Williamsa4983ce2020-07-23 12:55:12 +0100480 armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
Kevin May42477c12020-03-26 13:34:14 +0000481 const armnn::Tensor outputTensor = GetTensorForRequestArgument(outputArg, outputTensorInfo, memPools);
482 if (outputTensor.GetMemoryArea() == nullptr)
483 {
484 ALOGE("Cannot execute request. Error converting request output %u to tensor", i);
485 return V1_3::ErrorStatus::GENERAL_FAILURE;
486 }
487
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100488 const size_t outputSize = outputTensorInfo.GetNumBytes();
489
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
Sadik Armagan188675f2021-02-12 17:16:42 +0000516 size_t bufferSize = 0;
517#if !defined(ARMNN_ANDROID_S)
518 bufferSize = memPools.at(outputArg.location.poolIndex).getHidlMemory().size();
Sadik Armagan188675f2021-02-12 17:16:42 +0000519#else
Kevin Maydc873f62021-06-14 11:21:11 +0100520 bufferSize = memPools.at(outputArg.location.poolIndex).getSize();
Sadik Armagan188675f2021-02-12 17:16:42 +0000521#endif
Kevin May42477c12020-03-26 13:34:14 +0000522 if (bufferSize < outputSize)
523 {
Teresa Charlin4bd9a742020-08-12 12:58:50 +0100524 ALOGW("ArmnnPreparedModel_1_3::Execute failed bufferSize (%s) < outputSize (%s)",
525 std::to_string(bufferSize).c_str(), std::to_string(outputSize).c_str());
Finn Williamsa4983ce2020-07-23 12:55:12 +0100526 outputShapes[i].isSufficient = false;
Kevin May42477c12020-03-26 13:34:14 +0000527 return V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
528 }
Kevin May42477c12020-03-26 13:34:14 +0000529 }
530
531 return V1_3::ErrorStatus::NONE;
532}
533
534template<typename HalVersion>
Sadik Armagan188675f2021-02-12 17:16:42 +0000535std::tuple<V1_3::ErrorStatus, hidl_vec<V1_2::OutputShape>, V1_2::Timing, std::string>
Kevin May42477c12020-03-26 13:34:14 +0000536 ArmnnPreparedModel_1_3<HalVersion>::PrepareMemoryForIO(armnn::InputTensors& inputs,
537 armnn::OutputTensors& outputs,
538 std::vector<android::nn::RunTimePoolInfo>& memPools,
539 const V1_3::Request& request)
540{
Sadik Armagan188675f2021-02-12 17:16:42 +0000541#if !defined(ARMNN_ANDROID_S)
Kevin May42477c12020-03-26 13:34:14 +0000542 if (!setRunTimePoolInfosFromMemoryPools(&memPools, request.pools))
Sadik Armagan188675f2021-02-12 17:16:42 +0000543#else
544 if (!setRunTimePoolInfosFromMemoryPools(&memPools, uncheckedConvert(request.pools)))
545#endif
Kevin May42477c12020-03-26 13:34:14 +0000546 {
Sadik Armagan188675f2021-02-12 17:16:42 +0000547 return {V1_3::ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000548 }
549
550 // add the inputs and outputs with their data
551 try
552 {
553 if (PrepareMemoryForInputs(inputs, request, memPools) != V1_3::ErrorStatus::NONE)
554 {
Sadik Armagan188675f2021-02-12 17:16:42 +0000555 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000556 }
557
Sadik Armagan188675f2021-02-12 17:16:42 +0000558 std::vector<V1_2::OutputShape> outputShapes(request.outputs.size());
Kevin May42477c12020-03-26 13:34:14 +0000559
560 auto errorStatus = PrepareMemoryForOutputs(outputs, outputShapes, request, memPools);
561 if (errorStatus != V1_3::ErrorStatus::NONE)
562 {
563 return {errorStatus, outputShapes, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
564 }
565 }
566 catch (armnn::Exception& e)
567 {
568 ALOGW("armnn::Exception caught while preparing for EnqueueWorkload: %s", e.what());
Sadik Armagan188675f2021-02-12 17:16:42 +0000569 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000570 }
571 catch (std::exception& e)
572 {
573 ALOGE("std::exception caught while preparing for EnqueueWorkload: %s", e.what());
Sadik Armagan188675f2021-02-12 17:16:42 +0000574 return {V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
Kevin May42477c12020-03-26 13:34:14 +0000575 }
576
577 return {V1_3::ErrorStatus::NONE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute"};
578}
579
580template<typename HalVersion>
581template<typename CallbackContext>
582Return<void> ArmnnPreparedModel_1_3<HalVersion>::ExecuteSynchronously(const V1_3::Request& request,
583 CallbackContext cbCtx)
584{
Sadik Armagan188675f2021-02-12 17:16:42 +0000585 if (cbCtx.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000586 {
587 cbCtx.ctx.driverStart = Now();
588 }
589
590 if (!android::nn::validateRequest(convertToV1_3(request), m_Model))
591 {
592 ALOGE("ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
593 cbCtx.callback(V1_3::ErrorStatus::INVALID_ARGUMENT,
594 {},
595 g_NoTiming,
596 "ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
597 return Void();
598 }
599
600 if (!android::nn::validateRequest(request, m_Model))
601 {
602 ALOGE("ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
603 cbCtx.callback(V1_3::ErrorStatus::INVALID_ARGUMENT,
604 {},
605 g_NoTiming,
606 "ArmnnPreparedModel_1_3::ExecuteSynchronously invalid request model");
Sadik Armaganef8a3932020-04-09 17:21:50 +0100607 return Void();
Kevin May42477c12020-03-26 13:34:14 +0000608 }
609
610
611 // map the memory pool into shared pointers
612 // use a shared memory pools vector on the heap, as it is passed to the request thread
613 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
614
615 // allocate the tensors on the heap, as they are passed to the request thread
616 auto inputs = std::make_shared<armnn::InputTensors>();
617 auto outputs = std::make_shared<armnn::OutputTensors>();
618
619 auto [status, outputShapes, timing, message] = PrepareMemoryForIO(*inputs, *outputs, *memPools, request);
620 if (status != V1_3::ErrorStatus::NONE)
621 {
622 cbCtx.callback(status, outputShapes, timing, message);
Sadik Armaganef8a3932020-04-09 17:21:50 +0100623 return Void();
Kevin May42477c12020-03-26 13:34:14 +0000624 }
625
626 ALOGV("ArmnnPreparedModel_1_3::ExecuteSynchronously() before Execution");
627
628 ExecuteGraph(memPools, *inputs, *outputs, cbCtx);
629 return Void();
630}
631
632template<typename HalVersion>
633Return<void> ArmnnPreparedModel_1_3<HalVersion>::executeSynchronously(const V1_0::Request& request,
Sadik Armagan188675f2021-02-12 17:16:42 +0000634 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000635 executeSynchronously_cb cb)
636{
637 ALOGV("ArmnnPreparedModel_1_3::executeSynchronously(): %s", GetModelSummary(m_Model).c_str());
638 m_RequestCount++;
639
640 if (cb == nullptr)
641 {
642 ALOGE("ArmnnPreparedModel_1_3::executeSynchronously invalid callback passed");
643 return Void();
644 }
645
646 auto cbWrapper = [cb](V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +0000647 std::vector<V1_2::OutputShape> outputShapes,
648 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000649 std::string)
650 {
651 cb(convertToV1_0(errorStatus), outputShapes, timing);
652 };
653
654 CallbackContext_1_3 cbCtx;
655 cbCtx.callback = cbWrapper;
656 cbCtx.ctx.measureTimings = measureTiming;
657
658 ExecuteSynchronously(convertToV1_3(request), cbCtx);
659 return Void();
660}
661
662template<typename HalVersion>
Kevin May352d8382020-03-31 15:03:42 +0100663Return<void> ArmnnPreparedModel_1_3<HalVersion>::executeSynchronously_1_3(
664 const V1_3::Request& request,
Sadik Armagan188675f2021-02-12 17:16:42 +0000665 V1_2::MeasureTiming measureTiming,
Kevin May352d8382020-03-31 15:03:42 +0100666 const V1_3::OptionalTimePoint& deadline,
667 const V1_3::OptionalTimeoutDuration& loopTimeoutDuration,
668 executeSynchronously_1_3_cb cb)
Kevin May42477c12020-03-26 13:34:14 +0000669{
670 ALOGV("ArmnnPreparedModel_1_3::executeSynchronously_1_3(): %s", GetModelSummary(m_Model).c_str());
671 m_RequestCount++;
672
673 if (cb == nullptr)
674 {
675 ALOGE("ArmnnPreparedModel_1_3::executeSynchronously_1_3 invalid callback passed");
676 return Void();
677 }
678
Sadik Armagan188675f2021-02-12 17:16:42 +0000679 if (deadline.getDiscriminator() != V1_3::OptionalTimePoint::hidl_discriminator::none)
Kevin May42477c12020-03-26 13:34:14 +0000680 {
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100681 ALOGW("ArmnnPreparedModel_1_3::executeSynchronously_1_3 parameter deadline is set but not supported.");
Kevin May42477c12020-03-26 13:34:14 +0000682 }
683
Sadik Armagan188675f2021-02-12 17:16:42 +0000684 if (loopTimeoutDuration.getDiscriminator() != V1_3::OptionalTimeoutDuration::hidl_discriminator::none)
Sadik Armagan7b9ce8d2020-04-21 10:39:28 +0100685 {
686 ALOGW(
687 "ArmnnPreparedModel_1_3::executeSynchronously_1_3 parameter loopTimeoutDuration is set but not supported.");
Kevin May352d8382020-03-31 15:03:42 +0100688 }
689
Kevin May42477c12020-03-26 13:34:14 +0000690 auto cbWrapper = [cb](V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +0000691 std::vector<V1_2::OutputShape> outputShapes,
692 const V1_2::Timing& timing,
Kevin May42477c12020-03-26 13:34:14 +0000693 std::string)
694 {
695 cb(errorStatus, outputShapes, timing);
696 };
697
698 CallbackContext_1_3 cbCtx;
699 cbCtx.callback = cbWrapper;
700 cbCtx.ctx.measureTimings = measureTiming;
701
702 ExecuteSynchronously(request, cbCtx);
703 return Void();
704}
705
706template<typename HalVersion>
707Return<void> ArmnnPreparedModel_1_3<HalVersion>::configureExecutionBurst(
708 const sp<V1_2::IBurstCallback>& callback,
709 const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
710 const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
711 V1_3::IPreparedModel::configureExecutionBurst_cb cb)
712{
713 ALOGV("ArmnnPreparedModel_1_3::configureExecutionBurst");
714 const sp<V1_2::IBurstContext> burst = ExecutionBurstServer::create(callback,
715 requestChannel,
716 resultChannel,
717 this);
718
719 if (burst == nullptr)
720 {
721 cb(V1_0::ErrorStatus::GENERAL_FAILURE, {});
722 }
723 else
724 {
725 cb(V1_0::ErrorStatus::NONE, burst);
726 }
727 return Void();
728}
729
730template<typename HalVersion>
731template<typename CallbackContext>
Sadik Armagand7be72e2020-04-23 12:56:05 +0100732Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::ExecuteGraph(
Kevin May42477c12020-03-26 13:34:14 +0000733 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
734 armnn::InputTensors& inputTensors,
735 armnn::OutputTensors& outputTensors,
736 CallbackContext cb)
737{
738 ALOGV("ArmnnPreparedModel_1_3::ExecuteGraph(...)");
739
Kevin May42477c12020-03-26 13:34:14 +0000740 DumpTensorsIfRequired("Input", inputTensors);
741
Sadik Armagan188675f2021-02-12 17:16:42 +0000742 std::vector<V1_2::OutputShape> outputShapes(outputTensors.size());
Kevin May42477c12020-03-26 13:34:14 +0000743 for (unsigned int i = 0; i < outputTensors.size(); i++)
744 {
745 std::pair<int, armnn::Tensor> outputTensorPair = outputTensors[i];
746 const armnn::Tensor outputTensor = outputTensorPair.second;
747 const armnn::TensorInfo outputTensorInfo = outputTensor.GetInfo();
748
749 outputShapes[i] = ComputeShape(outputTensorInfo);
750 }
751
752 // run it
753 try
754 {
Sadik Armagan188675f2021-02-12 17:16:42 +0000755 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000756 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100757 cb.ctx.deviceStart = Now();
Kevin May42477c12020-03-26 13:34:14 +0000758 }
Finn Williamsd8fb5402021-05-19 20:52:00 +0100759 armnn::Status status;
760 if (m_AsyncModelExecutionEnabled)
761 {
762 ALOGW("ArmnnPreparedModel_1_3::ExecuteGraph m_AsyncModelExecutionEnabled true");
763 status = m_Runtime->Execute(*m_WorkingMemHandle, inputTensors, outputTensors);
764 }
765 else
766 {
767 ALOGW("ArmnnPreparedModel_1_3::ExecuteGraph m_AsyncModelExecutionEnabled false");
768 status = m_Runtime->EnqueueWorkload(m_NetworkId, inputTensors, outputTensors);
769 }
Kevin May42477c12020-03-26 13:34:14 +0000770
Sadik Armagan188675f2021-02-12 17:16:42 +0000771 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000772 {
Sadik Armagand7be72e2020-04-23 12:56:05 +0100773 cb.ctx.deviceEnd = Now();
Kevin May42477c12020-03-26 13:34:14 +0000774 }
775 if (status != armnn::Status::Success)
776 {
Finn Williamsd8fb5402021-05-19 20:52:00 +0100777 ALOGW("ArmnnPreparedModel_1_3::ExecuteGraph EnqueueWorkload failed");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100778 cb.callback(V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
779 return V1_3::ErrorStatus::GENERAL_FAILURE;
Kevin May42477c12020-03-26 13:34:14 +0000780 }
781 }
782 catch (armnn::Exception& e)
783 {
784 ALOGW("armnn:Exception caught from EnqueueWorkload: %s", e.what());
785 cb.callback(V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100786 return V1_3::ErrorStatus::GENERAL_FAILURE;
Kevin May42477c12020-03-26 13:34:14 +0000787 }
788 catch (std::exception& e)
789 {
790 ALOGE("std::exception caught from EnqueueWorkload: %s", e.what());
791 cb.callback(V1_3::ErrorStatus::GENERAL_FAILURE, {}, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100792 return V1_3::ErrorStatus::GENERAL_FAILURE;
Kevin May42477c12020-03-26 13:34:14 +0000793 }
794
795 CommitPools(*pMemPools);
796
797 DumpTensorsIfRequired("Output", outputTensors);
798
Sadik Armagan188675f2021-02-12 17:16:42 +0000799 if (cb.ctx.measureTimings == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000800 {
Kevin May949a69e2020-04-24 10:21:40 +0100801 cb.ctx.driverEnd = Now();
Sadik Armagan188675f2021-02-12 17:16:42 +0000802 V1_2::Timing timing;
Sadik Armagand7be72e2020-04-23 12:56:05 +0100803 timing.timeOnDevice = MicrosecondsDuration(cb.ctx.deviceEnd, cb.ctx.deviceStart);
Kevin May949a69e2020-04-24 10:21:40 +0100804 timing.timeInDriver = MicrosecondsDuration(cb.ctx.driverEnd, cb.ctx.driverStart);
805 ALOGV("ArmnnPreparedModel_1_3::execute timing - Device = %lu Driver = %lu", timing.timeOnDevice,
Kevin May42477c12020-03-26 13:34:14 +0000806 timing.timeInDriver);
807 cb.callback(V1_3::ErrorStatus::NONE, outputShapes, timing, "ArmnnPreparedModel_1_3::ExecuteGraph");
Sadik Armagand7be72e2020-04-23 12:56:05 +0100808 } else
809 {
Kevin May42477c12020-03-26 13:34:14 +0000810 cb.callback(V1_3::ErrorStatus::NONE, outputShapes, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
811 }
Sadik Armagand7be72e2020-04-23 12:56:05 +0100812 return V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000813}
814
Finn Williamsd8fb5402021-05-19 20:52:00 +0100815/// Schedule the graph prepared from the request for execution
816template<typename HalVersion>
817template<typename CallbackContext>
818void ArmnnPreparedModel_1_3<HalVersion>::ScheduleGraphForExecution(
819 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
820 std::shared_ptr<armnn::InputTensors>& inputTensors,
821 std::shared_ptr<armnn::OutputTensors>& outputTensors,
822 CallbackContext callbackContext,
823 armnn::QosExecPriority priority)
824{
825 ALOGV("ArmnnPreparedModel_1_3::ScheduleGraphForExecution(...)");
826
827 DumpTensorsIfRequired("Input", *inputTensors);
828
829 unsigned int outputTensorSize = outputTensors.get()->size();
830 std::vector<V1_2::OutputShape> outputShapes(outputTensorSize);
831 for (unsigned int i = 0; i < outputTensorSize; i++)
832 {
833 std::pair<int, armnn::Tensor> outputTensorPair = outputTensors.get()->at(i);
834 const armnn::Tensor outputTensor = outputTensorPair.second;
835 const armnn::TensorInfo outputTensorInfo = outputTensor.GetInfo();
836
837 outputShapes[i] = ComputeShape(outputTensorInfo);
838 }
839
840 auto tpCb = std::make_shared<
841 ArmnnThreadPoolCallback_1_3<CallbackContext_1_3>>(this,
842 pMemPools,
843 outputShapes,
844 inputTensors,
845 outputTensors,
846 callbackContext);
847
Finn Williamsca3a3e02021-06-11 15:04:02 +0100848 m_Threadpool->Schedule(m_NetworkId,
849 *tpCb->m_InputTensors,
850 *tpCb->m_OutputTensors,
851 priority,
852 tpCb);
Finn Williamsd8fb5402021-05-19 20:52:00 +0100853 ALOGV("ArmnnPreparedModel_1_3::ScheduleGraphForExecution end");
854}
855
Kevin May42477c12020-03-26 13:34:14 +0000856template<typename HalVersion>
857bool ArmnnPreparedModel_1_3<HalVersion>::ExecuteWithDummyInputs()
858{
859 std::vector<std::vector<char>> storage;
860 armnn::InputTensors inputTensors;
861 for (unsigned int i = 0; i < getMainModel(m_Model).inputIndexes.size(); i++)
862 {
863 const armnn::TensorInfo inputTensorInfo = m_Runtime->GetInputTensorInfo(m_NetworkId, i);
864 storage.emplace_back(inputTensorInfo.GetNumBytes());
865 const armnn::ConstTensor inputTensor(inputTensorInfo, storage.back().data());
866
867 inputTensors.emplace_back(i, inputTensor);
868 }
869
870 armnn::OutputTensors outputTensors;
871 for (unsigned int i = 0; i < getMainModel(m_Model).outputIndexes.size(); i++)
872 {
873 const armnn::TensorInfo outputTensorInfo = m_Runtime->GetOutputTensorInfo(m_NetworkId, i);
874 storage.emplace_back(outputTensorInfo.GetNumBytes());
875 const armnn::Tensor outputTensor(outputTensorInfo, storage.back().data());
876
877 outputTensors.emplace_back(i, outputTensor);
878 }
879
Sadik Armagan188675f2021-02-12 17:16:42 +0000880 auto nullCallback = [](V1_3::ErrorStatus, std::vector<V1_2::OutputShape>, const V1_2::Timing&, std::string) {};
Kevin May42477c12020-03-26 13:34:14 +0000881 CallbackContext_1_3 callbackContext;
882 callbackContext.callback = nullCallback;
Sadik Armagan188675f2021-02-12 17:16:42 +0000883 callbackContext.ctx.measureTimings = V1_2::MeasureTiming::NO;
Kevin May42477c12020-03-26 13:34:14 +0000884 auto memPools = std::make_shared<std::vector<::android::nn::RunTimePoolInfo>>();
Sadik Armagand7be72e2020-04-23 12:56:05 +0100885
886 auto errorStatus = ExecuteGraph(memPools,
887 inputTensors,
888 outputTensors,
889 callbackContext);
890 return errorStatus == V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000891}
892
893template<typename HalVersion>
894Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<HalVersion>::Execute(const V1_3::Request& request,
Sadik Armagan188675f2021-02-12 17:16:42 +0000895 V1_2::MeasureTiming measureTiming,
Kevin May42477c12020-03-26 13:34:14 +0000896 CallbackAsync_1_3 callback)
897{
898 ExecutionContext_1_3 ctx;
Sadik Armagan188675f2021-02-12 17:16:42 +0000899 if (measureTiming == V1_2::MeasureTiming::YES)
Kevin May42477c12020-03-26 13:34:14 +0000900 {
901 ctx.measureTimings = measureTiming;
902 ctx.driverStart = Now();
903 }
904
905 ALOGV("ArmnnPreparedModel_1_3::execute(): %s", GetModelSummary(m_Model).c_str());
906 m_RequestCount++;
907
908 if (!android::nn::validateRequest(request, m_Model))
909 {
910 callback(V1_3::ErrorStatus::INVALID_ARGUMENT, {}, g_NoTiming, "ArmnnPreparedModel_1_3::execute");
911 return V1_3::ErrorStatus::INVALID_ARGUMENT;
912 }
913
914 if (!m_RequestInputsAndOutputsDumpDir.empty())
915 {
916 ALOGD("Dumping inputs and outputs for request %" PRIuPTR, reinterpret_cast<std::uintptr_t>(&callback));
917 }
918
919 // map the memory pool into shared pointers
920 // use a shared memory pools vector on the heap, as it is passed to the request thread
921 auto memPools = std::make_shared<std::vector<android::nn::RunTimePoolInfo>>();
922
923 // allocate the tensors on the heap, as they are passed to the request thread
924 auto inputTensors = std::make_shared<armnn::InputTensors>();
925 auto outputTensors = std::make_shared<armnn::OutputTensors>();
926
927 auto [status, outShapes, timing, message] = PrepareMemoryForIO(*inputTensors, *outputTensors,
928 *memPools, request);
929 if (status != V1_3::ErrorStatus::NONE)
930 {
931 callback(status, outShapes, timing, message);
932 }
933
934 switch(status)
935 {
936 case V1_3::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE:
937 return V1_3::ErrorStatus::NONE;
938 case V1_3::ErrorStatus::GENERAL_FAILURE:
939 return V1_3::ErrorStatus::GENERAL_FAILURE;
Sadik Armagana07d2752021-05-12 20:33:58 +0100940 case V1_3::ErrorStatus::INVALID_ARGUMENT:
941 return V1_3::ErrorStatus::INVALID_ARGUMENT;
Kevin May42477c12020-03-26 13:34:14 +0000942 default:
943 {}
944 }
Kevin May42477c12020-03-26 13:34:14 +0000945 CallbackContext_1_3 cb;
946 cb.callback = callback;
947 cb.ctx = ctx;
Finn Williamsd8fb5402021-05-19 20:52:00 +0100948
949
950 enum class QosExecPriority
951 {
952 Low = 0,
953 Medium = 1,
954 High = 2
955 };
956
957
958 if (m_AsyncModelExecutionEnabled)
959 {
960 armnn::QosExecPriority priority;
961
962 switch (GetModelPriority()) {
963 case V1_3::Priority::LOW:
964 priority = armnn::QosExecPriority::Low;
965 break;
966 case V1_3::Priority::MEDIUM:
967 priority = armnn::QosExecPriority::Medium;
968 break;
969 case V1_3::Priority::HIGH:
970 priority = armnn::QosExecPriority::High;
971 break;
972 default:
973 priority = armnn::QosExecPriority::Medium;
974
975 }
976
977 ALOGV("ArmnnPreparedModel_1_3::execute(...) before ScheduleGraphForExecution");
978 ScheduleGraphForExecution(memPools, inputTensors, outputTensors, cb, priority);
979 ALOGV("ArmnnPreparedModel_1_3::execute(...) after ScheduleGraphForExecution");
980 return V1_3::ErrorStatus::NONE;
981 }
982
983 ALOGV("ArmnnPreparedModel_1_3::execute(...) before PostMsg");
984 // post the request for asynchronous execution
Kevin May42477c12020-03-26 13:34:14 +0000985 m_RequestThread.PostMsg(this, memPools, inputTensors, outputTensors, cb);
986 ALOGV("ArmnnPreparedModel_1_3::execute(...) after PostMsg");
987 return V1_3::ErrorStatus::NONE;
988}
989
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100990template<typename HalVersion>
991V1_3::Priority ArmnnPreparedModel_1_3<HalVersion>::GetModelPriority()
992{
993 return m_ModelPriority;
994}
995
Finn Williamsd8fb5402021-05-19 20:52:00 +0100996template<typename HalVersion>
997template <typename CallbackContext>
998void ArmnnPreparedModel_1_3<HalVersion>::ArmnnThreadPoolCallback_1_3<CallbackContext>::Notify(
999 armnn::Status status, armnn::InferenceTimingPair timeTaken)
1000{
1001 ALOGV("ArmnnPreparedModel_1_3::ArmnnThreadPoolCallback_1_3<CallbackContext>::Notify");
1002 CommitPools(*m_MemPools);
1003
1004 m_Model->DumpTensorsIfRequired("Output", *m_OutputTensors);
1005
1006 if (status != armnn::Status::Success)
1007 {
1008 ALOGW("ArmnnThreadPoolCallback_1_3::Notify EnqueueWorkload failed");
1009 m_CallbackContext.callback(V1_3::ErrorStatus::GENERAL_FAILURE,
1010 {},
1011 g_NoTiming,
1012 "ArmnnPreparedModel_1_3::ArmnnThreadPoolCallback_1_3");
1013 return;
1014 }
1015
1016 if (m_CallbackContext.ctx.measureTimings == V1_2::MeasureTiming::YES)
1017 {
1018 m_CallbackContext.ctx.deviceStart = timeTaken.first;
1019 m_CallbackContext.ctx.deviceEnd = timeTaken.second;
1020 m_CallbackContext.ctx.driverEnd = std::chrono::steady_clock::now();
1021 V1_2::Timing timing;
1022 timing.timeOnDevice = MicrosecondsDuration(m_CallbackContext.ctx.deviceEnd, m_CallbackContext.ctx.deviceStart);
1023 timing.timeInDriver = MicrosecondsDuration(m_CallbackContext.ctx.driverEnd, m_CallbackContext.ctx.driverStart);
1024 ALOGV("ArmnnPreparedModel_1_3::execute timing - Device = %lu Driver = %lu", timing.timeOnDevice,
1025 timing.timeInDriver);
1026 m_CallbackContext.callback(
1027 V1_3::ErrorStatus::NONE, m_OutputShapes, timing, "ArmnnPreparedModel_1_3::ExecuteGraph");
1028 } else
1029 {
1030 m_CallbackContext.callback(
1031 V1_3::ErrorStatus::NONE, m_OutputShapes, g_NoTiming, "ArmnnPreparedModel_1_3::ExecuteGraph");
1032 }
1033 return;
1034}
1035
Kevin May42477c12020-03-26 13:34:14 +00001036#ifdef ARMNN_ANDROID_NN_V1_3
1037template class ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>;
Sadik Armagand7be72e2020-04-23 12:56:05 +01001038template Return <V1_3::ErrorStatus> ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>::ExecuteGraph<CallbackContext_1_3>(
Kevin May42477c12020-03-26 13:34:14 +00001039 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
1040 armnn::InputTensors& pInputTensors,
1041 armnn::OutputTensors& pOutputTensors,
1042 CallbackContext_1_3 cb);
Finn Williamsd8fb5402021-05-19 20:52:00 +01001043
1044template void ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>::ScheduleGraphForExecution<CallbackContext_1_3>(
1045 std::shared_ptr<std::vector<::android::nn::RunTimePoolInfo>>& pMemPools,
1046 std::shared_ptr<armnn::InputTensors>& inputTensors,
1047 std::shared_ptr<armnn::OutputTensors>& outputTensors,
1048 CallbackContext_1_3 callbackContext,
1049 armnn::QosExecPriority priority);
Kevin May42477c12020-03-26 13:34:14 +00001050#endif
1051
1052} // namespace armnn_driver