blob: e04cf5ddaf0bee0d3904841db3ee7f76bcda1561 [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
Jim Flynn6398a982020-05-27 17:05:21 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5#include "Runtime.hpp"
6
David Beck056be3c2018-10-22 13:16:00 +01007#include <armnn/Version.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +00008#include <armnn/BackendRegistry.hpp>
Jim Flynnf7713212020-07-14 09:50:59 +01009#include <LabelsAndEventClasses.hpp>
Matthew Benthamf48afc62020-01-15 17:55:08 +000010#include <armnn/Logging.hpp>
alered01a7227ac2020-05-07 14:58:29 +010011#include <armnn/utility/Timer.hpp>
Matteo Martincighe54aa062019-08-05 14:12:11 +010012
Matteo Martincighe5b8eb92019-11-28 15:45:42 +000013#include <armnn/backends/IBackendContext.hpp>
Matteo Martincighe54aa062019-08-05 14:12:11 +010014#include <backendsCommon/DynamicBackendUtils.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010015#include <armnn/utility/PolymorphicDowncast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000016
surmeh013537c2c2018-05-18 16:31:43 +010017#include <iostream>
18
Colm Donelan1aff3932020-02-05 17:48:59 +000019#include <backends/BackendProfiling.hpp>
telsoa014fcda012018-03-09 14:13:49 +000020
21using namespace armnn;
22using namespace std;
23
24namespace armnn
25{
Kevin Mayd92a6e42021-02-04 10:27:41 +000026IRuntime::IRuntime() : pRuntimeImpl( new RuntimeImpl(armnn::IRuntime::CreationOptions())) {}
27
28IRuntime::IRuntime(const IRuntime::CreationOptions& options) : pRuntimeImpl(new RuntimeImpl(options)) {}
29
30IRuntime::~IRuntime() = default;
telsoa014fcda012018-03-09 14:13:49 +000031
32IRuntime* IRuntime::CreateRaw(const CreationOptions& options)
33{
Kevin Mayd92a6e42021-02-04 10:27:41 +000034 return new IRuntime(options);
telsoa014fcda012018-03-09 14:13:49 +000035}
36
37IRuntimePtr IRuntime::Create(const CreationOptions& options)
38{
39 return IRuntimePtr(CreateRaw(options), &IRuntime::Destroy);
40}
41
42void IRuntime::Destroy(IRuntime* runtime)
43{
Kevin Mayd92a6e42021-02-04 10:27:41 +000044 delete runtime;
telsoa014fcda012018-03-09 14:13:49 +000045}
46
Kevin Mayd92a6e42021-02-04 10:27:41 +000047Status IRuntime::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr network)
48{
49 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network));
50}
51
52Status IRuntime::LoadNetwork(NetworkId& networkIdOut,
53 IOptimizedNetworkPtr network,
54 std::string& errorMessage)
55{
56 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network), errorMessage);
57}
58
59Status IRuntime::LoadNetwork(NetworkId& networkIdOut,
60 IOptimizedNetworkPtr network,
61 std::string& errorMessage,
62 const INetworkProperties& networkProperties)
63{
64 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network), errorMessage, networkProperties);
65}
66
67TensorInfo IRuntime::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
68{
69 return pRuntimeImpl->GetInputTensorInfo(networkId, layerId);
70}
71
72TensorInfo IRuntime::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
73{
74 return pRuntimeImpl->GetOutputTensorInfo(networkId, layerId);
75}
76
77Status IRuntime::EnqueueWorkload(NetworkId networkId,
78 const InputTensors& inputTensors,
79 const OutputTensors& outputTensors)
80{
81 return pRuntimeImpl->EnqueueWorkload(networkId, inputTensors, outputTensors);
82}
83
Mike Kelly55a8ffd2021-04-07 20:10:49 +010084Status IRuntime::Execute(IWorkingMemHandle& workingMemHandle,
85 const InputTensors& inputTensors,
86 const OutputTensors& outputTensors)
87{
88 return pRuntimeImpl->Execute(workingMemHandle, inputTensors, outputTensors);
89}
90
Keith Davise813d672021-04-22 10:10:34 +010091void IRuntime::Schedule(NetworkId networkId,
92 const InputTensors& inputTensors,
93 const OutputTensors& outputTensors,
94 const QosExecPriority priority,
95 std::shared_ptr<IAsyncExecutionCallback> cb)
96{
97 pRuntimeImpl->Schedule(networkId, inputTensors, outputTensors, priority, cb);
98}
99
Kevin Mayd92a6e42021-02-04 10:27:41 +0000100Status IRuntime::UnloadNetwork(NetworkId networkId)
101{
102 return pRuntimeImpl->UnloadNetwork(networkId);
103}
104
105const IDeviceSpec& IRuntime::GetDeviceSpec() const
106{
107 return pRuntimeImpl->GetDeviceSpec();
108}
109
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100110std::unique_ptr<IWorkingMemHandle> IRuntime::CreateWorkingMemHandle(NetworkId networkId)
111{
112 return pRuntimeImpl->CreateWorkingMemHandle(networkId);
113}
114
Kevin Mayd92a6e42021-02-04 10:27:41 +0000115const std::shared_ptr<IProfiler> IRuntime::GetProfiler(NetworkId networkId) const
116{
117 return pRuntimeImpl->GetProfiler(networkId);
118}
119
120void IRuntime::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
121{
122 return pRuntimeImpl->RegisterDebugCallback(networkId, func);
123}
124
125int RuntimeImpl::GenerateNetworkId()
telsoa014fcda012018-03-09 14:13:49 +0000126{
127 return m_NetworkIdCounter++;
128}
129
Kevin Mayd92a6e42021-02-04 10:27:41 +0000130Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr inNetwork)
telsoa014fcda012018-03-09 14:13:49 +0000131{
telsoa01c577f2c2018-08-31 09:22:23 +0100132 std::string ignoredErrorMessage;
133 return LoadNetwork(networkIdOut, std::move(inNetwork), ignoredErrorMessage);
134}
135
Kevin Mayd92a6e42021-02-04 10:27:41 +0000136Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
137 IOptimizedNetworkPtr inNetwork,
138 std::string& errorMessage)
David Monahan4f1e8e42019-09-04 09:22:10 +0100139{
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100140 INetworkProperties networkProperties(false, MemorySource::Undefined, MemorySource::Undefined);
David Monahan4f1e8e42019-09-04 09:22:10 +0100141 return LoadNetwork(networkIdOut, std::move(inNetwork), errorMessage, networkProperties);
142}
143
Kevin Mayd92a6e42021-02-04 10:27:41 +0000144Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
145 IOptimizedNetworkPtr inNetwork,
146 std::string& errorMessage,
147 const INetworkProperties& networkProperties)
telsoa01c577f2c2018-08-31 09:22:23 +0100148{
telsoa014fcda012018-03-09 14:13:49 +0000149 IOptimizedNetwork* rawNetwork = inNetwork.release();
David Beck1b61be52018-11-08 09:19:14 +0000150
151 networkIdOut = GenerateNetworkId();
152
153 for (auto&& context : m_BackendContexts)
154 {
155 context.second->BeforeLoadNetwork(networkIdOut);
156 }
157
telsoa014fcda012018-03-09 14:13:49 +0000158 unique_ptr<LoadedNetwork> loadedNetwork = LoadedNetwork::MakeLoadedNetwork(
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000159 std::unique_ptr<IOptimizedNetwork>(rawNetwork),
David Monahan4f1e8e42019-09-04 09:22:10 +0100160 errorMessage,
Sadik Armagan3184c902020-03-18 10:57:30 +0000161 networkProperties,
Keith Davise813d672021-04-22 10:10:34 +0100162 m_ProfilingService,
163 networkIdOut);
telsoa014fcda012018-03-09 14:13:49 +0000164
165 if (!loadedNetwork)
166 {
167 return Status::Failure;
168 }
169
telsoa01c577f2c2018-08-31 09:22:23 +0100170 {
171 std::lock_guard<std::mutex> lockGuard(m_Mutex);
172
173 // Stores the network
174 m_LoadedNetworks[networkIdOut] = std::move(loadedNetwork);
175 }
telsoa014fcda012018-03-09 14:13:49 +0000176
David Beck1b61be52018-11-08 09:19:14 +0000177 for (auto&& context : m_BackendContexts)
178 {
179 context.second->AfterLoadNetwork(networkIdOut);
180 }
181
Sadik Armagan3184c902020-03-18 10:57:30 +0000182 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000183 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000184 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_LOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000185 }
186
telsoa014fcda012018-03-09 14:13:49 +0000187 return Status::Success;
telsoa014fcda012018-03-09 14:13:49 +0000188}
189
Kevin Mayd92a6e42021-02-04 10:27:41 +0000190Status RuntimeImpl::UnloadNetwork(NetworkId networkId)
telsoa014fcda012018-03-09 14:13:49 +0000191{
David Beck1b61be52018-11-08 09:19:14 +0000192 bool unloadOk = true;
193 for (auto&& context : m_BackendContexts)
David Beck9efb57d2018-11-05 13:40:33 +0000194 {
David Beck1b61be52018-11-08 09:19:14 +0000195 unloadOk &= context.second->BeforeUnloadNetwork(networkId);
David Beck9efb57d2018-11-05 13:40:33 +0000196 }
David Beck1b61be52018-11-08 09:19:14 +0000197
198 if (!unloadOk)
199 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000200 ARMNN_LOG(warning) << "RuntimeImpl::UnloadNetwork(): failed to unload "
Derek Lamberti08446972019-11-26 16:38:31 +0000201 "network with ID:" << networkId << " because BeforeUnloadNetwork failed";
David Beck1b61be52018-11-08 09:19:14 +0000202 return Status::Failure;
203 }
David Beck9efb57d2018-11-05 13:40:33 +0000204
Jim Flynnf7713212020-07-14 09:50:59 +0100205 std::unique_ptr<profiling::TimelineUtilityMethods> timelineUtils =
206 profiling::TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000207 {
telsoa01c577f2c2018-08-31 09:22:23 +0100208 std::lock_guard<std::mutex> lockGuard(m_Mutex);
209
Jim Flynnf7713212020-07-14 09:50:59 +0100210 // If timeline recording is on mark the Network end of life
211 if (timelineUtils)
212 {
213 auto search = m_LoadedNetworks.find(networkId);
214 if (search != m_LoadedNetworks.end())
215 {
216 profiling::ProfilingGuid networkGuid = search->second->GetNetworkGuid();
217 timelineUtils->RecordEvent(networkGuid,
218 profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
219 }
220 }
telsoa01c577f2c2018-08-31 09:22:23 +0100221 if (m_LoadedNetworks.erase(networkId) == 0)
222 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000223 ARMNN_LOG(warning) << "WARNING: RuntimeImpl::UnloadNetwork(): " << networkId << " not found!";
telsoa01c577f2c2018-08-31 09:22:23 +0100224 return Status::Failure;
225 }
Sadik Armagan3184c902020-03-18 10:57:30 +0000226
227 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000228 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000229 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_UNLOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000230 }
David Beck1b61be52018-11-08 09:19:14 +0000231 }
David Beck9efb57d2018-11-05 13:40:33 +0000232
David Beck1b61be52018-11-08 09:19:14 +0000233 for (auto&& context : m_BackendContexts)
234 {
235 context.second->AfterUnloadNetwork(networkId);
telsoa01c577f2c2018-08-31 09:22:23 +0100236 }
237
Kevin Mayd92a6e42021-02-04 10:27:41 +0000238 ARMNN_LOG(debug) << "RuntimeImpl::UnloadNetwork(): Unloaded network with ID: " << networkId;
telsoa014fcda012018-03-09 14:13:49 +0000239 return Status::Success;
240}
241
Kevin Mayd92a6e42021-02-04 10:27:41 +0000242const std::shared_ptr<IProfiler> RuntimeImpl::GetProfiler(NetworkId networkId) const
telsoa01c577f2c2018-08-31 09:22:23 +0100243{
244 auto it = m_LoadedNetworks.find(networkId);
245 if (it != m_LoadedNetworks.end())
246 {
247 auto& loadedNetwork = it->second;
248 return loadedNetwork->GetProfiler();
249 }
250
251 return nullptr;
252}
253
Kevin Mayd92a6e42021-02-04 10:27:41 +0000254void RuntimeImpl::ReportStructure() // armnn::profiling::IProfilingService& profilingService as param
Keith Davis33ed2212020-03-30 10:43:41 +0100255{
256 // No-op for the time being, but this may be useful in future to have the profilingService available
257 // if (profilingService.IsProfilingEnabled()){}
258
259 LoadedNetworks::iterator it = m_LoadedNetworks.begin();
260 while (it != m_LoadedNetworks.end())
261 {
262 auto& loadedNetwork = it->second;
263 loadedNetwork->SendNetworkStructure();
264 // Increment the Iterator to point to next entry
265 it++;
266 }
267}
268
Kevin Mayd92a6e42021-02-04 10:27:41 +0000269RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options)
Keith Davis33ed2212020-03-30 10:43:41 +0100270 : m_NetworkIdCounter(0),
271 m_ProfilingService(*this)
telsoa014fcda012018-03-09 14:13:49 +0000272{
alered01a7227ac2020-05-07 14:58:29 +0100273 const auto start_time = armnn::GetTimeNow();
Derek Lamberti08446972019-11-26 16:38:31 +0000274 ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION << "\n";
David Beck1b61be52018-11-08 09:19:14 +0000275
Keith Davis33ed2212020-03-30 10:43:41 +0100276 if ( options.m_ProfilingOptions.m_TimelineEnabled && !options.m_ProfilingOptions.m_EnableProfiling )
277 {
278 throw RuntimeException("It is not possible to enable timeline reporting without profiling being enabled");
279 }
280
Matteo Martincighe54aa062019-08-05 14:12:11 +0100281 // Load any available/compatible dynamic backend before the runtime
282 // goes through the backend registry
283 LoadDynamicBackends(options.m_DynamicBackendsPath);
284
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000285 BackendIdSet supportedBackends;
David Beck1b61be52018-11-08 09:19:14 +0000286 for (const auto& id : BackendRegistryInstance().GetBackendIds())
287 {
288 // Store backend contexts for the supported ones
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000289 try {
David Beck1b61be52018-11-08 09:19:14 +0000290 auto factoryFun = BackendRegistryInstance().GetFactory(id);
291 auto backend = factoryFun();
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100292 ARMNN_ASSERT(backend.get() != nullptr);
David Beck1b61be52018-11-08 09:19:14 +0000293
294 auto context = backend->CreateBackendContext(options);
295
296 // backends are allowed to return nullptrs if they
297 // don't wish to create a backend specific context
298 if (context)
299 {
300 m_BackendContexts.emplace(std::make_pair(id, std::move(context)));
301 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000302 supportedBackends.emplace(id);
Colm Donelan1aff3932020-02-05 17:48:59 +0000303
304 unique_ptr<armnn::profiling::IBackendProfiling> profilingIface =
305 std::make_unique<armnn::profiling::BackendProfiling>(armnn::profiling::BackendProfiling(
Sadik Armagan3184c902020-03-18 10:57:30 +0000306 options, m_ProfilingService, id));
Colm Donelan1aff3932020-02-05 17:48:59 +0000307
308 // Backends may also provide a profiling context. Ask for it now.
309 auto profilingContext = backend->CreateBackendProfilingContext(options, profilingIface);
310 // Backends that don't support profiling will return a null profiling context.
311 if (profilingContext)
312 {
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100313 // Pass the context onto the profiling service.
314 m_ProfilingService.AddBackendProfilingContext(id, profilingContext);
Colm Donelan1aff3932020-02-05 17:48:59 +0000315 }
David Beck1b61be52018-11-08 09:19:14 +0000316 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000317 catch (const BackendUnavailableException&)
318 {
319 // Ignore backends which are unavailable
320 }
David Beck1b61be52018-11-08 09:19:14 +0000321 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100322
Finn Williams45a73622020-05-15 18:41:05 +0100323 BackendRegistryInstance().SetProfilingService(m_ProfilingService);
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100324 // pass configuration info to the profiling service
325 m_ProfilingService.ConfigureProfilingService(options.m_ProfilingOptions);
Jim Flynn6398a982020-05-27 17:05:21 +0100326 if (options.m_ProfilingOptions.m_EnableProfiling)
327 {
328 // try to wait for the profiling service to initialise
329 m_ProfilingService.WaitForProfilingServiceActivation(3000);
330 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100331
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000332 m_DeviceSpec.AddSupportedBackends(supportedBackends);
alered01a7227ac2020-05-07 14:58:29 +0100333
334 ARMNN_LOG(info) << "Initialization time: " << std::setprecision(2)
335 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
surmeh01bceff2f2018-03-29 16:29:27 +0100336}
337
Kevin Mayd92a6e42021-02-04 10:27:41 +0000338RuntimeImpl::~RuntimeImpl()
surmeh01bceff2f2018-03-29 16:29:27 +0100339{
alered01a7227ac2020-05-07 14:58:29 +0100340 const auto start_time = armnn::GetTimeNow();
surmeh01bceff2f2018-03-29 16:29:27 +0100341 std::vector<int> networkIDs;
surmeh013537c2c2018-05-18 16:31:43 +0100342 try
343 {
344 // Coverity fix: The following code may throw an exception of type std::length_error.
345 std::transform(m_LoadedNetworks.begin(), m_LoadedNetworks.end(),
346 std::back_inserter(networkIDs),
347 [](const auto &pair) { return pair.first; });
348 }
349 catch (const std::exception& e)
350 {
351 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
352 // exception of type std::length_error.
353 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
354 std::cerr << "WARNING: An error has occurred when getting the IDs of the networks to unload: " << e.what()
355 << "\nSome of the loaded networks may not be unloaded" << std::endl;
356 }
357 // We then proceed to unload all the networks which IDs have been appended to the list
358 // up to the point the exception was thrown (if any).
surmeh01bceff2f2018-03-29 16:29:27 +0100359
360 for (auto networkID : networkIDs)
361 {
surmeh013537c2c2018-05-18 16:31:43 +0100362 try
363 {
364 // Coverity fix: UnloadNetwork() may throw an exception of type std::length_error,
365 // boost::log::v2s_mt_posix::odr_violation or boost::log::v2s_mt_posix::system_error
366 UnloadNetwork(networkID);
367 }
368 catch (const std::exception& e)
369 {
370 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
371 // exception of type std::length_error.
372 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
373 std::cerr << "WARNING: An error has occurred when unloading network " << networkID << ": " << e.what()
374 << std::endl;
375 }
telsoa014fcda012018-03-09 14:13:49 +0000376 }
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000377
378 // Clear all dynamic backends.
379 DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
380 m_DeviceSpec.ClearDynamicBackends();
Colm Donelan1aff3932020-02-05 17:48:59 +0000381 m_BackendContexts.clear();
Finn Williams45a73622020-05-15 18:41:05 +0100382
383 BackendRegistryInstance().SetProfilingService(armnn::EmptyOptional());
alered01a7227ac2020-05-07 14:58:29 +0100384 ARMNN_LOG(info) << "Shutdown time: " << std::setprecision(2)
385 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
telsoa014fcda012018-03-09 14:13:49 +0000386}
387
Kevin Mayd92a6e42021-02-04 10:27:41 +0000388LoadedNetwork* RuntimeImpl::GetLoadedNetworkPtr(NetworkId networkId) const
surmeh013537c2c2018-05-18 16:31:43 +0100389{
390 std::lock_guard<std::mutex> lockGuard(m_Mutex);
391 return m_LoadedNetworks.at(networkId).get();
392}
393
Kevin Mayd92a6e42021-02-04 10:27:41 +0000394TensorInfo RuntimeImpl::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000395{
surmeh013537c2c2018-05-18 16:31:43 +0100396 return GetLoadedNetworkPtr(networkId)->GetInputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000397}
398
Kevin Mayd92a6e42021-02-04 10:27:41 +0000399TensorInfo RuntimeImpl::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000400{
surmeh013537c2c2018-05-18 16:31:43 +0100401 return GetLoadedNetworkPtr(networkId)->GetOutputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000402}
403
Derek Lamberti03614f62018-10-02 15:52:46 +0100404
Kevin Mayd92a6e42021-02-04 10:27:41 +0000405Status RuntimeImpl::EnqueueWorkload(NetworkId networkId,
telsoa01c577f2c2018-08-31 09:22:23 +0100406 const InputTensors& inputTensors,
407 const OutputTensors& outputTensors)
telsoa014fcda012018-03-09 14:13:49 +0000408{
surmeh013537c2c2018-05-18 16:31:43 +0100409 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100410
411 if (!loadedNetwork)
412 {
413 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
414 return Status::Failure;
415 }
416 if (loadedNetwork->IsAsyncEnabled())
417 {
418 ARMNN_LOG(error) << "Network " << networkId << " is async enabled.\n";
419 return Status::Failure;
420 }
Narumol Prangnawarat5b4d0d52020-06-23 11:45:56 +0100421 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
422
423 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "EnqueueWorkload");
Derek Lamberti03614f62018-10-02 15:52:46 +0100424
425 static thread_local NetworkId lastId = networkId;
426 if (lastId != networkId)
427 {
428 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
429 {
430 network->FreeWorkingMemory();
431 });
432 }
433 lastId=networkId;
434
surmeh013537c2c2018-05-18 16:31:43 +0100435 return loadedNetwork->EnqueueWorkload(inputTensors, outputTensors);
telsoa014fcda012018-03-09 14:13:49 +0000436}
437
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100438Status RuntimeImpl::Execute(IWorkingMemHandle& iWorkingMemHandle,
439 const InputTensors& inputTensors,
440 const OutputTensors& outputTensors)
441{
442 NetworkId networkId = iWorkingMemHandle.GetNetworkId();
443 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
444
445 if (!loadedNetwork)
446 {
447 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
448 return Status::Failure;
449 }
450 if (!loadedNetwork->IsAsyncEnabled())
451 {
Keith Davise813d672021-04-22 10:10:34 +0100452 ARMNN_LOG(error) << "Attempting execute " << networkId << " when it is not async enabled.\n";
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100453 return Status::Failure;
454 }
455 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
456
457 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Execute");
458
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100459 return loadedNetwork->Execute(inputTensors, outputTensors, iWorkingMemHandle);
460}
461
Keith Davise813d672021-04-22 10:10:34 +0100462void RuntimeImpl::Schedule(NetworkId networkId,
463 const InputTensors& inputTensors,
464 const OutputTensors& outputTensors,
465 const QosExecPriority priority,
466 std::shared_ptr<IAsyncExecutionCallback> callback)
467{
468 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
469
470 if (!loadedNetwork)
471 {
472 throw armnn::Exception(
473 "Network with ID of " + std::to_string(networkId) + " does not exist \n"
474 );
475 }
476 if (!loadedNetwork->IsAsyncEnabled())
477 {
478 throw armnn::Exception(
479 "Attempting to schedule Network " + std::to_string(networkId) + " when it is not async enabled \n"
480 );
481 }
482
483 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
484
485 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Schedule");
486
487 loadedNetwork->Schedule(inputTensors, outputTensors, priority, callback);
488}
489
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100490/// Create a new unique WorkingMemHandle object. Create multiple handles if you wish to have
491/// overlapped Execution by calling this function from different threads.
492std::unique_ptr<IWorkingMemHandle> RuntimeImpl::CreateWorkingMemHandle(NetworkId networkId)
493{
494 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
495
496 if (!loadedNetwork)
497 {
498 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
499 return nullptr;
500 }
501 if (!loadedNetwork->IsAsyncEnabled())
502 {
503 ARMNN_LOG(error) << "Network " << networkId << " is not async enabled.\n";
504 return nullptr;
505 }
506 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
507
508 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "CreateWorkingMemHandle");
509
510 static thread_local NetworkId lastId = networkId;
511 if (lastId != networkId)
512 {
513 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
514 {
515 network->FreeWorkingMemory();
516 });
517 }
518 lastId=networkId;
519
520 return loadedNetwork->CreateWorkingMemHandle(networkId);
521}
522
Kevin Mayd92a6e42021-02-04 10:27:41 +0000523void RuntimeImpl::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +0000524{
525 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
526 loadedNetwork->RegisterDebugCallback(func);
527}
528
Kevin Mayd92a6e42021-02-04 10:27:41 +0000529void RuntimeImpl::LoadDynamicBackends(const std::string& overrideBackendPath)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100530{
531 // Get the paths where to load the dynamic backends from
532 std::vector<std::string> backendPaths = DynamicBackendUtils::GetBackendPaths(overrideBackendPath);
533
534 // Get the shared objects to try to load as dynamic backends
535 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
536
537 // Create a list of dynamic backends
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100538 m_DynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
539
540 // Register the dynamic backends in the backend registry
Matteo Martincigh89533902019-08-15 12:08:06 +0100541 BackendIdSet registeredBackendIds = DynamicBackendUtils::RegisterDynamicBackends(m_DynamicBackends);
542
543 // Add the registered dynamic backend ids to the list of supported backends
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000544 m_DeviceSpec.AddSupportedBackends(registeredBackendIds, true);
telsoa014fcda012018-03-09 14:13:49 +0000545}
Matteo Martincighe54aa062019-08-05 14:12:11 +0100546
547} // namespace armnn