blob: 91a21d4b53a6e75c9c02ea180b279cecb7634353 [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
Kevin Mayd92a6e42021-02-04 10:27:41 +000091Status IRuntime::UnloadNetwork(NetworkId networkId)
92{
93 return pRuntimeImpl->UnloadNetwork(networkId);
94}
95
96const IDeviceSpec& IRuntime::GetDeviceSpec() const
97{
98 return pRuntimeImpl->GetDeviceSpec();
99}
100
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100101std::unique_ptr<IWorkingMemHandle> IRuntime::CreateWorkingMemHandle(NetworkId networkId)
102{
103 return pRuntimeImpl->CreateWorkingMemHandle(networkId);
104}
105
Kevin Mayd92a6e42021-02-04 10:27:41 +0000106const std::shared_ptr<IProfiler> IRuntime::GetProfiler(NetworkId networkId) const
107{
108 return pRuntimeImpl->GetProfiler(networkId);
109}
110
111void IRuntime::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
112{
113 return pRuntimeImpl->RegisterDebugCallback(networkId, func);
114}
115
116int RuntimeImpl::GenerateNetworkId()
telsoa014fcda012018-03-09 14:13:49 +0000117{
118 return m_NetworkIdCounter++;
119}
120
Kevin Mayd92a6e42021-02-04 10:27:41 +0000121Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr inNetwork)
telsoa014fcda012018-03-09 14:13:49 +0000122{
telsoa01c577f2c2018-08-31 09:22:23 +0100123 std::string ignoredErrorMessage;
124 return LoadNetwork(networkIdOut, std::move(inNetwork), ignoredErrorMessage);
125}
126
Kevin Mayd92a6e42021-02-04 10:27:41 +0000127Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
128 IOptimizedNetworkPtr inNetwork,
129 std::string& errorMessage)
David Monahan4f1e8e42019-09-04 09:22:10 +0100130{
131 INetworkProperties networkProperties;
132 return LoadNetwork(networkIdOut, std::move(inNetwork), errorMessage, networkProperties);
133}
134
Kevin Mayd92a6e42021-02-04 10:27:41 +0000135Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
136 IOptimizedNetworkPtr inNetwork,
137 std::string& errorMessage,
138 const INetworkProperties& networkProperties)
telsoa01c577f2c2018-08-31 09:22:23 +0100139{
telsoa014fcda012018-03-09 14:13:49 +0000140 IOptimizedNetwork* rawNetwork = inNetwork.release();
David Beck1b61be52018-11-08 09:19:14 +0000141
142 networkIdOut = GenerateNetworkId();
143
144 for (auto&& context : m_BackendContexts)
145 {
146 context.second->BeforeLoadNetwork(networkIdOut);
147 }
148
telsoa014fcda012018-03-09 14:13:49 +0000149 unique_ptr<LoadedNetwork> loadedNetwork = LoadedNetwork::MakeLoadedNetwork(
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000150 std::unique_ptr<IOptimizedNetwork>(rawNetwork),
David Monahan4f1e8e42019-09-04 09:22:10 +0100151 errorMessage,
Sadik Armagan3184c902020-03-18 10:57:30 +0000152 networkProperties,
153 m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000154
155 if (!loadedNetwork)
156 {
157 return Status::Failure;
158 }
159
telsoa01c577f2c2018-08-31 09:22:23 +0100160 {
161 std::lock_guard<std::mutex> lockGuard(m_Mutex);
162
163 // Stores the network
164 m_LoadedNetworks[networkIdOut] = std::move(loadedNetwork);
165 }
telsoa014fcda012018-03-09 14:13:49 +0000166
David Beck1b61be52018-11-08 09:19:14 +0000167 for (auto&& context : m_BackendContexts)
168 {
169 context.second->AfterLoadNetwork(networkIdOut);
170 }
171
Sadik Armagan3184c902020-03-18 10:57:30 +0000172 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000173 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000174 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_LOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000175 }
176
telsoa014fcda012018-03-09 14:13:49 +0000177 return Status::Success;
telsoa014fcda012018-03-09 14:13:49 +0000178}
179
Kevin Mayd92a6e42021-02-04 10:27:41 +0000180Status RuntimeImpl::UnloadNetwork(NetworkId networkId)
telsoa014fcda012018-03-09 14:13:49 +0000181{
David Beck1b61be52018-11-08 09:19:14 +0000182 bool unloadOk = true;
183 for (auto&& context : m_BackendContexts)
David Beck9efb57d2018-11-05 13:40:33 +0000184 {
David Beck1b61be52018-11-08 09:19:14 +0000185 unloadOk &= context.second->BeforeUnloadNetwork(networkId);
David Beck9efb57d2018-11-05 13:40:33 +0000186 }
David Beck1b61be52018-11-08 09:19:14 +0000187
188 if (!unloadOk)
189 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000190 ARMNN_LOG(warning) << "RuntimeImpl::UnloadNetwork(): failed to unload "
Derek Lamberti08446972019-11-26 16:38:31 +0000191 "network with ID:" << networkId << " because BeforeUnloadNetwork failed";
David Beck1b61be52018-11-08 09:19:14 +0000192 return Status::Failure;
193 }
David Beck9efb57d2018-11-05 13:40:33 +0000194
Jim Flynnf7713212020-07-14 09:50:59 +0100195 std::unique_ptr<profiling::TimelineUtilityMethods> timelineUtils =
196 profiling::TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000197 {
telsoa01c577f2c2018-08-31 09:22:23 +0100198 std::lock_guard<std::mutex> lockGuard(m_Mutex);
199
Jim Flynnf7713212020-07-14 09:50:59 +0100200 // If timeline recording is on mark the Network end of life
201 if (timelineUtils)
202 {
203 auto search = m_LoadedNetworks.find(networkId);
204 if (search != m_LoadedNetworks.end())
205 {
206 profiling::ProfilingGuid networkGuid = search->second->GetNetworkGuid();
207 timelineUtils->RecordEvent(networkGuid,
208 profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
209 }
210 }
telsoa01c577f2c2018-08-31 09:22:23 +0100211 if (m_LoadedNetworks.erase(networkId) == 0)
212 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000213 ARMNN_LOG(warning) << "WARNING: RuntimeImpl::UnloadNetwork(): " << networkId << " not found!";
telsoa01c577f2c2018-08-31 09:22:23 +0100214 return Status::Failure;
215 }
Sadik Armagan3184c902020-03-18 10:57:30 +0000216
217 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000218 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000219 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_UNLOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000220 }
David Beck1b61be52018-11-08 09:19:14 +0000221 }
David Beck9efb57d2018-11-05 13:40:33 +0000222
David Beck1b61be52018-11-08 09:19:14 +0000223 for (auto&& context : m_BackendContexts)
224 {
225 context.second->AfterUnloadNetwork(networkId);
telsoa01c577f2c2018-08-31 09:22:23 +0100226 }
227
Kevin Mayd92a6e42021-02-04 10:27:41 +0000228 ARMNN_LOG(debug) << "RuntimeImpl::UnloadNetwork(): Unloaded network with ID: " << networkId;
telsoa014fcda012018-03-09 14:13:49 +0000229 return Status::Success;
230}
231
Kevin Mayd92a6e42021-02-04 10:27:41 +0000232const std::shared_ptr<IProfiler> RuntimeImpl::GetProfiler(NetworkId networkId) const
telsoa01c577f2c2018-08-31 09:22:23 +0100233{
234 auto it = m_LoadedNetworks.find(networkId);
235 if (it != m_LoadedNetworks.end())
236 {
237 auto& loadedNetwork = it->second;
238 return loadedNetwork->GetProfiler();
239 }
240
241 return nullptr;
242}
243
Kevin Mayd92a6e42021-02-04 10:27:41 +0000244void RuntimeImpl::ReportStructure() // armnn::profiling::IProfilingService& profilingService as param
Keith Davis33ed2212020-03-30 10:43:41 +0100245{
246 // No-op for the time being, but this may be useful in future to have the profilingService available
247 // if (profilingService.IsProfilingEnabled()){}
248
249 LoadedNetworks::iterator it = m_LoadedNetworks.begin();
250 while (it != m_LoadedNetworks.end())
251 {
252 auto& loadedNetwork = it->second;
253 loadedNetwork->SendNetworkStructure();
254 // Increment the Iterator to point to next entry
255 it++;
256 }
257}
258
Kevin Mayd92a6e42021-02-04 10:27:41 +0000259RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options)
Keith Davis33ed2212020-03-30 10:43:41 +0100260 : m_NetworkIdCounter(0),
261 m_ProfilingService(*this)
telsoa014fcda012018-03-09 14:13:49 +0000262{
alered01a7227ac2020-05-07 14:58:29 +0100263 const auto start_time = armnn::GetTimeNow();
Derek Lamberti08446972019-11-26 16:38:31 +0000264 ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION << "\n";
David Beck1b61be52018-11-08 09:19:14 +0000265
Keith Davis33ed2212020-03-30 10:43:41 +0100266 if ( options.m_ProfilingOptions.m_TimelineEnabled && !options.m_ProfilingOptions.m_EnableProfiling )
267 {
268 throw RuntimeException("It is not possible to enable timeline reporting without profiling being enabled");
269 }
270
Matteo Martincighe54aa062019-08-05 14:12:11 +0100271 // Load any available/compatible dynamic backend before the runtime
272 // goes through the backend registry
273 LoadDynamicBackends(options.m_DynamicBackendsPath);
274
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000275 BackendIdSet supportedBackends;
David Beck1b61be52018-11-08 09:19:14 +0000276 for (const auto& id : BackendRegistryInstance().GetBackendIds())
277 {
278 // Store backend contexts for the supported ones
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000279 try {
David Beck1b61be52018-11-08 09:19:14 +0000280 auto factoryFun = BackendRegistryInstance().GetFactory(id);
281 auto backend = factoryFun();
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100282 ARMNN_ASSERT(backend.get() != nullptr);
David Beck1b61be52018-11-08 09:19:14 +0000283
284 auto context = backend->CreateBackendContext(options);
285
286 // backends are allowed to return nullptrs if they
287 // don't wish to create a backend specific context
288 if (context)
289 {
290 m_BackendContexts.emplace(std::make_pair(id, std::move(context)));
291 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000292 supportedBackends.emplace(id);
Colm Donelan1aff3932020-02-05 17:48:59 +0000293
294 unique_ptr<armnn::profiling::IBackendProfiling> profilingIface =
295 std::make_unique<armnn::profiling::BackendProfiling>(armnn::profiling::BackendProfiling(
Sadik Armagan3184c902020-03-18 10:57:30 +0000296 options, m_ProfilingService, id));
Colm Donelan1aff3932020-02-05 17:48:59 +0000297
298 // Backends may also provide a profiling context. Ask for it now.
299 auto profilingContext = backend->CreateBackendProfilingContext(options, profilingIface);
300 // Backends that don't support profiling will return a null profiling context.
301 if (profilingContext)
302 {
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100303 // Pass the context onto the profiling service.
304 m_ProfilingService.AddBackendProfilingContext(id, profilingContext);
Colm Donelan1aff3932020-02-05 17:48:59 +0000305 }
David Beck1b61be52018-11-08 09:19:14 +0000306 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000307 catch (const BackendUnavailableException&)
308 {
309 // Ignore backends which are unavailable
310 }
David Beck1b61be52018-11-08 09:19:14 +0000311 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100312
Finn Williams45a73622020-05-15 18:41:05 +0100313 BackendRegistryInstance().SetProfilingService(m_ProfilingService);
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100314 // pass configuration info to the profiling service
315 m_ProfilingService.ConfigureProfilingService(options.m_ProfilingOptions);
Jim Flynn6398a982020-05-27 17:05:21 +0100316 if (options.m_ProfilingOptions.m_EnableProfiling)
317 {
318 // try to wait for the profiling service to initialise
319 m_ProfilingService.WaitForProfilingServiceActivation(3000);
320 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100321
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000322 m_DeviceSpec.AddSupportedBackends(supportedBackends);
alered01a7227ac2020-05-07 14:58:29 +0100323
324 ARMNN_LOG(info) << "Initialization time: " << std::setprecision(2)
325 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
surmeh01bceff2f2018-03-29 16:29:27 +0100326}
327
Kevin Mayd92a6e42021-02-04 10:27:41 +0000328RuntimeImpl::~RuntimeImpl()
surmeh01bceff2f2018-03-29 16:29:27 +0100329{
alered01a7227ac2020-05-07 14:58:29 +0100330 const auto start_time = armnn::GetTimeNow();
surmeh01bceff2f2018-03-29 16:29:27 +0100331 std::vector<int> networkIDs;
surmeh013537c2c2018-05-18 16:31:43 +0100332 try
333 {
334 // Coverity fix: The following code may throw an exception of type std::length_error.
335 std::transform(m_LoadedNetworks.begin(), m_LoadedNetworks.end(),
336 std::back_inserter(networkIDs),
337 [](const auto &pair) { return pair.first; });
338 }
339 catch (const std::exception& e)
340 {
341 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
342 // exception of type std::length_error.
343 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
344 std::cerr << "WARNING: An error has occurred when getting the IDs of the networks to unload: " << e.what()
345 << "\nSome of the loaded networks may not be unloaded" << std::endl;
346 }
347 // We then proceed to unload all the networks which IDs have been appended to the list
348 // up to the point the exception was thrown (if any).
surmeh01bceff2f2018-03-29 16:29:27 +0100349
350 for (auto networkID : networkIDs)
351 {
surmeh013537c2c2018-05-18 16:31:43 +0100352 try
353 {
354 // Coverity fix: UnloadNetwork() may throw an exception of type std::length_error,
355 // boost::log::v2s_mt_posix::odr_violation or boost::log::v2s_mt_posix::system_error
356 UnloadNetwork(networkID);
357 }
358 catch (const std::exception& e)
359 {
360 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
361 // exception of type std::length_error.
362 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
363 std::cerr << "WARNING: An error has occurred when unloading network " << networkID << ": " << e.what()
364 << std::endl;
365 }
telsoa014fcda012018-03-09 14:13:49 +0000366 }
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000367
368 // Clear all dynamic backends.
369 DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
370 m_DeviceSpec.ClearDynamicBackends();
Colm Donelan1aff3932020-02-05 17:48:59 +0000371 m_BackendContexts.clear();
Finn Williams45a73622020-05-15 18:41:05 +0100372
373 BackendRegistryInstance().SetProfilingService(armnn::EmptyOptional());
alered01a7227ac2020-05-07 14:58:29 +0100374 ARMNN_LOG(info) << "Shutdown time: " << std::setprecision(2)
375 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
telsoa014fcda012018-03-09 14:13:49 +0000376}
377
Kevin Mayd92a6e42021-02-04 10:27:41 +0000378LoadedNetwork* RuntimeImpl::GetLoadedNetworkPtr(NetworkId networkId) const
surmeh013537c2c2018-05-18 16:31:43 +0100379{
380 std::lock_guard<std::mutex> lockGuard(m_Mutex);
381 return m_LoadedNetworks.at(networkId).get();
382}
383
Kevin Mayd92a6e42021-02-04 10:27:41 +0000384TensorInfo RuntimeImpl::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000385{
surmeh013537c2c2018-05-18 16:31:43 +0100386 return GetLoadedNetworkPtr(networkId)->GetInputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000387}
388
Kevin Mayd92a6e42021-02-04 10:27:41 +0000389TensorInfo RuntimeImpl::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000390{
surmeh013537c2c2018-05-18 16:31:43 +0100391 return GetLoadedNetworkPtr(networkId)->GetOutputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000392}
393
Derek Lamberti03614f62018-10-02 15:52:46 +0100394
Kevin Mayd92a6e42021-02-04 10:27:41 +0000395Status RuntimeImpl::EnqueueWorkload(NetworkId networkId,
telsoa01c577f2c2018-08-31 09:22:23 +0100396 const InputTensors& inputTensors,
397 const OutputTensors& outputTensors)
telsoa014fcda012018-03-09 14:13:49 +0000398{
surmeh013537c2c2018-05-18 16:31:43 +0100399 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100400
401 if (!loadedNetwork)
402 {
403 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
404 return Status::Failure;
405 }
406 if (loadedNetwork->IsAsyncEnabled())
407 {
408 ARMNN_LOG(error) << "Network " << networkId << " is async enabled.\n";
409 return Status::Failure;
410 }
Narumol Prangnawarat5b4d0d52020-06-23 11:45:56 +0100411 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
412
413 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "EnqueueWorkload");
Derek Lamberti03614f62018-10-02 15:52:46 +0100414
415 static thread_local NetworkId lastId = networkId;
416 if (lastId != networkId)
417 {
418 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
419 {
420 network->FreeWorkingMemory();
421 });
422 }
423 lastId=networkId;
424
surmeh013537c2c2018-05-18 16:31:43 +0100425 return loadedNetwork->EnqueueWorkload(inputTensors, outputTensors);
telsoa014fcda012018-03-09 14:13:49 +0000426}
427
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100428Status RuntimeImpl::Execute(IWorkingMemHandle& iWorkingMemHandle,
429 const InputTensors& inputTensors,
430 const OutputTensors& outputTensors)
431{
432 NetworkId networkId = iWorkingMemHandle.GetNetworkId();
433 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
434
435 if (!loadedNetwork)
436 {
437 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
438 return Status::Failure;
439 }
440 if (!loadedNetwork->IsAsyncEnabled())
441 {
442 ARMNN_LOG(error) << "Network " << networkId << " is not async enabled.\n";
443 return Status::Failure;
444 }
445 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
446
447 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Execute");
448
449 static thread_local NetworkId lastId = networkId;
450 if (lastId != networkId)
451 {
452 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
453 {
454 network->FreeWorkingMemory();
455 });
456 }
457 lastId=networkId;
458
459 return loadedNetwork->Execute(inputTensors, outputTensors, iWorkingMemHandle);
460}
461
462/// Create a new unique WorkingMemHandle object. Create multiple handles if you wish to have
463/// overlapped Execution by calling this function from different threads.
464std::unique_ptr<IWorkingMemHandle> RuntimeImpl::CreateWorkingMemHandle(NetworkId networkId)
465{
466 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
467
468 if (!loadedNetwork)
469 {
470 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
471 return nullptr;
472 }
473 if (!loadedNetwork->IsAsyncEnabled())
474 {
475 ARMNN_LOG(error) << "Network " << networkId << " is not async enabled.\n";
476 return nullptr;
477 }
478 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
479
480 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "CreateWorkingMemHandle");
481
482 static thread_local NetworkId lastId = networkId;
483 if (lastId != networkId)
484 {
485 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
486 {
487 network->FreeWorkingMemory();
488 });
489 }
490 lastId=networkId;
491
492 return loadedNetwork->CreateWorkingMemHandle(networkId);
493}
494
Kevin Mayd92a6e42021-02-04 10:27:41 +0000495void RuntimeImpl::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +0000496{
497 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
498 loadedNetwork->RegisterDebugCallback(func);
499}
500
Kevin Mayd92a6e42021-02-04 10:27:41 +0000501void RuntimeImpl::LoadDynamicBackends(const std::string& overrideBackendPath)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100502{
503 // Get the paths where to load the dynamic backends from
504 std::vector<std::string> backendPaths = DynamicBackendUtils::GetBackendPaths(overrideBackendPath);
505
506 // Get the shared objects to try to load as dynamic backends
507 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
508
509 // Create a list of dynamic backends
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100510 m_DynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
511
512 // Register the dynamic backends in the backend registry
Matteo Martincigh89533902019-08-15 12:08:06 +0100513 BackendIdSet registeredBackendIds = DynamicBackendUtils::RegisterDynamicBackends(m_DynamicBackends);
514
515 // Add the registered dynamic backend ids to the list of supported backends
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000516 m_DeviceSpec.AddSupportedBackends(registeredBackendIds, true);
telsoa014fcda012018-03-09 14:13:49 +0000517}
Matteo Martincighe54aa062019-08-05 14:12:11 +0100518
519} // namespace armnn