2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // See LICENSE file in the project root for full license information.
7 #include "armnn/Version.hpp"
11 #ifdef ARMCOMPUTECL_ENABLED
12 #include <arm_compute/core/CL/OpenCL.h>
13 #include <arm_compute/core/CL/CLKernelLibrary.h>
14 #include <arm_compute/runtime/CL/CLScheduler.h>
17 #include <boost/log/trivial.hpp>
18 #include <boost/polymorphic_cast.hpp>
20 using namespace armnn;
26 IRuntime* IRuntime::CreateRaw(const CreationOptions& options)
28 return new Runtime(options);
31 IRuntimePtr IRuntime::Create(const CreationOptions& options)
33 return IRuntimePtr(CreateRaw(options), &IRuntime::Destroy);
36 void IRuntime::Destroy(IRuntime* runtime)
38 delete boost::polymorphic_downcast<Runtime*>(runtime);
41 int Runtime::GenerateNetworkId()
43 return m_NetworkIdCounter++;
46 Status Runtime::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr inNetwork)
48 std::string ignoredErrorMessage;
49 return LoadNetwork(networkIdOut, std::move(inNetwork), ignoredErrorMessage);
52 Status Runtime::LoadNetwork(NetworkId& networkIdOut,
53 IOptimizedNetworkPtr inNetwork,
54 std::string & errorMessage)
56 IOptimizedNetwork* rawNetwork = inNetwork.release();
57 unique_ptr<LoadedNetwork> loadedNetwork = LoadedNetwork::MakeLoadedNetwork(
58 std::unique_ptr<OptimizedNetwork>(boost::polymorphic_downcast<OptimizedNetwork*>(rawNetwork)),
63 return Status::Failure;
66 networkIdOut = GenerateNetworkId();
69 std::lock_guard<std::mutex> lockGuard(m_Mutex);
72 m_LoadedNetworks[networkIdOut] = std::move(loadedNetwork);
75 return Status::Success;
78 Status Runtime::UnloadNetwork(NetworkId networkId)
80 #ifdef ARMCOMPUTECL_ENABLED
81 if (arm_compute::CLScheduler::get().context()() != NULL)
83 // Waits for all queued CL requests to finish before unloading the network they may be using.
86 // Coverity fix: arm_compute::CLScheduler::sync() may throw an exception of type cl::Error.
87 arm_compute::CLScheduler::get().sync();
89 catch (const cl::Error&)
91 BOOST_LOG_TRIVIAL(warning) << "WARNING: Runtime::UnloadNetwork(): an error occurred while waiting for "
92 "the queued CL requests to finish";
93 return Status::Failure;
99 std::lock_guard<std::mutex> lockGuard(m_Mutex);
101 if (m_LoadedNetworks.erase(networkId) == 0)
103 BOOST_LOG_TRIVIAL(warning) << "WARNING: Runtime::UnloadNetwork(): " << networkId << " not found!";
104 return Status::Failure;
107 #ifdef ARMCOMPUTECL_ENABLED
108 if (arm_compute::CLScheduler::get().context()() != NULL && m_LoadedNetworks.empty())
110 // There are no loaded networks left, so clear the CL cache to free up memory
111 m_ClContextControl.ClearClCache();
116 BOOST_LOG_TRIVIAL(debug) << "Runtime::UnloadNetwork(): Unloaded network with ID: " << networkId;
117 return Status::Success;
120 const std::shared_ptr<IProfiler> Runtime::GetProfiler(NetworkId networkId) const
122 auto it = m_LoadedNetworks.find(networkId);
123 if (it != m_LoadedNetworks.end())
125 auto& loadedNetwork = it->second;
126 return loadedNetwork->GetProfiler();
132 Runtime::Runtime(const CreationOptions& options)
133 : m_ClContextControl(options.m_GpuAccTunedParameters.get(),
134 options.m_EnableGpuProfiling)
135 , m_NetworkIdCounter(0)
137 BOOST_LOG_TRIVIAL(info) << "ArmNN v" << ARMNN_VERSION << "\n";
139 m_DeviceSpec.m_SupportedComputeDevices.insert(armnn::Compute::CpuRef);
140 #if ARMCOMPUTECL_ENABLED
141 m_DeviceSpec.m_SupportedComputeDevices.insert(armnn::Compute::GpuAcc);
143 #if ARMCOMPUTENEON_ENABLED
144 m_DeviceSpec.m_SupportedComputeDevices.insert(armnn::Compute::CpuAcc);
150 std::vector<int> networkIDs;
153 // Coverity fix: The following code may throw an exception of type std::length_error.
154 std::transform(m_LoadedNetworks.begin(), m_LoadedNetworks.end(),
155 std::back_inserter(networkIDs),
156 [](const auto &pair) { return pair.first; });
158 catch (const std::exception& e)
160 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
161 // exception of type std::length_error.
162 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
163 std::cerr << "WARNING: An error has occurred when getting the IDs of the networks to unload: " << e.what()
164 << "\nSome of the loaded networks may not be unloaded" << std::endl;
166 // We then proceed to unload all the networks which IDs have been appended to the list
167 // up to the point the exception was thrown (if any).
169 for (auto networkID : networkIDs)
173 // Coverity fix: UnloadNetwork() may throw an exception of type std::length_error,
174 // boost::log::v2s_mt_posix::odr_violation or boost::log::v2s_mt_posix::system_error
175 UnloadNetwork(networkID);
177 catch (const std::exception& e)
179 // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
180 // exception of type std::length_error.
181 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
182 std::cerr << "WARNING: An error has occurred when unloading network " << networkID << ": " << e.what()
188 LoadedNetwork* Runtime::GetLoadedNetworkPtr(NetworkId networkId) const
190 std::lock_guard<std::mutex> lockGuard(m_Mutex);
191 return m_LoadedNetworks.at(networkId).get();
194 TensorInfo Runtime::GetInputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
196 return GetLoadedNetworkPtr(networkId)->GetInputTensorInfo(layerId);
199 TensorInfo Runtime::GetOutputTensorInfo(NetworkId networkId, LayerBindingId layerId) const
201 return GetLoadedNetworkPtr(networkId)->GetOutputTensorInfo(layerId);
204 Status Runtime::EnqueueWorkload(NetworkId networkId,
205 const InputTensors& inputTensors,
206 const OutputTensors& outputTensors)
208 LoadedNetwork* loadedNetwork = GetLoadedNetworkPtr(networkId);
209 return loadedNetwork->EnqueueWorkload(inputTensors, outputTensors);