blob: c2b748653db51d0b36049fea57ef545fb434ae95 [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>
Jan Eilers15fcc7e2021-07-14 13:50:15 +01009#include <armnn/BackendHelper.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
Nikhil Raj77fe76b2021-06-09 14:55:32 +010017#include <common/include/LabelsAndEventClasses.hpp>
18
surmeh013537c2c2018-05-18 16:31:43 +010019#include <iostream>
20
Colm Donelan1aff3932020-02-05 17:48:59 +000021#include <backends/BackendProfiling.hpp>
telsoa014fcda012018-03-09 14:13:49 +000022
23using namespace armnn;
24using namespace std;
25
26namespace armnn
27{
Kevin Mayd92a6e42021-02-04 10:27:41 +000028IRuntime::IRuntime() : pRuntimeImpl( new RuntimeImpl(armnn::IRuntime::CreationOptions())) {}
29
30IRuntime::IRuntime(const IRuntime::CreationOptions& options) : pRuntimeImpl(new RuntimeImpl(options)) {}
31
32IRuntime::~IRuntime() = default;
telsoa014fcda012018-03-09 14:13:49 +000033
34IRuntime* IRuntime::CreateRaw(const CreationOptions& options)
35{
Kevin Mayd92a6e42021-02-04 10:27:41 +000036 return new IRuntime(options);
telsoa014fcda012018-03-09 14:13:49 +000037}
38
39IRuntimePtr IRuntime::Create(const CreationOptions& options)
40{
41 return IRuntimePtr(CreateRaw(options), &IRuntime::Destroy);
42}
43
44void IRuntime::Destroy(IRuntime* runtime)
45{
Kevin Mayd92a6e42021-02-04 10:27:41 +000046 delete runtime;
telsoa014fcda012018-03-09 14:13:49 +000047}
48
Kevin Mayd92a6e42021-02-04 10:27:41 +000049Status IRuntime::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr network)
50{
51 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network));
52}
53
54Status IRuntime::LoadNetwork(NetworkId& networkIdOut,
55 IOptimizedNetworkPtr network,
56 std::string& errorMessage)
57{
58 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network), errorMessage);
59}
60
61Status IRuntime::LoadNetwork(NetworkId& networkIdOut,
62 IOptimizedNetworkPtr network,
63 std::string& errorMessage,
64 const INetworkProperties& networkProperties)
65{
66 return pRuntimeImpl->LoadNetwork(networkIdOut, std::move(network), errorMessage, networkProperties);
67}
68
69TensorInfo IRuntime::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
70{
71 return pRuntimeImpl->GetInputTensorInfo(networkId, layerId);
72}
73
74TensorInfo IRuntime::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
75{
76 return pRuntimeImpl->GetOutputTensorInfo(networkId, layerId);
77}
78
79Status IRuntime::EnqueueWorkload(NetworkId networkId,
80 const InputTensors& inputTensors,
81 const OutputTensors& outputTensors)
82{
83 return pRuntimeImpl->EnqueueWorkload(networkId, inputTensors, outputTensors);
84}
85
Mike Kelly55a8ffd2021-04-07 20:10:49 +010086Status IRuntime::Execute(IWorkingMemHandle& workingMemHandle,
87 const InputTensors& inputTensors,
88 const OutputTensors& outputTensors)
89{
90 return pRuntimeImpl->Execute(workingMemHandle, inputTensors, outputTensors);
91}
92
Kevin Mayd92a6e42021-02-04 10:27:41 +000093Status IRuntime::UnloadNetwork(NetworkId networkId)
94{
95 return pRuntimeImpl->UnloadNetwork(networkId);
96}
97
98const IDeviceSpec& IRuntime::GetDeviceSpec() const
99{
100 return pRuntimeImpl->GetDeviceSpec();
101}
102
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100103std::unique_ptr<IWorkingMemHandle> IRuntime::CreateWorkingMemHandle(NetworkId networkId)
104{
105 return pRuntimeImpl->CreateWorkingMemHandle(networkId);
106}
107
Kevin Mayd92a6e42021-02-04 10:27:41 +0000108const std::shared_ptr<IProfiler> IRuntime::GetProfiler(NetworkId networkId) const
109{
110 return pRuntimeImpl->GetProfiler(networkId);
111}
112
113void IRuntime::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
114{
115 return pRuntimeImpl->RegisterDebugCallback(networkId, func);
116}
117
118int RuntimeImpl::GenerateNetworkId()
telsoa014fcda012018-03-09 14:13:49 +0000119{
120 return m_NetworkIdCounter++;
121}
122
Kevin Mayd92a6e42021-02-04 10:27:41 +0000123Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr inNetwork)
telsoa014fcda012018-03-09 14:13:49 +0000124{
telsoa01c577f2c2018-08-31 09:22:23 +0100125 std::string ignoredErrorMessage;
126 return LoadNetwork(networkIdOut, std::move(inNetwork), ignoredErrorMessage);
127}
128
Kevin Mayd92a6e42021-02-04 10:27:41 +0000129Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
130 IOptimizedNetworkPtr inNetwork,
131 std::string& errorMessage)
David Monahan4f1e8e42019-09-04 09:22:10 +0100132{
Francis Murtagh73d3e2e2021-04-29 14:23:04 +0100133 INetworkProperties networkProperties(false, MemorySource::Undefined, MemorySource::Undefined);
David Monahan4f1e8e42019-09-04 09:22:10 +0100134 return LoadNetwork(networkIdOut, std::move(inNetwork), errorMessage, networkProperties);
135}
136
Kevin Mayd92a6e42021-02-04 10:27:41 +0000137Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut,
138 IOptimizedNetworkPtr inNetwork,
139 std::string& errorMessage,
140 const INetworkProperties& networkProperties)
telsoa01c577f2c2018-08-31 09:22:23 +0100141{
telsoa014fcda012018-03-09 14:13:49 +0000142 IOptimizedNetwork* rawNetwork = inNetwork.release();
David Beck1b61be52018-11-08 09:19:14 +0000143
144 networkIdOut = GenerateNetworkId();
145
146 for (auto&& context : m_BackendContexts)
147 {
148 context.second->BeforeLoadNetwork(networkIdOut);
149 }
150
telsoa014fcda012018-03-09 14:13:49 +0000151 unique_ptr<LoadedNetwork> loadedNetwork = LoadedNetwork::MakeLoadedNetwork(
Francis Murtagh3d2b4b22021-02-15 18:23:17 +0000152 std::unique_ptr<IOptimizedNetwork>(rawNetwork),
David Monahan4f1e8e42019-09-04 09:22:10 +0100153 errorMessage,
Sadik Armagan3184c902020-03-18 10:57:30 +0000154 networkProperties,
Finn Williamsf364d532021-06-09 17:07:33 +0100155 m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000156
157 if (!loadedNetwork)
158 {
159 return Status::Failure;
160 }
161
telsoa01c577f2c2018-08-31 09:22:23 +0100162 {
163 std::lock_guard<std::mutex> lockGuard(m_Mutex);
164
165 // Stores the network
166 m_LoadedNetworks[networkIdOut] = std::move(loadedNetwork);
167 }
telsoa014fcda012018-03-09 14:13:49 +0000168
David Beck1b61be52018-11-08 09:19:14 +0000169 for (auto&& context : m_BackendContexts)
170 {
171 context.second->AfterLoadNetwork(networkIdOut);
172 }
173
Sadik Armagan3184c902020-03-18 10:57:30 +0000174 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000175 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000176 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_LOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000177 }
178
telsoa014fcda012018-03-09 14:13:49 +0000179 return Status::Success;
telsoa014fcda012018-03-09 14:13:49 +0000180}
181
Kevin Mayd92a6e42021-02-04 10:27:41 +0000182Status RuntimeImpl::UnloadNetwork(NetworkId networkId)
telsoa014fcda012018-03-09 14:13:49 +0000183{
David Beck1b61be52018-11-08 09:19:14 +0000184 bool unloadOk = true;
185 for (auto&& context : m_BackendContexts)
David Beck9efb57d2018-11-05 13:40:33 +0000186 {
David Beck1b61be52018-11-08 09:19:14 +0000187 unloadOk &= context.second->BeforeUnloadNetwork(networkId);
David Beck9efb57d2018-11-05 13:40:33 +0000188 }
David Beck1b61be52018-11-08 09:19:14 +0000189
190 if (!unloadOk)
191 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000192 ARMNN_LOG(warning) << "RuntimeImpl::UnloadNetwork(): failed to unload "
Derek Lamberti08446972019-11-26 16:38:31 +0000193 "network with ID:" << networkId << " because BeforeUnloadNetwork failed";
David Beck1b61be52018-11-08 09:19:14 +0000194 return Status::Failure;
195 }
David Beck9efb57d2018-11-05 13:40:33 +0000196
Jim Flynnf7713212020-07-14 09:50:59 +0100197 std::unique_ptr<profiling::TimelineUtilityMethods> timelineUtils =
198 profiling::TimelineUtilityMethods::GetTimelineUtils(m_ProfilingService);
telsoa014fcda012018-03-09 14:13:49 +0000199 {
telsoa01c577f2c2018-08-31 09:22:23 +0100200 std::lock_guard<std::mutex> lockGuard(m_Mutex);
201
Jim Flynnf7713212020-07-14 09:50:59 +0100202 // If timeline recording is on mark the Network end of life
203 if (timelineUtils)
204 {
205 auto search = m_LoadedNetworks.find(networkId);
206 if (search != m_LoadedNetworks.end())
207 {
208 profiling::ProfilingGuid networkGuid = search->second->GetNetworkGuid();
209 timelineUtils->RecordEvent(networkGuid,
210 profiling::LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS);
211 }
212 }
telsoa01c577f2c2018-08-31 09:22:23 +0100213 if (m_LoadedNetworks.erase(networkId) == 0)
214 {
Kevin Mayd92a6e42021-02-04 10:27:41 +0000215 ARMNN_LOG(warning) << "WARNING: RuntimeImpl::UnloadNetwork(): " << networkId << " not found!";
telsoa01c577f2c2018-08-31 09:22:23 +0100216 return Status::Failure;
217 }
Sadik Armagan3184c902020-03-18 10:57:30 +0000218
219 if (m_ProfilingService.IsProfilingEnabled())
Keith Davise394bd92019-12-02 15:12:19 +0000220 {
Sadik Armagan3184c902020-03-18 10:57:30 +0000221 m_ProfilingService.IncrementCounterValue(armnn::profiling::NETWORK_UNLOADS);
Keith Davise394bd92019-12-02 15:12:19 +0000222 }
David Beck1b61be52018-11-08 09:19:14 +0000223 }
David Beck9efb57d2018-11-05 13:40:33 +0000224
David Beck1b61be52018-11-08 09:19:14 +0000225 for (auto&& context : m_BackendContexts)
226 {
227 context.second->AfterUnloadNetwork(networkId);
telsoa01c577f2c2018-08-31 09:22:23 +0100228 }
229
Kevin Mayd92a6e42021-02-04 10:27:41 +0000230 ARMNN_LOG(debug) << "RuntimeImpl::UnloadNetwork(): Unloaded network with ID: " << networkId;
telsoa014fcda012018-03-09 14:13:49 +0000231 return Status::Success;
232}
233
Kevin Mayd92a6e42021-02-04 10:27:41 +0000234const std::shared_ptr<IProfiler> RuntimeImpl::GetProfiler(NetworkId networkId) const
telsoa01c577f2c2018-08-31 09:22:23 +0100235{
236 auto it = m_LoadedNetworks.find(networkId);
237 if (it != m_LoadedNetworks.end())
238 {
239 auto& loadedNetwork = it->second;
240 return loadedNetwork->GetProfiler();
241 }
242
243 return nullptr;
244}
245
Kevin Mayd92a6e42021-02-04 10:27:41 +0000246void RuntimeImpl::ReportStructure() // armnn::profiling::IProfilingService& profilingService as param
Keith Davis33ed2212020-03-30 10:43:41 +0100247{
248 // No-op for the time being, but this may be useful in future to have the profilingService available
249 // if (profilingService.IsProfilingEnabled()){}
250
251 LoadedNetworks::iterator it = m_LoadedNetworks.begin();
252 while (it != m_LoadedNetworks.end())
253 {
254 auto& loadedNetwork = it->second;
255 loadedNetwork->SendNetworkStructure();
256 // Increment the Iterator to point to next entry
257 it++;
258 }
259}
260
Kevin Mayd92a6e42021-02-04 10:27:41 +0000261RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options)
Keith Davis33ed2212020-03-30 10:43:41 +0100262 : m_NetworkIdCounter(0),
263 m_ProfilingService(*this)
telsoa014fcda012018-03-09 14:13:49 +0000264{
alered01a7227ac2020-05-07 14:58:29 +0100265 const auto start_time = armnn::GetTimeNow();
Derek Lamberti08446972019-11-26 16:38:31 +0000266 ARMNN_LOG(info) << "ArmNN v" << ARMNN_VERSION << "\n";
David Beck1b61be52018-11-08 09:19:14 +0000267
Keith Davis33ed2212020-03-30 10:43:41 +0100268 if ( options.m_ProfilingOptions.m_TimelineEnabled && !options.m_ProfilingOptions.m_EnableProfiling )
269 {
270 throw RuntimeException("It is not possible to enable timeline reporting without profiling being enabled");
271 }
272
Matteo Martincighe54aa062019-08-05 14:12:11 +0100273 // Load any available/compatible dynamic backend before the runtime
274 // goes through the backend registry
275 LoadDynamicBackends(options.m_DynamicBackendsPath);
276
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000277 BackendIdSet supportedBackends;
David Beck1b61be52018-11-08 09:19:14 +0000278 for (const auto& id : BackendRegistryInstance().GetBackendIds())
279 {
280 // Store backend contexts for the supported ones
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000281 try {
David Beck1b61be52018-11-08 09:19:14 +0000282 auto factoryFun = BackendRegistryInstance().GetFactory(id);
283 auto backend = factoryFun();
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100284 ARMNN_ASSERT(backend.get() != nullptr);
David Beck1b61be52018-11-08 09:19:14 +0000285
Jan Eilers15fcc7e2021-07-14 13:50:15 +0100286 // If the runtime is created in protected mode only add backends that support this mode
287 if (options.m_ProtectedMode)
288 {
289 // check if backend supports ProtectedMode
290 using BackendCapability = BackendOptions::BackendOption;
291 BackendCapability protectedContentCapability {"ProtectedContentAllocation", true};
292 if (!HasCapability(protectedContentCapability, id))
293 {
294 // Protected Content Allocation is not supported by the backend
295 // backend should not be registered
296 ARMNN_LOG(warning) << "Backend "
297 << id
298 << " is not registered as does not support protected content allocation \n";
299 continue;
300 }
301 std::string err;
302 if (!backend->UseCustomMemoryAllocator(err))
303 {
304 ARMNN_LOG(error) << "The backend "
305 << id
306 << " reported an error when entering protected mode. Backend won't be used."
307 << " ErrorMsg: " << err;
308 continue;
309 }
310 }
311
David Beck1b61be52018-11-08 09:19:14 +0000312 auto context = backend->CreateBackendContext(options);
313
314 // backends are allowed to return nullptrs if they
315 // don't wish to create a backend specific context
316 if (context)
317 {
318 m_BackendContexts.emplace(std::make_pair(id, std::move(context)));
319 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000320 supportedBackends.emplace(id);
Colm Donelan1aff3932020-02-05 17:48:59 +0000321
322 unique_ptr<armnn::profiling::IBackendProfiling> profilingIface =
323 std::make_unique<armnn::profiling::BackendProfiling>(armnn::profiling::BackendProfiling(
Sadik Armagan3184c902020-03-18 10:57:30 +0000324 options, m_ProfilingService, id));
Colm Donelan1aff3932020-02-05 17:48:59 +0000325
326 // Backends may also provide a profiling context. Ask for it now.
327 auto profilingContext = backend->CreateBackendProfilingContext(options, profilingIface);
328 // Backends that don't support profiling will return a null profiling context.
329 if (profilingContext)
330 {
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100331 // Pass the context onto the profiling service.
332 m_ProfilingService.AddBackendProfilingContext(id, profilingContext);
Colm Donelan1aff3932020-02-05 17:48:59 +0000333 }
David Beck1b61be52018-11-08 09:19:14 +0000334 }
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000335 catch (const BackendUnavailableException&)
336 {
337 // Ignore backends which are unavailable
338 }
David Beck1b61be52018-11-08 09:19:14 +0000339 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100340
Finn Williams45a73622020-05-15 18:41:05 +0100341 BackendRegistryInstance().SetProfilingService(m_ProfilingService);
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100342 // pass configuration info to the profiling service
343 m_ProfilingService.ConfigureProfilingService(options.m_ProfilingOptions);
Jim Flynn6398a982020-05-27 17:05:21 +0100344 if (options.m_ProfilingOptions.m_EnableProfiling)
345 {
346 // try to wait for the profiling service to initialise
347 m_ProfilingService.WaitForProfilingServiceActivation(3000);
348 }
Finn Williamsfe5a24b2020-04-09 16:05:28 +0100349
Matthew Bentham9a61fa62020-02-04 10:03:55 +0000350 m_DeviceSpec.AddSupportedBackends(supportedBackends);
alered01a7227ac2020-05-07 14:58:29 +0100351
352 ARMNN_LOG(info) << "Initialization time: " << std::setprecision(2)
353 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
surmeh01bceff2f2018-03-29 16:29:27 +0100354}
355
Kevin Mayd92a6e42021-02-04 10:27:41 +0000356RuntimeImpl::~RuntimeImpl()
surmeh01bceff2f2018-03-29 16:29:27 +0100357{
alered01a7227ac2020-05-07 14:58:29 +0100358 const auto start_time = armnn::GetTimeNow();
surmeh01bceff2f2018-03-29 16:29:27 +0100359 std::vector<int> networkIDs;
surmeh013537c2c2018-05-18 16:31:43 +0100360 try
361 {
362 // Coverity fix: The following code may throw an exception of type std::length_error.
363 std::transform(m_LoadedNetworks.begin(), m_LoadedNetworks.end(),
364 std::back_inserter(networkIDs),
365 [](const auto &pair) { return pair.first; });
366 }
367 catch (const std::exception& e)
368 {
369 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
370 // exception of type std::length_error.
371 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
372 std::cerr << "WARNING: An error has occurred when getting the IDs of the networks to unload: " << e.what()
373 << "\nSome of the loaded networks may not be unloaded" << std::endl;
374 }
375 // We then proceed to unload all the networks which IDs have been appended to the list
376 // up to the point the exception was thrown (if any).
surmeh01bceff2f2018-03-29 16:29:27 +0100377
378 for (auto networkID : networkIDs)
379 {
surmeh013537c2c2018-05-18 16:31:43 +0100380 try
381 {
382 // Coverity fix: UnloadNetwork() may throw an exception of type std::length_error,
383 // boost::log::v2s_mt_posix::odr_violation or boost::log::v2s_mt_posix::system_error
384 UnloadNetwork(networkID);
385 }
386 catch (const std::exception& e)
387 {
388 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
389 // exception of type std::length_error.
390 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
391 std::cerr << "WARNING: An error has occurred when unloading network " << networkID << ": " << e.what()
392 << std::endl;
393 }
telsoa014fcda012018-03-09 14:13:49 +0000394 }
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000395
396 // Clear all dynamic backends.
397 DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
398 m_DeviceSpec.ClearDynamicBackends();
Colm Donelan1aff3932020-02-05 17:48:59 +0000399 m_BackendContexts.clear();
Finn Williams45a73622020-05-15 18:41:05 +0100400
401 BackendRegistryInstance().SetProfilingService(armnn::EmptyOptional());
alered01a7227ac2020-05-07 14:58:29 +0100402 ARMNN_LOG(info) << "Shutdown time: " << std::setprecision(2)
403 << std::fixed << armnn::GetTimeDuration(start_time).count() << " ms\n";
telsoa014fcda012018-03-09 14:13:49 +0000404}
405
Kevin Mayd92a6e42021-02-04 10:27:41 +0000406LoadedNetwork* RuntimeImpl::GetLoadedNetworkPtr(NetworkId networkId) const
surmeh013537c2c2018-05-18 16:31:43 +0100407{
408 std::lock_guard<std::mutex> lockGuard(m_Mutex);
409 return m_LoadedNetworks.at(networkId).get();
410}
411
Kevin Mayd92a6e42021-02-04 10:27:41 +0000412TensorInfo RuntimeImpl::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000413{
surmeh013537c2c2018-05-18 16:31:43 +0100414 return GetLoadedNetworkPtr(networkId)->GetInputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000415}
416
Kevin Mayd92a6e42021-02-04 10:27:41 +0000417TensorInfo RuntimeImpl::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
telsoa014fcda012018-03-09 14:13:49 +0000418{
surmeh013537c2c2018-05-18 16:31:43 +0100419 return GetLoadedNetworkPtr(networkId)->GetOutputTensorInfo(layerId);
telsoa014fcda012018-03-09 14:13:49 +0000420}
421
Derek Lamberti03614f62018-10-02 15:52:46 +0100422
Kevin Mayd92a6e42021-02-04 10:27:41 +0000423Status RuntimeImpl::EnqueueWorkload(NetworkId networkId,
telsoa01c577f2c2018-08-31 09:22:23 +0100424 const InputTensors& inputTensors,
425 const OutputTensors& outputTensors)
telsoa014fcda012018-03-09 14:13:49 +0000426{
surmeh013537c2c2018-05-18 16:31:43 +0100427 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100428
429 if (!loadedNetwork)
430 {
431 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
432 return Status::Failure;
433 }
434 if (loadedNetwork->IsAsyncEnabled())
435 {
436 ARMNN_LOG(error) << "Network " << networkId << " is async enabled.\n";
437 return Status::Failure;
438 }
Narumol Prangnawarat5b4d0d52020-06-23 11:45:56 +0100439 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
440
441 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "EnqueueWorkload");
Derek Lamberti03614f62018-10-02 15:52:46 +0100442
443 static thread_local NetworkId lastId = networkId;
444 if (lastId != networkId)
445 {
446 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
447 {
448 network->FreeWorkingMemory();
449 });
450 }
451 lastId=networkId;
452
surmeh013537c2c2018-05-18 16:31:43 +0100453 return loadedNetwork->EnqueueWorkload(inputTensors, outputTensors);
telsoa014fcda012018-03-09 14:13:49 +0000454}
455
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100456Status RuntimeImpl::Execute(IWorkingMemHandle& iWorkingMemHandle,
457 const InputTensors& inputTensors,
458 const OutputTensors& outputTensors)
459{
460 NetworkId networkId = iWorkingMemHandle.GetNetworkId();
461 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
462
463 if (!loadedNetwork)
464 {
465 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
466 return Status::Failure;
467 }
468 if (!loadedNetwork->IsAsyncEnabled())
469 {
Keith Davise813d672021-04-22 10:10:34 +0100470 ARMNN_LOG(error) << "Attempting execute " << networkId << " when it is not async enabled.\n";
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100471 return Status::Failure;
472 }
473 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
474
475 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "Execute");
476
Mike Kelly55a8ffd2021-04-07 20:10:49 +0100477 return loadedNetwork->Execute(inputTensors, outputTensors, iWorkingMemHandle);
478}
479
480/// Create a new unique WorkingMemHandle object. Create multiple handles if you wish to have
481/// overlapped Execution by calling this function from different threads.
482std::unique_ptr<IWorkingMemHandle> RuntimeImpl::CreateWorkingMemHandle(NetworkId networkId)
483{
484 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
485
486 if (!loadedNetwork)
487 {
488 ARMNN_LOG(error) << "A Network with an id of " << networkId << " does not exist.\n";
489 return nullptr;
490 }
491 if (!loadedNetwork->IsAsyncEnabled())
492 {
493 ARMNN_LOG(error) << "Network " << networkId << " is not async enabled.\n";
494 return nullptr;
495 }
496 ProfilerManager::GetInstance().RegisterProfiler(loadedNetwork->GetProfiler().get());
497
498 ARMNN_SCOPED_PROFILING_EVENT(Compute::Undefined, "CreateWorkingMemHandle");
499
500 static thread_local NetworkId lastId = networkId;
501 if (lastId != networkId)
502 {
503 LoadedNetworkFuncSafe(lastId, [](LoadedNetwork* network)
504 {
505 network->FreeWorkingMemory();
506 });
507 }
508 lastId=networkId;
509
510 return loadedNetwork->CreateWorkingMemHandle(networkId);
511}
512
Kevin Mayd92a6e42021-02-04 10:27:41 +0000513void RuntimeImpl::RegisterDebugCallback(NetworkId networkId, const DebugCallbackFunction& func)
Nattapat Chaimanowong6e948202019-03-22 14:01:46 +0000514{
515 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
516 loadedNetwork->RegisterDebugCallback(func);
517}
518
Kevin Mayd92a6e42021-02-04 10:27:41 +0000519void RuntimeImpl::LoadDynamicBackends(const std::string& overrideBackendPath)
Matteo Martincighe54aa062019-08-05 14:12:11 +0100520{
521 // Get the paths where to load the dynamic backends from
522 std::vector<std::string> backendPaths = DynamicBackendUtils::GetBackendPaths(overrideBackendPath);
523
524 // Get the shared objects to try to load as dynamic backends
525 std::vector<std::string> sharedObjects = DynamicBackendUtils::GetSharedObjects(backendPaths);
526
527 // Create a list of dynamic backends
Matteo Martincigh0c2b2892019-08-05 14:12:11 +0100528 m_DynamicBackends = DynamicBackendUtils::CreateDynamicBackends(sharedObjects);
529
530 // Register the dynamic backends in the backend registry
Matteo Martincigh89533902019-08-15 12:08:06 +0100531 BackendIdSet registeredBackendIds = DynamicBackendUtils::RegisterDynamicBackends(m_DynamicBackends);
532
533 // Add the registered dynamic backend ids to the list of supported backends
Narumol Prangnawarat60a20fb2019-12-09 17:24:41 +0000534 m_DeviceSpec.AddSupportedBackends(registeredBackendIds, true);
telsoa014fcda012018-03-09 14:13:49 +0000535}
Matteo Martincighe54aa062019-08-05 14:12:11 +0100536
537} // namespace armnn