blob: c63fb0c893f5044d083608600e3804141dde6f55 [file] [log] [blame]
David Beck1b61be52018-11-08 09:19:14 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "ClBackendContext.hpp"
Derek Lamberti836b27b2019-11-20 10:51:57 +00007#include "ClContextControl.hpp"
Derek Lamberti08446972019-11-26 16:38:31 +00008
9#include <armnn/Logging.hpp>
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010010#include <armnn/utility/Assert.hpp>
Jan Eilersbb446e52020-04-02 13:56:54 +010011#include <armnn/utility/PolymorphicDowncast.hpp>
Derek Lamberti08446972019-11-26 16:38:31 +000012
David Beck1b61be52018-11-08 09:19:14 +000013#include <arm_compute/core/CL/OpenCL.h>
14#include <arm_compute/core/CL/CLKernelLibrary.h>
15#include <arm_compute/runtime/CL/CLScheduler.h>
Derek Lamberti836b27b2019-11-20 10:51:57 +000016#include <arm_compute/runtime/CL/CLTunerTypes.h>
17
David Beck1b61be52018-11-08 09:19:14 +000018namespace armnn
19{
20
21struct ClBackendContext::ClContextControlWrapper
22{
Derek Lamberti836b27b2019-11-20 10:51:57 +000023 ClContextControlWrapper(arm_compute::CLTuner* tuner,
Finn Williams40646322021-02-11 16:16:42 +000024 arm_compute::CLGEMMHeuristicsHandle* heuristicsHandle,
David Beck1b61be52018-11-08 09:19:14 +000025 bool profilingEnabled)
Finn Williams40646322021-02-11 16:16:42 +000026 : m_ClContextControl(tuner, heuristicsHandle, profilingEnabled)
David Beck1b61be52018-11-08 09:19:14 +000027 {}
28
29 bool Sync()
30 {
David Beck1b61be52018-11-08 09:19:14 +000031 if (arm_compute::CLScheduler::get().context()() != NULL)
32 {
33 // Waits for all queued CL requests to finish before unloading the network they may be using.
34 try
35 {
36 // Coverity fix: arm_compute::CLScheduler::sync() may throw an exception of type cl::Error.
37 arm_compute::CLScheduler::get().sync();
38 }
39 catch (const cl::Error&)
40 {
Derek Lamberti08446972019-11-26 16:38:31 +000041 ARMNN_LOG(warning) << "Runtime::UnloadNetwork(): an error occurred while waiting for "
42 "the queued CL requests to finish";
David Beck1b61be52018-11-08 09:19:14 +000043 return false;
44 }
45 }
Aron Virginas-Tard46e6472018-11-16 10:26:23 +000046
David Beck1b61be52018-11-08 09:19:14 +000047 return true;
48 }
49
50 void ClearClCache()
51 {
David Beck1b61be52018-11-08 09:19:14 +000052 if (arm_compute::CLScheduler::get().context()() != NULL)
53 {
54 // There are no loaded networks left, so clear the CL cache to free up memory
55 m_ClContextControl.ClearClCache();
56 }
David Beck1b61be52018-11-08 09:19:14 +000057 }
58
David Beck1b61be52018-11-08 09:19:14 +000059 ClContextControl m_ClContextControl;
60};
61
Derek Lamberti836b27b2019-11-20 10:51:57 +000062std::string LowerString(std::string value)
63{
64 std::transform(value.begin(), value.end(), value.begin(),
65 [](unsigned char c){ return std::tolower(c); });
66
67 return value;
68}
69
70enum class TuningLevel
71{
72 None,
73 Rapid,
74 Normal,
75 Exhaustive
76};
77
78
79TuningLevel ParseTuningLevel(const BackendOptions::Var& value, TuningLevel defaultValue)
80{
81 if (value.IsInt())
82 {
alered01a7227ac2020-05-07 14:58:29 +010083 int v = value.AsInt();
Derek Lamberti836b27b2019-11-20 10:51:57 +000084 if (v > static_cast<int>(TuningLevel::Exhaustive) ||
85 v < static_cast<int>(TuningLevel::None))
86 {
87 ARMNN_LOG(warning) << "Invalid GpuAcc tuning level ("<< v << ") selected. "
88 "Using default(" << static_cast<int>(defaultValue) << ")";
89 } else
90 {
91 return static_cast<TuningLevel>(v);
92 }
93 }
94 return defaultValue;
95}
96
97bool ParseBoolean(const BackendOptions::Var& value, bool defaultValue)
98{
99 if (value.IsBool())
100 {
101 return value.AsBool();
102 }
Derek Lamberti836b27b2019-11-20 10:51:57 +0000103 return defaultValue;
104}
105
106std::string ParseFile(const BackendOptions::Var& value, std::string defaultValue)
107{
108 if (value.IsString())
109 {
110 return value.AsString();
111 }
112 return defaultValue;
113}
114
Derek Lamberti5c510f82020-02-11 12:56:52 +0000115void ConfigureTuner(arm_compute::CLTuner &tuner, TuningLevel level)
116{
117 tuner.set_tune_new_kernels(true); // Turn on tuning initially.
118
119 switch (level)
120 {
121 case TuningLevel::Rapid:
Jan Eilers2cd18472020-12-15 10:42:38 +0000122 ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Rapid (1)";
Derek Lamberti5c510f82020-02-11 12:56:52 +0000123 tuner.set_tuner_mode(arm_compute::CLTunerMode::RAPID);
124 break;
125 case TuningLevel::Normal:
Jan Eilers2cd18472020-12-15 10:42:38 +0000126 ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Normal (2)";
Derek Lamberti5c510f82020-02-11 12:56:52 +0000127 tuner.set_tuner_mode(arm_compute::CLTunerMode::NORMAL);
128 break;
129 case TuningLevel::Exhaustive:
Jan Eilers2cd18472020-12-15 10:42:38 +0000130 ARMNN_LOG(info) << "Gpu tuning is activated. TuningLevel: Exhaustive (3)";
Derek Lamberti5c510f82020-02-11 12:56:52 +0000131 tuner.set_tuner_mode(arm_compute::CLTunerMode::EXHAUSTIVE);
132 break;
133 case TuningLevel::None:
134 default:
135 tuner.set_tune_new_kernels(false); // Turn off tuning. Set to "use" only mode.
136 break;
137 }
138}
139
David Beck1b61be52018-11-08 09:19:14 +0000140ClBackendContext::ClBackendContext(const IRuntime::CreationOptions& options)
141 : IBackendContext(options)
Derek Lamberti5c510f82020-02-11 12:56:52 +0000142 , m_TuningFile()
David Beck1b61be52018-11-08 09:19:14 +0000143{
Derek Lamberti836b27b2019-11-20 10:51:57 +0000144 bool kernelProfiling = options.m_EnableGpuProfiling;
Derek Lamberti836b27b2019-11-20 10:51:57 +0000145
Derek Lamberti836b27b2019-11-20 10:51:57 +0000146 arm_compute::CLTuner* tuner = nullptr;
Finn Williams40646322021-02-11 16:16:42 +0000147 arm_compute::CLGEMMHeuristicsHandle* mlgoTuner = nullptr;
Derek Lambertief7e6b62020-02-04 14:49:16 +0000148 bool useLegacyTunerAPI = options.m_GpuAccTunedParameters.get() != nullptr;
149 if (useLegacyTunerAPI)
Derek Lamberti836b27b2019-11-20 10:51:57 +0000150 {
Jan Eilersbb446e52020-04-02 13:56:54 +0100151 auto clTunerParams = PolymorphicDowncast<ClTunedParameters*>(
Derek Lambertief7e6b62020-02-04 14:49:16 +0000152 options.m_GpuAccTunedParameters.get());
Derek Lamberti5c510f82020-02-11 12:56:52 +0000153 tuner = &clTunerParams->m_Tuner;
Derek Lamberti836b27b2019-11-20 10:51:57 +0000154
Derek Lamberti5c510f82020-02-11 12:56:52 +0000155 if (tuner)
Derek Lamberti836b27b2019-11-20 10:51:57 +0000156 {
Derek Lamberti5c510f82020-02-11 12:56:52 +0000157 auto ConvertTuningLevel = [](IGpuAccTunedParameters::TuningLevel level,
158 armnn::IGpuAccTunedParameters::Mode mode)
Derek Lamberti836b27b2019-11-20 10:51:57 +0000159 {
Derek Lamberti5c510f82020-02-11 12:56:52 +0000160 if (mode == armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
161 {
162 return TuningLevel::None;
163 }
164
Derek Lambertief7e6b62020-02-04 14:49:16 +0000165 switch(level)
Derek Lamberti836b27b2019-11-20 10:51:57 +0000166 {
Derek Lambertief7e6b62020-02-04 14:49:16 +0000167 case IGpuAccTunedParameters::TuningLevel::Rapid:
Derek Lamberti5c510f82020-02-11 12:56:52 +0000168 return TuningLevel::Rapid;
Derek Lambertief7e6b62020-02-04 14:49:16 +0000169 case IGpuAccTunedParameters::TuningLevel::Normal:
Derek Lamberti5c510f82020-02-11 12:56:52 +0000170 return TuningLevel::Normal;
Derek Lambertief7e6b62020-02-04 14:49:16 +0000171 case IGpuAccTunedParameters::TuningLevel::Exhaustive:
Derek Lamberti5c510f82020-02-11 12:56:52 +0000172 return TuningLevel::Exhaustive;
Derek Lambertief7e6b62020-02-04 14:49:16 +0000173 default:
174 {
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +0100175 ARMNN_ASSERT_MSG(false, "Tuning level not recognised.");
Derek Lamberti5c510f82020-02-11 12:56:52 +0000176 return TuningLevel::None;
Derek Lambertief7e6b62020-02-04 14:49:16 +0000177 }
Derek Lamberti836b27b2019-11-20 10:51:57 +0000178 }
Derek Lambertief7e6b62020-02-04 14:49:16 +0000179 };
Derek Lamberti836b27b2019-11-20 10:51:57 +0000180
Derek Lamberti5c510f82020-02-11 12:56:52 +0000181 TuningLevel tuningLevel = ConvertTuningLevel(clTunerParams->m_TuningLevel, clTunerParams->m_Mode);
182 ConfigureTuner(*tuner, tuningLevel);
Derek Lambertief7e6b62020-02-04 14:49:16 +0000183 }
184 }
185 else //New backend options API
186 {
Derek Lamberti5c510f82020-02-11 12:56:52 +0000187 const TuningLevel defaultTuningLevel = TuningLevel::None;
188 auto tuningLevel = defaultTuningLevel;
189
Derek Lambertief7e6b62020-02-04 14:49:16 +0000190 ParseOptions(options.m_BackendOptions, "GpuAcc", [&](std::string name, const BackendOptions::Var& value)
Derek Lamberti836b27b2019-11-20 10:51:57 +0000191 {
Derek Lambertief7e6b62020-02-04 14:49:16 +0000192 if (name == "KernelProfilingEnabled")
193 {
194 kernelProfiling |= ParseBoolean(value, false);
195 } else if (name == "TuningFile")
196 {
197 m_TuningFile = ParseFile(value, "");
198 } else if (name == "TuningLevel")
199 {
200 tuningLevel = ParseTuningLevel(value, defaultTuningLevel);
201 }
Finn Williams40646322021-02-11 16:16:42 +0000202 else if (name == "MLGOTuningFilePath")
203 {
204 m_MLGOTuningFile = ParseFile(value, "");
205 }
Derek Lambertief7e6b62020-02-04 14:49:16 +0000206 });
Derek Lamberti836b27b2019-11-20 10:51:57 +0000207
Derek Lambertief7e6b62020-02-04 14:49:16 +0000208 // Create the tuner, in tuning mode initially.
209 m_Tuner = std::make_unique<arm_compute::CLTuner>(true);
210
Derek Lamberti5c510f82020-02-11 12:56:52 +0000211 ConfigureTuner(*(m_Tuner.get()), tuningLevel);
Derek Lambertief7e6b62020-02-04 14:49:16 +0000212
Stuart Taylor06ccd712022-03-15 17:03:58 +0000213 if (!m_TuningFile.empty())
Derek Lambertief7e6b62020-02-04 14:49:16 +0000214 {
Derek Lamberti836b27b2019-11-20 10:51:57 +0000215 try
216 {
Jan Eilers2cd18472020-12-15 10:42:38 +0000217 ARMNN_LOG(info) << "Loading Gpu tuning data from file: " << m_TuningFile;
Derek Lamberti836b27b2019-11-20 10:51:57 +0000218 m_Tuner->load_from_file(m_TuningFile.c_str());
alered01a7227ac2020-05-07 14:58:29 +0100219 }
220 catch (const std::exception& e)
Derek Lamberti836b27b2019-11-20 10:51:57 +0000221 {
Stuart Taylor06ccd712022-03-15 17:03:58 +0000222 // Warn if not tuning, otherwise tuning will generate new params
223 if (tuningLevel == TuningLevel::None)
224 {
225 ARMNN_LOG(warning) << "Could not load GpuAcc tuner data file.";
226 }
Derek Lamberti836b27b2019-11-20 10:51:57 +0000227 }
Derek Lamberti836b27b2019-11-20 10:51:57 +0000228 }
Finn Williams40646322021-02-11 16:16:42 +0000229
230 if (!m_MLGOTuningFile.empty())
231 {
232 try
233 {
234 ARMNN_LOG(info) << "Loading Gpu MLGO tuning data from file: " << m_TuningFile;
235 if(m_MLGOTuner.reload_from_file(m_MLGOTuningFile.c_str()))
236 {
237 mlgoTuner = &m_MLGOTuner;
238 }
239 }
240 catch (const std::exception& e)
241 {
242 ARMNN_LOG(warning) << "Could not load GpuAcc MLGO tuner data file.";
243 }
244 }
245
alered01a7227ac2020-05-07 14:58:29 +0100246 tuner = m_Tuner.get();
Derek Lamberti836b27b2019-11-20 10:51:57 +0000247 }
248
249 m_ClContextControlWrapper = std::make_unique<ClContextControlWrapper>(
250 tuner,
Finn Williams40646322021-02-11 16:16:42 +0000251 mlgoTuner,
Derek Lamberti836b27b2019-11-20 10:51:57 +0000252 kernelProfiling
Finn Williams40646322021-02-11 16:16:42 +0000253 );
David Beck1b61be52018-11-08 09:19:14 +0000254}
255
256bool ClBackendContext::BeforeLoadNetwork(NetworkId)
257{
258 return true;
259}
260
261bool ClBackendContext::AfterLoadNetwork(NetworkId networkId)
262{
263 {
264 std::lock_guard<std::mutex> lockGuard(m_Mutex);
265 m_NetworkIds.insert(networkId);
266 }
267 return true;
268}
269
270bool ClBackendContext::BeforeUnloadNetwork(NetworkId)
271{
272 return m_ClContextControlWrapper->Sync();
273}
274
275bool ClBackendContext::AfterUnloadNetwork(NetworkId networkId)
276{
277 bool clearCache = false;
278 {
279 std::lock_guard<std::mutex> lockGuard(m_Mutex);
280 m_NetworkIds.erase(networkId);
281 clearCache = m_NetworkIds.empty();
282 }
283
284 if (clearCache)
285 {
286 m_ClContextControlWrapper->ClearClCache();
287 }
288
289 return true;
290}
291
Narumol Prangnawaratec5463d2022-02-04 17:50:20 +0000292bool ClBackendContext::AfterEnqueueWorkload(NetworkId)
293{
294 return m_ClContextControlWrapper->Sync();
295}
296
David Beck1b61be52018-11-08 09:19:14 +0000297ClBackendContext::~ClBackendContext()
298{
Derek Lamberti836b27b2019-11-20 10:51:57 +0000299 if (m_Tuner && !m_TuningFile.empty())
300 {
301 try
302 {
303 m_Tuner->save_to_file(m_TuningFile.c_str());
304 }
305 catch(const std::exception& e)
306 {
307 ARMNN_LOG(warning) << "Could not save GpuAcc tuner data to file " << m_TuningFile;
308 }
309 }
David Beck1b61be52018-11-08 09:19:14 +0000310}
311
312} // namespace armnn