blob: 374064e408c720ef68457894e6d271e7d3f33211 [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>
Matthew Benthamf48afc62020-01-15 17:55:08 +00009#include <armnn/Logging.hpp>
alered01a7227ac2020-05-07 14:58:29 +010010#include <armnn/utility/Timer.hpp>
Matteo Martincighe54aa062019-08-05 14:12:11 +010011
Matteo Martincighe5b8eb92019-11-28 15:45:42 +000012#include <armnn/backends/IBackendContext.hpp>
Matteo Martincighe54aa062019-08-05 14:12:11 +010013#include <backendsCommon/DynamicBackendUtils.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010014#include <armnn/utility/PolymorphicDowncast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000015
Nikhil Raj77fe76b2021-06-09 14:55:32 +010016#include <common/include/LabelsAndEventClasses.hpp>
17
surmeh013537c2c2018-05-18 16:31:43 +010018#include <iostream>
19
Colm Donelan1aff3932020-02-05 17:48:59 +000020#include <backends/BackendProfiling.hpp>
telsoa014fcda012018-03-09 14:13:49 +000021
22using namespace armnn;
23using namespace std;
24
25namespace armnn
26{
Kevin Mayd92a6e42021-02-04 10:27:41 +000027IRuntime::IRuntime() : pRuntimeImpl( new RuntimeImpl(armnn::IRuntime::CreationOptions())) {}
28
29IRuntime::IRuntime(const IRuntime::CreationOptions& options) : pRuntimeImpl(new RuntimeImpl(options)) {}
30
31IRuntime::~IRuntime() = default;
telsoa014fcda012018-03-09 14:13:49 +000032
33IRuntime* IRuntime::CreateRaw(const CreationOptions& options)
34{
Kevin Mayd92a6e42021-02-04 10:27:41 +000035 return new IRuntime(options);
telsoa014fcda012018-03-09 14:13:49 +000036}
37
38IRuntimePtr IRuntime::Create(const CreationOptions& options)
39{
40 return IRuntimePtr(CreateRaw(options), &IRuntime::Destroy);
41}
42
43void IRuntime::Destroy(IRuntime* runtime)
44{
Kevin Mayd92a6e42021-02-04 10:27:41 +000045 delete runtime;
telsoa014fcda012018-03-09 14:13:49 +000046}
47
Kevin Mayd92a6e42021-02-04 10:27:41 +000048Status IRuntime::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr network)
49{
50 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network));
51}
52
53Status IRuntime::LoadNetwork(NetworkId& networkIdOut,
54 IOptimizedNetworkPtr network,
55 std::string& errorMessage)
56{
57 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network), errorMessage);
58}
59
60Status IRuntime::LoadNetwork(NetworkId& networkIdOut,
61 IOptimizedNetworkPtr network,
62 std::string& errorMessage,
63 const INetworkProperties& networkProperties)
64{
65 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network), errorMessage, networkProperties);
66}
67
68TensorInfo IRuntime::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
69{
70 return pRuntimeImpl->GetInputTensorInfo(networkId, layerId);
71}
72
73TensorInfo IRuntime::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
74{
75 return pRuntimeImpl->GetOutputTensorInfo(networkId, layerId);
76}
77
78Status IRuntime::EnqueueWorkload(NetworkId networkId,
79 const InputTensors& inputTensors,
80 const OutputTensors& outputTensors)
81{
82 return pRuntimeImpl->EnqueueWorkload(networkId, inputTensors, outputTensors);
83}
84
Mike Kelly55a8ffd2021-04-07 20:10:49 +010085Status IRuntime::Execute(IWorkingMemHandle& workingMemHandle,
86 const InputTensors& inputTensors,
87 const OutputTensors& outputTensors)
88{
89 return pRuntimeImpl->Execute(workingMemHandle, inputTensors, outputTensors);
90}
91
Keith Davise813d672021-04-22 10:10:34 +010092void IRuntime::Schedule(NetworkId networkId,
93 const InputTensors& inputTensors,
94 const OutputTensors& outputTensors,
95 const QosExecPriority priority,
96 std::shared_ptr<IAsyncExecutionCallback> cb)
97{
98 pRuntimeImpl->Schedule(networkId, inputTensors, outputTensors, priority, cb);
99}
100
Kevin Mayd92a6e42021-02-04 10:27:41 +0000101Status IRuntime::UnloadNetwork(NetworkId networkId)
102{
103 return pRuntimeImpl->UnloadNetwork(networkId);
104}
105
106const IDeviceSpec& IRuntime::GetDeviceSpec() const
107{
108 return pRuntimeImpl->GetDeviceSpec();
109}
110
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100111std::unique_ptr<IWorkingMemHandle> IRuntime::CreateWorkingMemHandle(NetworkId networkId)
112{
113 return pRuntimeImpl->CreateWorkingMemHandle(networkId);
114}
115
Kevin Mayd92a6e42021-02-04 10:27:41 +0000116const std::shared_ptr<IProfiler> IRuntime::GetProfiler(NetworkId networkId) const
117{
118 return pRuntimeImpl->GetProfiler(networkId);
119}
120
121void IRuntime::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
122{
123 return pRuntimeImpl->RegisterDebugCallback(networkId, func);
124}
125
126int RuntimeImpl::GenerateNetworkId()
telsoa014fcda012018-03-09 14:13:49 +0000127{
128 return m_NetworkIdCounter++;
129}
130
Kevin Mayd92a6e42021-02-04 10:27:41 +0000131Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr inNetwork)
telsoa014fcda012018-03-09 14:13:49 +0000132{
telsoa01c577f2c2018-08-31 09:22:23 +0100133 std::string ignoredErrorMessage;
134 return LoadNetwork(networkIdOut, std::move(inNetwork), ignoredErrorMessage);
135}
136
Kevin Mayd92a6e42021-02-04 10:27:41 +0000137Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
138 IOptimizedNetworkPtr inNetwork,
139 std::string& errorMessage)
David Monahan4f1e8e42019-09-04 09:22:10 +0100140{
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100141 INetworkProperties networkProperties(false, MemorySource::Undefined, MemorySource::Undefined);
David Monahan4f1e8e42019-09-04 09:22:10 +0100142 return LoadNetwork(networkIdOut, std::move(inNetwork), errorMessage, networkProperties);
143}
144
Kevin Mayd92a6e42021-02-04 10:27:41 +0000145Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
146 IOptimizedNetworkPtr inNetwork,
147 std::string& errorMessage,
148 const INetworkProperties& networkProperties)
telsoa01c577f2c2018-08-31 09:22:23 +0100149{
telsoa014fcda012018-03-09 14:13:49 +0000150 IOptimizedNetwork* rawNetwork = inNetwork.release();
David Beck1b61be52018-11-08 09:19:14 +0000151
152 networkIdOut = GenerateNetworkId();
153
154 for (auto&& context : m_BackendContexts)
155 {
156 context.second->BeforeLoadNetwork(networkIdOut);
157 }
158
telsoa014fcda012018-03-09 14:13:49 +0000159 unique_ptr<LoadedNetwork> loadedNetwork = LoadedNetwork::MakeLoadedNetwork(
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000160 std::unique_ptr<IOptimizedNetwork>(rawNetwork),
David Monahan4f1e8e42019-09-04 09:22:10 +0100161 errorMessage,
Sadik Armagan3184c902020-03-18 10:57:30 +0000162 networkProperties,
Keith Davise813d672021-04-22 10:10:34 +0100163 m_ProfilingService,
164 networkIdOut);
telsoa014fcda012018-03-09 14:13:49 +0000165
166 if (!loadedNetwork)
167 {
168 return Status::Failure;
169 }
170
telsoa01c577f2c2018-08-31 09:22:23 +0100171 {
172 std::lock_guard<std::mutex> lockGuard(m_Mutex);
173
174 // Stores the network
175 m_LoadedNetworks[networkIdOut] = std::move(loadedNetwork);
176 }
telsoa014fcda012018-03-09 14:13:49 +0000177
David Beck1b61be52018-11-08 09:19:14 +0000178 for (auto&& context : m_BackendContexts)
179 {
180 context.second->AfterLoadNetwork(networkIdOut);
181 }
182
Sadik Armagan3184c902020-03-18 10:57:30 +0000183 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000184 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000185 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_LOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000186 }
187
telsoa014fcda012018-03-09 14:13:49 +0000188 return Status::Success;
telsoa014fcda012018-03-09 14:13:49 +0000189}
190
Kevin Mayd92a6e42021-02-04 10:27:41 +0000191Status RuntimeImpl::UnloadNetwork(NetworkId networkId)
telsoa014fcda012018-03-09 14:13:49 +0000192{
David Beck1b61be52018-11-08 09:19:14 +0000193 bool unloadOk = true;
194 for (auto&& context : m_BackendContexts)
David Beck9efb57d2018-11-05 13:40:33 +0000195 {
David Beck1b61be52018-11-08 09:19:14 +0000196 unloadOk &= context.second->BeforeUnloadNetwork(networkId);
David Beck9efb57d2018-11-05 13:40:33 +0000197 }
David Beck1b61be52018-11-08 09:19:14 +0000198
199 if (!unloadOk)
200 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000201 ARMNN_LOG(warning) << "RuntimeImpl::UnloadNetwork(): failed to unload "
Derek Lamberti08446972019-11-26 16:38:31 +0000202 "network with ID:" << networkId << " because BeforeUnloadNetwork failed";
David Beck1b61be52018-11-08 09:19:14 +0000203 return Status::Failure;
204 }
David Beck9efb57d2018-11-05 13:40:33 +0000205
Jim Flynnf7713212020-07-14 09:50:59 +0100206 std::unique_ptr<profiling::TimelineUtilityMethods> timelineUtils =
207 profiling::TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000208 {
telsoa01c577f2c2018-08-31 09:22:23 +0100209 std::lock_guard<std::mutex> lockGuard(m_Mutex);
210
Jim Flynnf7713212020-07-14 09:50:59 +0100211 // If timeline recording is on mark the Network end of life
212 if (timelineUtils)
213 {
214 auto search = m_LoadedNetworks.find(networkId);
215 if (search != m_LoadedNetworks.end())
216 {
217 profiling::ProfilingGuid networkGuid = search->second->GetNetworkGuid();
218 timelineUtils->RecordEvent(networkGuid,
219 profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
220 }
221 }
telsoa01c577f2c2018-08-31 09:22:23 +0100222 if (m_LoadedNetworks.erase(networkId) == 0)
223 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000224 ARMNN_LOG(warning) << "WARNING: RuntimeImpl::UnloadNetwork(): " << networkId << " not found!";
telsoa01c577f2c2018-08-31 09:22:23 +0100225 return Status::Failure;
226 }
Sadik Armagan3184c902020-03-18 10:57:30 +0000227
228 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000229 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000230 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_UNLOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000231 }
David Beck1b61be52018-11-08 09:19:14 +0000232 }
David Beck9efb57d2018-11-05 13:40:33 +0000233
David Beck1b61be52018-11-08 09:19:14 +0000234 for (auto&& context : m_BackendContexts)
235 {
236 context.second->AfterUnloadNetwork(networkId);
telsoa01c577f2c2018-08-31 09:22:23 +0100237 }
238
Kevin Mayd92a6e42021-02-04 10:27:41 +0000239 ARMNN_LOG(debug) << "RuntimeImpl::UnloadNetwork(): Unloaded network with ID: " << networkId;
telsoa014fcda012018-03-09 14:13:49 +0000240 return Status::Success;
241}
242
Kevin Mayd92a6e42021-02-04 10:27:41 +0000243const std::shared_ptr<IProfiler> RuntimeImpl::GetProfiler(NetworkId networkId) const
telsoa01c577f2c2018-08-31 09:22:23 +0100244{
245 auto it = m_LoadedNetworks.find(networkId);
246 if (it != m_LoadedNetworks.end())
247 {
248 auto& loadedNetwork = it->second;
249 return loadedNetwork->GetProfiler();
250 }
251
252 return nullptr;
253}
254
Kevin Mayd92a6e42021-02-04 10:27:41 +0000255void RuntimeImpl::ReportStructure() // armnn::profiling::IProfilingService& profilingService as param
Keith Davis33ed2212020-03-30 10:43:41 +0100256{
257 // No-op for the time being, but this may be useful in future to have the profilingService available
258 // if (profilingService.IsProfilingEnabled()){}
259
260 LoadedNetworks::iterator it = m_LoadedNetworks.begin();
261 while (it != m_LoadedNetworks.end())
262 {
263 auto& loadedNetwork = it->second;
264 loadedNetwork->SendNetworkStructure();
265 // Increment the Iterator to point to next entry
266 it++;
267 }
268}
269
Kevin Mayd92a6e42021-02-04 10:27:41 +0000270RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options)
Keith Davis33ed2212020-03-30 10:43:41 +0100271 : m_NetworkIdCounter(0),
272 m_ProfilingService(*this)
telsoa014fcda012018-03-09 14:13:49 +0000273{
alered01a7227ac2020-05-07 14:58:29 +0100274 const auto start_time = armnn::GetTimeNow();
Derek Lamberti08446972019-11-26 16:38:31 +0000275 ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION << "\n";
David Beck1b61be52018-11-08 09:19:14 +0000276
Keith Davis33ed2212020-03-30 10:43:41 +0100277 if ( options.m_ProfilingOptions.m_TimelineEnabled && !options.m_ProfilingOptions.m_EnableProfiling )
278 {
279 throw RuntimeException("It is not possible to enable timeline reporting without profiling being enabled");
280 }
281
Matteo Martincighe54aa062019-08-05 14:12:11 +0100282 // Load any available/compatible dynamic backend before the runtime
283 // goes through the backend registry
284 LoadDynamicBackends(options.m_DynamicBackendsPath);
285
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000286 BackendIdSet supportedBackends;
David Beck1b61be52018-11-08 09:19:14 +0000287 for (const auto& id : BackendRegistryInstance().GetBackendIds())
288 {
289 // Store backend contexts for the supported ones
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000290 try {
David Beck1b61be52018-11-08 09:19:14 +0000291 auto factoryFun = BackendRegistryInstance().GetFactory(id);
292 auto backend = factoryFun();
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100293 ARMNN_ASSERT(backend.get() != nullptr);
David Beck1b61be52018-11-08 09:19:14 +0000294
295 auto context = backend->CreateBackendContext(options);
296
297 // backends are allowed to return nullptrs if they
298 // don't wish to create a backend specific context
299 if (context)
300 {
301 m_BackendContexts.emplace(std::make_pair(id, std::move(context)));
302 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000303 supportedBackends.emplace(id);
Colm Donelan1aff3932020-02-05 17:48:59 +0000304
305 unique_ptr<armnn::profiling::IBackendProfiling> profilingIface =
306 std::make_unique<armnn::profiling::BackendProfiling>(armnn::profiling::BackendProfiling(
Sadik Armagan3184c902020-03-18 10:57:30 +0000307 options, m_ProfilingService, id));
Colm Donelan1aff3932020-02-05 17:48:59 +0000308
309 // Backends may also provide a profiling context. Ask for it now.
310 auto profilingContext = backend->CreateBackendProfilingContext(options, profilingIface);
311 // Backends that don't support profiling will return a null profiling context.
312 if (profilingContext)
313 {
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100314 // Pass the context onto the profiling service.
315 m_ProfilingService.AddBackendProfilingContext(id, profilingContext);
Colm Donelan1aff3932020-02-05 17:48:59 +0000316 }
David Beck1b61be52018-11-08 09:19:14 +0000317 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000318 catch (const BackendUnavailableException&)
319 {
320 // Ignore backends which are unavailable
321 }
David Beck1b61be52018-11-08 09:19:14 +0000322 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100323
Finn Williams45a73622020-05-15 18:41:05 +0100324 BackendRegistryInstance().SetProfilingService(m_ProfilingService);
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100325 // pass configuration info to the profiling service
326 m_ProfilingService.ConfigureProfilingService(options.m_ProfilingOptions);
Jim Flynn6398a982020-05-27 17:05:21 +0100327 if (options.m_ProfilingOptions.m_EnableProfiling)
328 {
329 // try to wait for the profiling service to initialise
330 m_ProfilingService.WaitForProfilingServiceActivation(3000);
331 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100332
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000333 m_DeviceSpec.AddSupportedBackends(supportedBackends);
alered01a7227ac2020-05-07 14:58:29 +0100334
335 ARMNN_LOG(info) << "Initialization time: " << std::setprecision(2)
336 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
surmeh01bceff2f2018-03-29 16:29:27 +0100337}
338
Kevin Mayd92a6e42021-02-04 10:27:41 +0000339RuntimeImpl::~RuntimeImpl()
surmeh01bceff2f2018-03-29 16:29:27 +0100340{
alered01a7227ac2020-05-07 14:58:29 +0100341 const auto start_time = armnn::GetTimeNow();
surmeh01bceff2f2018-03-29 16:29:27 +0100342 std::vector<int> networkIDs;
surmeh013537c2c2018-05-18 16:31:43 +0100343 try
344 {
345 // Coverity fix: The following code may throw an exception of type std::length_error.
346 std::transform(m_LoadedNetworks.begin(), m_LoadedNetworks.end(),
347 std::back_inserter(networkIDs),
348 [](const auto &pair) { return pair.first; });
349 }
350 catch (const std::exception& e)
351 {
352 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
353 // exception of type std::length_error.
354 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
355 std::cerr << "WARNING: An error has occurred when getting the IDs of the networks to unload: " << e.what()
356 << "\nSome of the loaded networks may not be unloaded" << std::endl;
357 }
358 // We then proceed to unload all the networks which IDs have been appended to the list
359 // up to the point the exception was thrown (if any).
surmeh01bceff2f2018-03-29 16:29:27 +0100360
361 for (auto networkID : networkIDs)
362 {
surmeh013537c2c2018-05-18 16:31:43 +0100363 try
364 {
365 // Coverity fix: UnloadNetwork() may throw an exception of type std::length_error,
366 // boost::log::v2s_mt_posix::odr_violation or boost::log::v2s_mt_posix::system_error
367 UnloadNetwork(networkID);
368 }
369 catch (const std::exception& e)
370 {
371 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
372 // exception of type std::length_error.
373 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
374 std::cerr << "WARNING: An error has occurred when unloading network " << networkID << ": " << e.what()
375 << std::endl;
376 }
telsoa014fcda012018-03-09 14:13:49 +0000377 }
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000378
379 // Clear all dynamic backends.
380 DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
381 m_DeviceSpec.ClearDynamicBackends();
Colm Donelan1aff3932020-02-05 17:48:59 +0000382 m_BackendContexts.clear();
Finn Williams45a73622020-05-15 18:41:05 +0100383
384 BackendRegistryInstance().SetProfilingService(armnn::EmptyOptional());
alered01a7227ac2020-05-07 14:58:29 +0100385 ARMNN_LOG(info) << "Shutdown time: " << std::setprecision(2)
386 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
telsoa014fcda012018-03-09 14:13:49 +0000387}
388
Kevin Mayd92a6e42021-02-04 10:27:41 +0000389LoadedNetwork* RuntimeImpl::GetLoadedNetworkPtr(NetworkId networkId) const
surmeh013537c2c2018-05-18 16:31:43 +0100390{
391 std::lock_guard<std::mutex> lockGuard(m_Mutex);
392 return m_LoadedNetworks.at(networkId).get();
393}
394
Kevin Mayd92a6e42021-02-04 10:27:41 +0000395TensorInfo RuntimeImpl::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000396{
surmeh013537c2c2018-05-18 16:31:43 +0100397 return GetLoadedNetworkPtr(networkId)->GetInputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000398}
399
Kevin Mayd92a6e42021-02-04 10:27:41 +0000400TensorInfo RuntimeImpl::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000401{
surmeh013537c2c2018-05-18 16:31:43 +0100402 return GetLoadedNetworkPtr(networkId)->GetOutputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000403}
404
Derek Lamberti03614f62018-10-02 15:52:46 +0100405
Kevin Mayd92a6e42021-02-04 10:27:41 +0000406Status RuntimeImpl::EnqueueWorkload(NetworkId networkId,
telsoa01c577f2c2018-08-31 09:22:23 +0100407 const InputTensors& inputTensors,
408 const OutputTensors& outputTensors)
telsoa014fcda012018-03-09 14:13:49 +0000409{
surmeh013537c2c2018-05-18 16:31:43 +0100410 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100411
412 if (!loadedNetwork)
413 {
414 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
415 return Status::Failure;
416 }
417 if (loadedNetwork->IsAsyncEnabled())
418 {
419 ARMNN_LOG(error) << "Network " << networkId << " is async enabled.\n";
420 return Status::Failure;
421 }
Narumol Prangnawarat5b4d0d52020-06-23 11:45:56 +0100422 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
423
424 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "EnqueueWorkload");
Derek Lamberti03614f62018-10-02 15:52:46 +0100425
426 static thread_local NetworkId lastId = networkId;
427 if (lastId != networkId)
428 {
429 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
430 {
431 network->FreeWorkingMemory();
432 });
433 }
434 lastId=networkId;
435
surmeh013537c2c2018-05-18 16:31:43 +0100436 return loadedNetwork->EnqueueWorkload(inputTensors, outputTensors);
telsoa014fcda012018-03-09 14:13:49 +0000437}
438
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100439Status RuntimeImpl::Execute(IWorkingMemHandle& iWorkingMemHandle,
440 const InputTensors& inputTensors,
441 const OutputTensors& outputTensors)
442{
443 NetworkId networkId = iWorkingMemHandle.GetNetworkId();
444 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
445
446 if (!loadedNetwork)
447 {
448 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
449 return Status::Failure;
450 }
451 if (!loadedNetwork->IsAsyncEnabled())
452 {
Keith Davise813d672021-04-22 10:10:34 +0100453 ARMNN_LOG(error) << "Attempting execute " << networkId << " when it is not async enabled.\n";
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100454 return Status::Failure;
455 }
456 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
457
458 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Execute");
459
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100460 return loadedNetwork->Execute(inputTensors, outputTensors, iWorkingMemHandle);
461}
462
Keith Davise813d672021-04-22 10:10:34 +0100463void RuntimeImpl::Schedule(NetworkId networkId,
464 const InputTensors& inputTensors,
465 const OutputTensors& outputTensors,
466 const QosExecPriority priority,
467 std::shared_ptr<IAsyncExecutionCallback> callback)
468{
469 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
470
471 if (!loadedNetwork)
472 {
473 throw armnn::Exception(
474 "Network with ID of " + std::to_string(networkId) + " does not exist \n"
475 );
476 }
477 if (!loadedNetwork->IsAsyncEnabled())
478 {
479 throw armnn::Exception(
480 "Attempting to schedule Network " + std::to_string(networkId) + " when it is not async enabled \n"
481 );
482 }
483
484 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
485
486 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Schedule");
487
488 loadedNetwork->Schedule(inputTensors, outputTensors, priority, callback);
489}
490
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100491/// Create a new unique WorkingMemHandle object. Create multiple handles if you wish to have
492/// overlapped Execution by calling this function from different threads.
493std::unique_ptr<IWorkingMemHandle> RuntimeImpl::CreateWorkingMemHandle(NetworkId networkId)
494{
495 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
496
497 if (!loadedNetwork)
498 {
499 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
500 return nullptr;
501 }
502 if (!loadedNetwork->IsAsyncEnabled())
503 {
504 ARMNN_LOG(error) << "Network " << networkId << " is not async enabled.\n";
505 return nullptr;
506 }
507 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
508
509 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "CreateWorkingMemHandle");
510
511 static thread_local NetworkId lastId = networkId;
512 if (lastId != networkId)
513 {
514 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
515 {
516 network->FreeWorkingMemory();
517 });
518 }
519 lastId=networkId;
520
521 return loadedNetwork->CreateWorkingMemHandle(networkId);
522}
523
Kevin Mayd92a6e42021-02-04 10:27:41 +0000524void RuntimeImpl::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +0000525{
526 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
527 loadedNetwork->RegisterDebugCallback(func);
528}
529
Kevin Mayd92a6e42021-02-04 10:27:41 +0000530void RuntimeImpl::LoadDynamicBackends(const std::string& overrideBackendPath)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100531{
532 // Get the paths where to load the dynamic backends from
533 std::vector<std::string> backendPaths = DynamicBackendUtils::GetBackendPaths(overrideBackendPath);
534
535 // Get the shared objects to try to load as dynamic backends
536 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
537
538 // Create a list of dynamic backends
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100539 m_DynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
540
541 // Register the dynamic backends in the backend registry
Matteo Martincigh89533902019-08-15 12:08:06 +0100542 BackendIdSet registeredBackendIds = DynamicBackendUtils::RegisterDynamicBackends(m_DynamicBackends);
543
544 // Add the registered dynamic backend ids to the list of supported backends
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000545 m_DeviceSpec.AddSupportedBackends(registeredBackendIds, true);
telsoa014fcda012018-03-09 14:13:49 +0000546}
Matteo Martincighe54aa062019-08-05 14:12:11 +0100547
548} // namespace armnn