blob: 57aaabd277855f2a35f045485f46506f9e2f1492 [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
Mike Kelly386ff1a2021-03-29 15:04:50 +010067std::unique_ptr<IAsyncNetwork> IRuntime::CreateAsyncNetwork(NetworkId& networkIdOut,
68 IOptimizedNetworkPtr network,
69 std::string& errorMessage,
70 const INetworkProperties& networkProperties)
71{
72 return pRuntimeImpl->CreateAsyncNetwork(networkIdOut, std::move(network), errorMessage, networkProperties);
73}
74
Kevin Mayd92a6e42021-02-04 10:27:41 +000075TensorInfo IRuntime::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
76{
77 return pRuntimeImpl->GetInputTensorInfo(networkId, layerId);
78}
79
80TensorInfo IRuntime::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
81{
82 return pRuntimeImpl->GetOutputTensorInfo(networkId, layerId);
83}
84
85Status IRuntime::EnqueueWorkload(NetworkId networkId,
86 const InputTensors& inputTensors,
87 const OutputTensors& outputTensors)
88{
89 return pRuntimeImpl->EnqueueWorkload(networkId, inputTensors, outputTensors);
90}
91
92Status IRuntime::UnloadNetwork(NetworkId networkId)
93{
94 return pRuntimeImpl->UnloadNetwork(networkId);
95}
96
97const IDeviceSpec& IRuntime::GetDeviceSpec() const
98{
99 return pRuntimeImpl->GetDeviceSpec();
100}
101
102const std::shared_ptr<IProfiler> IRuntime::GetProfiler(NetworkId networkId) const
103{
104 return pRuntimeImpl->GetProfiler(networkId);
105}
106
107void IRuntime::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
108{
109 return pRuntimeImpl->RegisterDebugCallback(networkId, func);
110}
111
112int RuntimeImpl::GenerateNetworkId()
telsoa014fcda012018-03-09 14:13:49 +0000113{
114 return m_NetworkIdCounter++;
115}
116
Kevin Mayd92a6e42021-02-04 10:27:41 +0000117Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr inNetwork)
telsoa014fcda012018-03-09 14:13:49 +0000118{
telsoa01c577f2c2018-08-31 09:22:23 +0100119 std::string ignoredErrorMessage;
120 return LoadNetwork(networkIdOut, std::move(inNetwork), ignoredErrorMessage);
121}
122
Kevin Mayd92a6e42021-02-04 10:27:41 +0000123Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
124 IOptimizedNetworkPtr inNetwork,
125 std::string& errorMessage)
David Monahan4f1e8e42019-09-04 09:22:10 +0100126{
127 INetworkProperties networkProperties;
128 return LoadNetwork(networkIdOut, std::move(inNetwork), errorMessage, networkProperties);
129}
130
Kevin Mayd92a6e42021-02-04 10:27:41 +0000131Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
132 IOptimizedNetworkPtr inNetwork,
133 std::string& errorMessage,
134 const INetworkProperties& networkProperties)
telsoa01c577f2c2018-08-31 09:22:23 +0100135{
telsoa014fcda012018-03-09 14:13:49 +0000136 IOptimizedNetwork* rawNetwork = inNetwork.release();
David Beck1b61be52018-11-08 09:19:14 +0000137
138 networkIdOut = GenerateNetworkId();
139
140 for (auto&& context : m_BackendContexts)
141 {
142 context.second->BeforeLoadNetwork(networkIdOut);
143 }
144
telsoa014fcda012018-03-09 14:13:49 +0000145 unique_ptr<LoadedNetwork> loadedNetwork = LoadedNetwork::MakeLoadedNetwork(
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000146 std::unique_ptr<IOptimizedNetwork>(rawNetwork),
David Monahan4f1e8e42019-09-04 09:22:10 +0100147 errorMessage,
Sadik Armagan3184c902020-03-18 10:57:30 +0000148 networkProperties,
149 m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000150
151 if (!loadedNetwork)
152 {
153 return Status::Failure;
154 }
155
telsoa01c577f2c2018-08-31 09:22:23 +0100156 {
157 std::lock_guard<std::mutex> lockGuard(m_Mutex);
158
159 // Stores the network
160 m_LoadedNetworks[networkIdOut] = std::move(loadedNetwork);
161 }
telsoa014fcda012018-03-09 14:13:49 +0000162
David Beck1b61be52018-11-08 09:19:14 +0000163 for (auto&& context : m_BackendContexts)
164 {
165 context.second->AfterLoadNetwork(networkIdOut);
166 }
167
Sadik Armagan3184c902020-03-18 10:57:30 +0000168 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000169 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000170 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_LOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000171 }
172
telsoa014fcda012018-03-09 14:13:49 +0000173 return Status::Success;
telsoa014fcda012018-03-09 14:13:49 +0000174}
175
Mike Kelly386ff1a2021-03-29 15:04:50 +0100176std::unique_ptr<IAsyncNetwork> RuntimeImpl::CreateAsyncNetwork(NetworkId& networkIdOut,
177 IOptimizedNetworkPtr network,
178 std::string&,
179 const INetworkProperties& networkProperties)
180{
181 IOptimizedNetwork* rawNetwork = network.release();
182
183 networkIdOut = GenerateNetworkId();
184
185 for (auto&& context : m_BackendContexts)
186 {
187 context.second->BeforeLoadNetwork(networkIdOut);
188 }
189
Sadik Armagana0042512021-03-30 11:05:36 +0100190 unique_ptr<IAsyncNetwork> asyncNetwork = std::make_unique<IAsyncNetwork>(
Mike Kelly386ff1a2021-03-29 15:04:50 +0100191 std::unique_ptr<IOptimizedNetwork>(rawNetwork),
192 networkProperties,
193 m_ProfilingService);
194
195 if (!asyncNetwork)
196 {
197 return nullptr;
198 }
199
200 for (auto&& context : m_BackendContexts)
201 {
202 context.second->AfterLoadNetwork(networkIdOut);
203 }
204
205 if (m_ProfilingService.IsProfilingEnabled())
206 {
207 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_LOADS);
208 }
209
210 return asyncNetwork;
211}
212
Kevin Mayd92a6e42021-02-04 10:27:41 +0000213Status RuntimeImpl::UnloadNetwork(NetworkId networkId)
telsoa014fcda012018-03-09 14:13:49 +0000214{
David Beck1b61be52018-11-08 09:19:14 +0000215 bool unloadOk = true;
216 for (auto&& context : m_BackendContexts)
David Beck9efb57d2018-11-05 13:40:33 +0000217 {
David Beck1b61be52018-11-08 09:19:14 +0000218 unloadOk &= context.second->BeforeUnloadNetwork(networkId);
David Beck9efb57d2018-11-05 13:40:33 +0000219 }
David Beck1b61be52018-11-08 09:19:14 +0000220
221 if (!unloadOk)
222 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000223 ARMNN_LOG(warning) << "RuntimeImpl::UnloadNetwork(): failed to unload "
Derek Lamberti08446972019-11-26 16:38:31 +0000224 "network with ID:" << networkId << " because BeforeUnloadNetwork failed";
David Beck1b61be52018-11-08 09:19:14 +0000225 return Status::Failure;
226 }
David Beck9efb57d2018-11-05 13:40:33 +0000227
Jim Flynnf7713212020-07-14 09:50:59 +0100228 std::unique_ptr<profiling::TimelineUtilityMethods> timelineUtils =
229 profiling::TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000230 {
telsoa01c577f2c2018-08-31 09:22:23 +0100231 std::lock_guard<std::mutex> lockGuard(m_Mutex);
232
Jim Flynnf7713212020-07-14 09:50:59 +0100233 // If timeline recording is on mark the Network end of life
234 if (timelineUtils)
235 {
236 auto search = m_LoadedNetworks.find(networkId);
237 if (search != m_LoadedNetworks.end())
238 {
239 profiling::ProfilingGuid networkGuid = search->second->GetNetworkGuid();
240 timelineUtils->RecordEvent(networkGuid,
241 profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
242 }
243 }
telsoa01c577f2c2018-08-31 09:22:23 +0100244 if (m_LoadedNetworks.erase(networkId) == 0)
245 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000246 ARMNN_LOG(warning) << "WARNING: RuntimeImpl::UnloadNetwork(): " << networkId << " not found!";
telsoa01c577f2c2018-08-31 09:22:23 +0100247 return Status::Failure;
248 }
Sadik Armagan3184c902020-03-18 10:57:30 +0000249
250 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000251 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000252 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_UNLOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000253 }
David Beck1b61be52018-11-08 09:19:14 +0000254 }
David Beck9efb57d2018-11-05 13:40:33 +0000255
David Beck1b61be52018-11-08 09:19:14 +0000256 for (auto&& context : m_BackendContexts)
257 {
258 context.second->AfterUnloadNetwork(networkId);
telsoa01c577f2c2018-08-31 09:22:23 +0100259 }
260
Kevin Mayd92a6e42021-02-04 10:27:41 +0000261 ARMNN_LOG(debug) << "RuntimeImpl::UnloadNetwork(): Unloaded network with ID: " << networkId;
telsoa014fcda012018-03-09 14:13:49 +0000262 return Status::Success;
263}
264
Kevin Mayd92a6e42021-02-04 10:27:41 +0000265const std::shared_ptr<IProfiler> RuntimeImpl::GetProfiler(NetworkId networkId) const
telsoa01c577f2c2018-08-31 09:22:23 +0100266{
267 auto it = m_LoadedNetworks.find(networkId);
268 if (it != m_LoadedNetworks.end())
269 {
270 auto& loadedNetwork = it->second;
271 return loadedNetwork->GetProfiler();
272 }
273
274 return nullptr;
275}
276
Kevin Mayd92a6e42021-02-04 10:27:41 +0000277void RuntimeImpl::ReportStructure() // armnn::profiling::IProfilingService& profilingService as param
Keith Davis33ed2212020-03-30 10:43:41 +0100278{
279 // No-op for the time being, but this may be useful in future to have the profilingService available
280 // if (profilingService.IsProfilingEnabled()){}
281
282 LoadedNetworks::iterator it = m_LoadedNetworks.begin();
283 while (it != m_LoadedNetworks.end())
284 {
285 auto& loadedNetwork = it->second;
286 loadedNetwork->SendNetworkStructure();
287 // Increment the Iterator to point to next entry
288 it++;
289 }
290}
291
Kevin Mayd92a6e42021-02-04 10:27:41 +0000292RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options)
Keith Davis33ed2212020-03-30 10:43:41 +0100293 : m_NetworkIdCounter(0),
294 m_ProfilingService(*this)
telsoa014fcda012018-03-09 14:13:49 +0000295{
alered01a7227ac2020-05-07 14:58:29 +0100296 const auto start_time = armnn::GetTimeNow();
Derek Lamberti08446972019-11-26 16:38:31 +0000297 ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION << "\n";
David Beck1b61be52018-11-08 09:19:14 +0000298
Keith Davis33ed2212020-03-30 10:43:41 +0100299 if ( options.m_ProfilingOptions.m_TimelineEnabled && !options.m_ProfilingOptions.m_EnableProfiling )
300 {
301 throw RuntimeException("It is not possible to enable timeline reporting without profiling being enabled");
302 }
303
Matteo Martincighe54aa062019-08-05 14:12:11 +0100304 // Load any available/compatible dynamic backend before the runtime
305 // goes through the backend registry
306 LoadDynamicBackends(options.m_DynamicBackendsPath);
307
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000308 BackendIdSet supportedBackends;
David Beck1b61be52018-11-08 09:19:14 +0000309 for (const auto& id : BackendRegistryInstance().GetBackendIds())
310 {
311 // Store backend contexts for the supported ones
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000312 try {
David Beck1b61be52018-11-08 09:19:14 +0000313 auto factoryFun = BackendRegistryInstance().GetFactory(id);
314 auto backend = factoryFun();
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100315 ARMNN_ASSERT(backend.get() != nullptr);
David Beck1b61be52018-11-08 09:19:14 +0000316
317 auto context = backend->CreateBackendContext(options);
318
319 // backends are allowed to return nullptrs if they
320 // don't wish to create a backend specific context
321 if (context)
322 {
323 m_BackendContexts.emplace(std::make_pair(id, std::move(context)));
324 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000325 supportedBackends.emplace(id);
Colm Donelan1aff3932020-02-05 17:48:59 +0000326
327 unique_ptr<armnn::profiling::IBackendProfiling> profilingIface =
328 std::make_unique<armnn::profiling::BackendProfiling>(armnn::profiling::BackendProfiling(
Sadik Armagan3184c902020-03-18 10:57:30 +0000329 options, m_ProfilingService, id));
Colm Donelan1aff3932020-02-05 17:48:59 +0000330
331 // Backends may also provide a profiling context. Ask for it now.
332 auto profilingContext = backend->CreateBackendProfilingContext(options, profilingIface);
333 // Backends that don't support profiling will return a null profiling context.
334 if (profilingContext)
335 {
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100336 // Pass the context onto the profiling service.
337 m_ProfilingService.AddBackendProfilingContext(id, profilingContext);
Colm Donelan1aff3932020-02-05 17:48:59 +0000338 }
David Beck1b61be52018-11-08 09:19:14 +0000339 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000340 catch (const BackendUnavailableException&)
341 {
342 // Ignore backends which are unavailable
343 }
David Beck1b61be52018-11-08 09:19:14 +0000344 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100345
Finn Williams45a73622020-05-15 18:41:05 +0100346 BackendRegistryInstance().SetProfilingService(m_ProfilingService);
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100347 // pass configuration info to the profiling service
348 m_ProfilingService.ConfigureProfilingService(options.m_ProfilingOptions);
Jim Flynn6398a982020-05-27 17:05:21 +0100349 if (options.m_ProfilingOptions.m_EnableProfiling)
350 {
351 // try to wait for the profiling service to initialise
352 m_ProfilingService.WaitForProfilingServiceActivation(3000);
353 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100354
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000355 m_DeviceSpec.AddSupportedBackends(supportedBackends);
alered01a7227ac2020-05-07 14:58:29 +0100356
357 ARMNN_LOG(info) << "Initialization time: " << std::setprecision(2)
358 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
surmeh01bceff2f2018-03-29 16:29:27 +0100359}
360
Kevin Mayd92a6e42021-02-04 10:27:41 +0000361RuntimeImpl::~RuntimeImpl()
surmeh01bceff2f2018-03-29 16:29:27 +0100362{
alered01a7227ac2020-05-07 14:58:29 +0100363 const auto start_time = armnn::GetTimeNow();
surmeh01bceff2f2018-03-29 16:29:27 +0100364 std::vector<int> networkIDs;
surmeh013537c2c2018-05-18 16:31:43 +0100365 try
366 {
367 // Coverity fix: The following code may throw an exception of type std::length_error.
368 std::transform(m_LoadedNetworks.begin(), m_LoadedNetworks.end(),
369 std::back_inserter(networkIDs),
370 [](const auto &pair) { return pair.first; });
371 }
372 catch (const std::exception& e)
373 {
374 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
375 // exception of type std::length_error.
376 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
377 std::cerr << "WARNING: An error has occurred when getting the IDs of the networks to unload: " << e.what()
378 << "\nSome of the loaded networks may not be unloaded" << std::endl;
379 }
380 // We then proceed to unload all the networks which IDs have been appended to the list
381 // up to the point the exception was thrown (if any).
surmeh01bceff2f2018-03-29 16:29:27 +0100382
383 for (auto networkID : networkIDs)
384 {
surmeh013537c2c2018-05-18 16:31:43 +0100385 try
386 {
387 // Coverity fix: UnloadNetwork() may throw an exception of type std::length_error,
388 // boost::log::v2s_mt_posix::odr_violation or boost::log::v2s_mt_posix::system_error
389 UnloadNetwork(networkID);
390 }
391 catch (const std::exception& e)
392 {
393 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
394 // exception of type std::length_error.
395 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
396 std::cerr << "WARNING: An error has occurred when unloading network " << networkID << ": " << e.what()
397 << std::endl;
398 }
telsoa014fcda012018-03-09 14:13:49 +0000399 }
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000400
401 // Clear all dynamic backends.
402 DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
403 m_DeviceSpec.ClearDynamicBackends();
Colm Donelan1aff3932020-02-05 17:48:59 +0000404 m_BackendContexts.clear();
Finn Williams45a73622020-05-15 18:41:05 +0100405
406 BackendRegistryInstance().SetProfilingService(armnn::EmptyOptional());
alered01a7227ac2020-05-07 14:58:29 +0100407 ARMNN_LOG(info) << "Shutdown time: " << std::setprecision(2)
408 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
telsoa014fcda012018-03-09 14:13:49 +0000409}
410
Kevin Mayd92a6e42021-02-04 10:27:41 +0000411LoadedNetwork* RuntimeImpl::GetLoadedNetworkPtr(NetworkId networkId) const
surmeh013537c2c2018-05-18 16:31:43 +0100412{
413 std::lock_guard<std::mutex> lockGuard(m_Mutex);
414 return m_LoadedNetworks.at(networkId).get();
415}
416
Kevin Mayd92a6e42021-02-04 10:27:41 +0000417TensorInfo RuntimeImpl::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000418{
surmeh013537c2c2018-05-18 16:31:43 +0100419 return GetLoadedNetworkPtr(networkId)->GetInputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000420}
421
Kevin Mayd92a6e42021-02-04 10:27:41 +0000422TensorInfo RuntimeImpl::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000423{
surmeh013537c2c2018-05-18 16:31:43 +0100424 return GetLoadedNetworkPtr(networkId)->GetOutputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000425}
426
Derek Lamberti03614f62018-10-02 15:52:46 +0100427
Kevin Mayd92a6e42021-02-04 10:27:41 +0000428Status RuntimeImpl::EnqueueWorkload(NetworkId networkId,
telsoa01c577f2c2018-08-31 09:22:23 +0100429 const InputTensors& inputTensors,
430 const OutputTensors& outputTensors)
telsoa014fcda012018-03-09 14:13:49 +0000431{
surmeh013537c2c2018-05-18 16:31:43 +0100432 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
Narumol Prangnawarat5b4d0d52020-06-23 11:45:56 +0100433 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
434
435 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "EnqueueWorkload");
Derek Lamberti03614f62018-10-02 15:52:46 +0100436
437 static thread_local NetworkId lastId = networkId;
438 if (lastId != networkId)
439 {
440 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
441 {
442 network->FreeWorkingMemory();
443 });
444 }
445 lastId=networkId;
446
surmeh013537c2c2018-05-18 16:31:43 +0100447 return loadedNetwork->EnqueueWorkload(inputTensors, outputTensors);
telsoa014fcda012018-03-09 14:13:49 +0000448}
449
Kevin Mayd92a6e42021-02-04 10:27:41 +0000450void RuntimeImpl::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +0000451{
452 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
453 loadedNetwork->RegisterDebugCallback(func);
454}
455
Kevin Mayd92a6e42021-02-04 10:27:41 +0000456void RuntimeImpl::LoadDynamicBackends(const std::string& overrideBackendPath)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100457{
458 // Get the paths where to load the dynamic backends from
459 std::vector<std::string> backendPaths = DynamicBackendUtils::GetBackendPaths(overrideBackendPath);
460
461 // Get the shared objects to try to load as dynamic backends
462 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
463
464 // Create a list of dynamic backends
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100465 m_DynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
466
467 // Register the dynamic backends in the backend registry
Matteo Martincigh89533902019-08-15 12:08:06 +0100468 BackendIdSet registeredBackendIds = DynamicBackendUtils::RegisterDynamicBackends(m_DynamicBackends);
469
470 // Add the registered dynamic backend ids to the list of supported backends
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000471 m_DeviceSpec.AddSupportedBackends(registeredBackendIds, true);
telsoa014fcda012018-03-09 14:13:49 +0000472}
Matteo Martincighe54aa062019-08-05 14:12:11 +0100473
474} // namespace armnn