blob: f16d18619132c1682f6b14e85b0b094a32364b0a [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
Kevin Mayd92a6e42021-02-04 10:27:41 +000092Status IRuntime::UnloadNetwork(NetworkId networkId)
93{
94 return pRuntimeImpl->UnloadNetwork(networkId);
95}
96
97const IDeviceSpec& IRuntime::GetDeviceSpec() const
98{
99 return pRuntimeImpl->GetDeviceSpec();
100}
101
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100102std::unique_ptr<IWorkingMemHandle> IRuntime::CreateWorkingMemHandle(NetworkId networkId)
103{
104 return pRuntimeImpl->CreateWorkingMemHandle(networkId);
105}
106
Kevin Mayd92a6e42021-02-04 10:27:41 +0000107const std::shared_ptr<IProfiler> IRuntime::GetProfiler(NetworkId networkId) const
108{
109 return pRuntimeImpl->GetProfiler(networkId);
110}
111
112void IRuntime::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
113{
114 return pRuntimeImpl->RegisterDebugCallback(networkId, func);
115}
116
117int RuntimeImpl::GenerateNetworkId()
telsoa014fcda012018-03-09 14:13:49 +0000118{
119 return m_NetworkIdCounter++;
120}
121
Kevin Mayd92a6e42021-02-04 10:27:41 +0000122Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr inNetwork)
telsoa014fcda012018-03-09 14:13:49 +0000123{
telsoa01c577f2c2018-08-31 09:22:23 +0100124 std::string ignoredErrorMessage;
125 return LoadNetwork(networkIdOut, std::move(inNetwork), ignoredErrorMessage);
126}
127
Kevin Mayd92a6e42021-02-04 10:27:41 +0000128Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
129 IOptimizedNetworkPtr inNetwork,
130 std::string& errorMessage)
David Monahan4f1e8e42019-09-04 09:22:10 +0100131{
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100132 INetworkProperties networkProperties(false, MemorySource::Undefined, MemorySource::Undefined);
David Monahan4f1e8e42019-09-04 09:22:10 +0100133 return LoadNetwork(networkIdOut, std::move(inNetwork), errorMessage, networkProperties);
134}
135
Kevin Mayd92a6e42021-02-04 10:27:41 +0000136Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
137 IOptimizedNetworkPtr inNetwork,
138 std::string& errorMessage,
139 const INetworkProperties& networkProperties)
telsoa01c577f2c2018-08-31 09:22:23 +0100140{
telsoa014fcda012018-03-09 14:13:49 +0000141 IOptimizedNetwork* rawNetwork = inNetwork.release();
David Beck1b61be52018-11-08 09:19:14 +0000142
143 networkIdOut = GenerateNetworkId();
144
145 for (auto&& context : m_BackendContexts)
146 {
147 context.second->BeforeLoadNetwork(networkIdOut);
148 }
149
telsoa014fcda012018-03-09 14:13:49 +0000150 unique_ptr<LoadedNetwork> loadedNetwork = LoadedNetwork::MakeLoadedNetwork(
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000151 std::unique_ptr<IOptimizedNetwork>(rawNetwork),
David Monahan4f1e8e42019-09-04 09:22:10 +0100152 errorMessage,
Sadik Armagan3184c902020-03-18 10:57:30 +0000153 networkProperties,
Finn Williamsf364d532021-06-09 17:07:33 +0100154 m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000155
156 if (!loadedNetwork)
157 {
158 return Status::Failure;
159 }
160
telsoa01c577f2c2018-08-31 09:22:23 +0100161 {
162 std::lock_guard<std::mutex> lockGuard(m_Mutex);
163
164 // Stores the network
165 m_LoadedNetworks[networkIdOut] = std::move(loadedNetwork);
166 }
telsoa014fcda012018-03-09 14:13:49 +0000167
David Beck1b61be52018-11-08 09:19:14 +0000168 for (auto&& context : m_BackendContexts)
169 {
170 context.second->AfterLoadNetwork(networkIdOut);
171 }
172
Sadik Armagan3184c902020-03-18 10:57:30 +0000173 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000174 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000175 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_LOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000176 }
177
telsoa014fcda012018-03-09 14:13:49 +0000178 return Status::Success;
telsoa014fcda012018-03-09 14:13:49 +0000179}
180
Kevin Mayd92a6e42021-02-04 10:27:41 +0000181Status RuntimeImpl::UnloadNetwork(NetworkId networkId)
telsoa014fcda012018-03-09 14:13:49 +0000182{
David Beck1b61be52018-11-08 09:19:14 +0000183 bool unloadOk = true;
184 for (auto&& context : m_BackendContexts)
David Beck9efb57d2018-11-05 13:40:33 +0000185 {
David Beck1b61be52018-11-08 09:19:14 +0000186 unloadOk &= context.second->BeforeUnloadNetwork(networkId);
David Beck9efb57d2018-11-05 13:40:33 +0000187 }
David Beck1b61be52018-11-08 09:19:14 +0000188
189 if (!unloadOk)
190 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000191 ARMNN_LOG(warning) << "RuntimeImpl::UnloadNetwork(): failed to unload "
Derek Lamberti08446972019-11-26 16:38:31 +0000192 "network with ID:" << networkId << " because BeforeUnloadNetwork failed";
David Beck1b61be52018-11-08 09:19:14 +0000193 return Status::Failure;
194 }
David Beck9efb57d2018-11-05 13:40:33 +0000195
Jim Flynnf7713212020-07-14 09:50:59 +0100196 std::unique_ptr<profiling::TimelineUtilityMethods> timelineUtils =
197 profiling::TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000198 {
telsoa01c577f2c2018-08-31 09:22:23 +0100199 std::lock_guard<std::mutex> lockGuard(m_Mutex);
200
Jim Flynnf7713212020-07-14 09:50:59 +0100201 // If timeline recording is on mark the Network end of life
202 if (timelineUtils)
203 {
204 auto search = m_LoadedNetworks.find(networkId);
205 if (search != m_LoadedNetworks.end())
206 {
207 profiling::ProfilingGuid networkGuid = search->second->GetNetworkGuid();
208 timelineUtils->RecordEvent(networkGuid,
209 profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
210 }
211 }
telsoa01c577f2c2018-08-31 09:22:23 +0100212 if (m_LoadedNetworks.erase(networkId) == 0)
213 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000214 ARMNN_LOG(warning) << "WARNING: RuntimeImpl::UnloadNetwork(): " << networkId << " not found!";
telsoa01c577f2c2018-08-31 09:22:23 +0100215 return Status::Failure;
216 }
Sadik Armagan3184c902020-03-18 10:57:30 +0000217
218 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000219 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000220 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_UNLOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000221 }
David Beck1b61be52018-11-08 09:19:14 +0000222 }
David Beck9efb57d2018-11-05 13:40:33 +0000223
David Beck1b61be52018-11-08 09:19:14 +0000224 for (auto&& context : m_BackendContexts)
225 {
226 context.second->AfterUnloadNetwork(networkId);
telsoa01c577f2c2018-08-31 09:22:23 +0100227 }
228
Kevin Mayd92a6e42021-02-04 10:27:41 +0000229 ARMNN_LOG(debug) << "RuntimeImpl::UnloadNetwork(): Unloaded network with ID: " << networkId;
telsoa014fcda012018-03-09 14:13:49 +0000230 return Status::Success;
231}
232
Kevin Mayd92a6e42021-02-04 10:27:41 +0000233const std::shared_ptr<IProfiler> RuntimeImpl::GetProfiler(NetworkId networkId) const
telsoa01c577f2c2018-08-31 09:22:23 +0100234{
235 auto it = m_LoadedNetworks.find(networkId);
236 if (it != m_LoadedNetworks.end())
237 {
238 auto& loadedNetwork = it->second;
239 return loadedNetwork->GetProfiler();
240 }
241
242 return nullptr;
243}
244
Kevin Mayd92a6e42021-02-04 10:27:41 +0000245void RuntimeImpl::ReportStructure() // armnn::profiling::IProfilingService& profilingService as param
Keith Davis33ed2212020-03-30 10:43:41 +0100246{
247 // No-op for the time being, but this may be useful in future to have the profilingService available
248 // if (profilingService.IsProfilingEnabled()){}
249
250 LoadedNetworks::iterator it = m_LoadedNetworks.begin();
251 while (it != m_LoadedNetworks.end())
252 {
253 auto& loadedNetwork = it->second;
254 loadedNetwork->SendNetworkStructure();
255 // Increment the Iterator to point to next entry
256 it++;
257 }
258}
259
Kevin Mayd92a6e42021-02-04 10:27:41 +0000260RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options)
Keith Davis33ed2212020-03-30 10:43:41 +0100261 : m_NetworkIdCounter(0),
262 m_ProfilingService(*this)
telsoa014fcda012018-03-09 14:13:49 +0000263{
alered01a7227ac2020-05-07 14:58:29 +0100264 const auto start_time = armnn::GetTimeNow();
Derek Lamberti08446972019-11-26 16:38:31 +0000265 ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION << "\n";
David Beck1b61be52018-11-08 09:19:14 +0000266
Keith Davis33ed2212020-03-30 10:43:41 +0100267 if ( options.m_ProfilingOptions.m_TimelineEnabled && !options.m_ProfilingOptions.m_EnableProfiling )
268 {
269 throw RuntimeException("It is not possible to enable timeline reporting without profiling being enabled");
270 }
271
Matteo Martincighe54aa062019-08-05 14:12:11 +0100272 // Load any available/compatible dynamic backend before the runtime
273 // goes through the backend registry
274 LoadDynamicBackends(options.m_DynamicBackendsPath);
275
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000276 BackendIdSet supportedBackends;
David Beck1b61be52018-11-08 09:19:14 +0000277 for (const auto& id : BackendRegistryInstance().GetBackendIds())
278 {
279 // Store backend contexts for the supported ones
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000280 try {
David Beck1b61be52018-11-08 09:19:14 +0000281 auto factoryFun = BackendRegistryInstance().GetFactory(id);
282 auto backend = factoryFun();
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100283 ARMNN_ASSERT(backend.get() != nullptr);
David Beck1b61be52018-11-08 09:19:14 +0000284
285 auto context = backend->CreateBackendContext(options);
286
287 // backends are allowed to return nullptrs if they
288 // don't wish to create a backend specific context
289 if (context)
290 {
291 m_BackendContexts.emplace(std::make_pair(id, std::move(context)));
292 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000293 supportedBackends.emplace(id);
Colm Donelan1aff3932020-02-05 17:48:59 +0000294
295 unique_ptr<armnn::profiling::IBackendProfiling> profilingIface =
296 std::make_unique<armnn::profiling::BackendProfiling>(armnn::profiling::BackendProfiling(
Sadik Armagan3184c902020-03-18 10:57:30 +0000297 options, m_ProfilingService, id));
Colm Donelan1aff3932020-02-05 17:48:59 +0000298
299 // Backends may also provide a profiling context. Ask for it now.
300 auto profilingContext = backend->CreateBackendProfilingContext(options, profilingIface);
301 // Backends that don't support profiling will return a null profiling context.
302 if (profilingContext)
303 {
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100304 // Pass the context onto the profiling service.
305 m_ProfilingService.AddBackendProfilingContext(id, profilingContext);
Colm Donelan1aff3932020-02-05 17:48:59 +0000306 }
David Beck1b61be52018-11-08 09:19:14 +0000307 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000308 catch (const BackendUnavailableException&)
309 {
310 // Ignore backends which are unavailable
311 }
David Beck1b61be52018-11-08 09:19:14 +0000312 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100313
Finn Williams45a73622020-05-15 18:41:05 +0100314 BackendRegistryInstance().SetProfilingService(m_ProfilingService);
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100315 // pass configuration info to the profiling service
316 m_ProfilingService.ConfigureProfilingService(options.m_ProfilingOptions);
Jim Flynn6398a982020-05-27 17:05:21 +0100317 if (options.m_ProfilingOptions.m_EnableProfiling)
318 {
319 // try to wait for the profiling service to initialise
320 m_ProfilingService.WaitForProfilingServiceActivation(3000);
321 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100322
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000323 m_DeviceSpec.AddSupportedBackends(supportedBackends);
alered01a7227ac2020-05-07 14:58:29 +0100324
325 ARMNN_LOG(info) << "Initialization time: " << std::setprecision(2)
326 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
surmeh01bceff2f2018-03-29 16:29:27 +0100327}
328
Kevin Mayd92a6e42021-02-04 10:27:41 +0000329RuntimeImpl::~RuntimeImpl()
surmeh01bceff2f2018-03-29 16:29:27 +0100330{
alered01a7227ac2020-05-07 14:58:29 +0100331 const auto start_time = armnn::GetTimeNow();
surmeh01bceff2f2018-03-29 16:29:27 +0100332 std::vector<int> networkIDs;
surmeh013537c2c2018-05-18 16:31:43 +0100333 try
334 {
335 // Coverity fix: The following code may throw an exception of type std::length_error.
336 std::transform(m_LoadedNetworks.begin(), m_LoadedNetworks.end(),
337 std::back_inserter(networkIDs),
338 [](const auto &pair) { return pair.first; });
339 }
340 catch (const std::exception& e)
341 {
342 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
343 // exception of type std::length_error.
344 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
345 std::cerr << "WARNING: An error has occurred when getting the IDs of the networks to unload: " << e.what()
346 << "\nSome of the loaded networks may not be unloaded" << std::endl;
347 }
348 // We then proceed to unload all the networks which IDs have been appended to the list
349 // up to the point the exception was thrown (if any).
surmeh01bceff2f2018-03-29 16:29:27 +0100350
351 for (auto networkID : networkIDs)
352 {
surmeh013537c2c2018-05-18 16:31:43 +0100353 try
354 {
355 // Coverity fix: UnloadNetwork() may throw an exception of type std::length_error,
356 // boost::log::v2s_mt_posix::odr_violation or boost::log::v2s_mt_posix::system_error
357 UnloadNetwork(networkID);
358 }
359 catch (const std::exception& e)
360 {
361 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
362 // exception of type std::length_error.
363 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
364 std::cerr << "WARNING: An error has occurred when unloading network " << networkID << ": " << e.what()
365 << std::endl;
366 }
telsoa014fcda012018-03-09 14:13:49 +0000367 }
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000368
369 // Clear all dynamic backends.
370 DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
371 m_DeviceSpec.ClearDynamicBackends();
Colm Donelan1aff3932020-02-05 17:48:59 +0000372 m_BackendContexts.clear();
Finn Williams45a73622020-05-15 18:41:05 +0100373
374 BackendRegistryInstance().SetProfilingService(armnn::EmptyOptional());
alered01a7227ac2020-05-07 14:58:29 +0100375 ARMNN_LOG(info) << "Shutdown time: " << std::setprecision(2)
376 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
telsoa014fcda012018-03-09 14:13:49 +0000377}
378
Kevin Mayd92a6e42021-02-04 10:27:41 +0000379LoadedNetwork* RuntimeImpl::GetLoadedNetworkPtr(NetworkId networkId) const
surmeh013537c2c2018-05-18 16:31:43 +0100380{
381 std::lock_guard<std::mutex> lockGuard(m_Mutex);
382 return m_LoadedNetworks.at(networkId).get();
383}
384
Kevin Mayd92a6e42021-02-04 10:27:41 +0000385TensorInfo RuntimeImpl::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000386{
surmeh013537c2c2018-05-18 16:31:43 +0100387 return GetLoadedNetworkPtr(networkId)->GetInputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000388}
389
Kevin Mayd92a6e42021-02-04 10:27:41 +0000390TensorInfo RuntimeImpl::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000391{
surmeh013537c2c2018-05-18 16:31:43 +0100392 return GetLoadedNetworkPtr(networkId)->GetOutputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000393}
394
Derek Lamberti03614f62018-10-02 15:52:46 +0100395
Kevin Mayd92a6e42021-02-04 10:27:41 +0000396Status RuntimeImpl::EnqueueWorkload(NetworkId networkId,
telsoa01c577f2c2018-08-31 09:22:23 +0100397 const InputTensors& inputTensors,
398 const OutputTensors& outputTensors)
telsoa014fcda012018-03-09 14:13:49 +0000399{
surmeh013537c2c2018-05-18 16:31:43 +0100400 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100401
402 if (!loadedNetwork)
403 {
404 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
405 return Status::Failure;
406 }
407 if (loadedNetwork->IsAsyncEnabled())
408 {
409 ARMNN_LOG(error) << "Network " << networkId << " is async enabled.\n";
410 return Status::Failure;
411 }
Narumol Prangnawarat5b4d0d52020-06-23 11:45:56 +0100412 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
413
414 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "EnqueueWorkload");
Derek Lamberti03614f62018-10-02 15:52:46 +0100415
416 static thread_local NetworkId lastId = networkId;
417 if (lastId != networkId)
418 {
419 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
420 {
421 network->FreeWorkingMemory();
422 });
423 }
424 lastId=networkId;
425
surmeh013537c2c2018-05-18 16:31:43 +0100426 return loadedNetwork->EnqueueWorkload(inputTensors, outputTensors);
telsoa014fcda012018-03-09 14:13:49 +0000427}
428
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100429Status RuntimeImpl::Execute(IWorkingMemHandle& iWorkingMemHandle,
430 const InputTensors& inputTensors,
431 const OutputTensors& outputTensors)
432{
433 NetworkId networkId = iWorkingMemHandle.GetNetworkId();
434 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
435
436 if (!loadedNetwork)
437 {
438 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
439 return Status::Failure;
440 }
441 if (!loadedNetwork->IsAsyncEnabled())
442 {
Keith Davise813d672021-04-22 10:10:34 +0100443 ARMNN_LOG(error) << "Attempting execute " << networkId << " when it is not async enabled.\n";
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100444 return Status::Failure;
445 }
446 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
447
448 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Execute");
449
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100450 return loadedNetwork->Execute(inputTensors, outputTensors, iWorkingMemHandle);
451}
452
453/// Create a new unique WorkingMemHandle object. Create multiple handles if you wish to have
454/// overlapped Execution by calling this function from different threads.
455std::unique_ptr<IWorkingMemHandle> RuntimeImpl::CreateWorkingMemHandle(NetworkId networkId)
456{
457 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
458
459 if (!loadedNetwork)
460 {
461 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
462 return nullptr;
463 }
464 if (!loadedNetwork->IsAsyncEnabled())
465 {
466 ARMNN_LOG(error) << "Network " << networkId << " is not async enabled.\n";
467 return nullptr;
468 }
469 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
470
471 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "CreateWorkingMemHandle");
472
473 static thread_local NetworkId lastId = networkId;
474 if (lastId != networkId)
475 {
476 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
477 {
478 network->FreeWorkingMemory();
479 });
480 }
481 lastId=networkId;
482
483 return loadedNetwork->CreateWorkingMemHandle(networkId);
484}
485
Kevin Mayd92a6e42021-02-04 10:27:41 +0000486void RuntimeImpl::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +0000487{
488 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
489 loadedNetwork->RegisterDebugCallback(func);
490}
491
Kevin Mayd92a6e42021-02-04 10:27:41 +0000492void RuntimeImpl::LoadDynamicBackends(const std::string& overrideBackendPath)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100493{
494 // Get the paths where to load the dynamic backends from
495 std::vector<std::string> backendPaths = DynamicBackendUtils::GetBackendPaths(overrideBackendPath);
496
497 // Get the shared objects to try to load as dynamic backends
498 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
499
500 // Create a list of dynamic backends
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100501 m_DynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
502
503 // Register the dynamic backends in the backend registry
Matteo Martincigh89533902019-08-15 12:08:06 +0100504 BackendIdSet registeredBackendIds = DynamicBackendUtils::RegisterDynamicBackends(m_DynamicBackends);
505
506 // Add the registered dynamic backend ids to the list of supported backends
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000507 m_DeviceSpec.AddSupportedBackends(registeredBackendIds, true);
telsoa014fcda012018-03-09 14:13:49 +0000508}
Matteo Martincighe54aa062019-08-05 14:12:11 +0100509
510} // namespace armnn