blob: 8df8143927575e7dffc73160329cb4ec56852883 [file] [log] [blame]
David Beck1b61be52018-11-08 09:19:14 +00001//
Colm Donelanb4ef1632024-02-01 15:00:43 +00002// Copyright © 2017, 2024 Arm Ltd and Contributors. All rights reserved.
David Beck1b61be52018-11-08 09:19:14 +00003// 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>
Jan Eilersbb446e52020-04-02 13:56:54 +010010#include <armnn/utility/PolymorphicDowncast.hpp>
Derek Lamberti08446972019-11-26 16:38:31 +000011
David Beck1b61be52018-11-08 09:19:14 +000012#include <arm_compute/core/CL/OpenCL.h>
13#include <arm_compute/core/CL/CLKernelLibrary.h>
14#include <arm_compute/runtime/CL/CLScheduler.h>
Derek Lamberti836b27b2019-11-20 10:51:57 +000015#include <arm_compute/runtime/CL/CLTunerTypes.h>
16
David Beck1b61be52018-11-08 09:19:14 +000017namespace armnn
18{
19
20struct ClBackendContext::ClContextControlWrapper
21{
TeresaARM8b4a4832022-12-20 16:28:22 +000022 ClContextControlWrapper(arm_compute::CLTuner* tuner,
23 arm_compute::CLGEMMHeuristicsHandle* heuristicsHandle,
24 bool profilingEnabled)
25 : m_ClContextControl(tuner, heuristicsHandle, profilingEnabled)
26 {}
David Beck1b61be52018-11-08 09:19:14 +000027
28 bool Sync()
29 {
David Beck1b61be52018-11-08 09:19:14 +000030 if (arm_compute::CLScheduler::get().context()() != NULL)
31 {
32 // Waits for all queued CL requests to finish before unloading the network they may be using.
33 try
34 {
35 // Coverity fix: arm_compute::CLScheduler::sync() may throw an exception of type cl::Error.
36 arm_compute::CLScheduler::get().sync();
37 }
38 catch (const cl::Error&)
39 {
Derek Lamberti08446972019-11-26 16:38:31 +000040 ARMNN_LOG(warning) << "Runtime::UnloadNetwork(): an error occurred while waiting for "
41 "the queued CL requests to finish";
David Beck1b61be52018-11-08 09:19:14 +000042 return false;
43 }
44 }
Aron Virginas-Tard46e6472018-11-16 10:26:23 +000045
David Beck1b61be52018-11-08 09:19:14 +000046 return true;
47 }
48
49 void ClearClCache()
50 {
David Beck1b61be52018-11-08 09:19:14 +000051 if (arm_compute::CLScheduler::get().context()() != NULL)
52 {
53 // There are no loaded networks left, so clear the CL cache to free up memory
54 m_ClContextControl.ClearClCache();
55 }
David Beck1b61be52018-11-08 09:19:14 +000056 }
57
David Beck1b61be52018-11-08 09:19:14 +000058 ClContextControl m_ClContextControl;
59};
60
David Beck1b61be52018-11-08 09:19:14 +000061ClBackendContext::ClBackendContext(const IRuntime::CreationOptions& options)
62 : IBackendContext(options)
Derek Lamberti5c510f82020-02-11 12:56:52 +000063 , m_TuningFile()
David Beck1b61be52018-11-08 09:19:14 +000064{
Derek Lamberti836b27b2019-11-20 10:51:57 +000065 bool kernelProfiling = options.m_EnableGpuProfiling;
Derek Lamberti836b27b2019-11-20 10:51:57 +000066
Derek Lamberti836b27b2019-11-20 10:51:57 +000067 arm_compute::CLTuner* tuner = nullptr;
Finn Williams40646322021-02-11 16:16:42 +000068 arm_compute::CLGEMMHeuristicsHandle* mlgoTuner = nullptr;
Derek Lambertief7e6b62020-02-04 14:49:16 +000069 bool useLegacyTunerAPI = options.m_GpuAccTunedParameters.get() != nullptr;
70 if (useLegacyTunerAPI)
Derek Lamberti836b27b2019-11-20 10:51:57 +000071 {
Jan Eilersbb446e52020-04-02 13:56:54 +010072 auto clTunerParams = PolymorphicDowncast<ClTunedParameters*>(
Derek Lambertief7e6b62020-02-04 14:49:16 +000073 options.m_GpuAccTunedParameters.get());
Derek Lamberti5c510f82020-02-11 12:56:52 +000074 tuner = &clTunerParams->m_Tuner;
Derek Lamberti836b27b2019-11-20 10:51:57 +000075
Derek Lamberti5c510f82020-02-11 12:56:52 +000076 if (tuner)
Derek Lamberti836b27b2019-11-20 10:51:57 +000077 {
Derek Lamberti5c510f82020-02-11 12:56:52 +000078 auto ConvertTuningLevel = [](IGpuAccTunedParameters::TuningLevel level,
79 armnn::IGpuAccTunedParameters::Mode mode)
Derek Lamberti836b27b2019-11-20 10:51:57 +000080 {
Derek Lamberti5c510f82020-02-11 12:56:52 +000081 if (mode == armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
82 {
83 return TuningLevel::None;
84 }
85
Derek Lambertief7e6b62020-02-04 14:49:16 +000086 switch(level)
Derek Lamberti836b27b2019-11-20 10:51:57 +000087 {
Derek Lambertief7e6b62020-02-04 14:49:16 +000088 case IGpuAccTunedParameters::TuningLevel::Rapid:
Derek Lamberti5c510f82020-02-11 12:56:52 +000089 return TuningLevel::Rapid;
Derek Lambertief7e6b62020-02-04 14:49:16 +000090 case IGpuAccTunedParameters::TuningLevel::Normal:
Derek Lamberti5c510f82020-02-11 12:56:52 +000091 return TuningLevel::Normal;
Derek Lambertief7e6b62020-02-04 14:49:16 +000092 case IGpuAccTunedParameters::TuningLevel::Exhaustive:
Derek Lamberti5c510f82020-02-11 12:56:52 +000093 return TuningLevel::Exhaustive;
Derek Lambertief7e6b62020-02-04 14:49:16 +000094 default:
95 {
Colm Donelanb4ef1632024-02-01 15:00:43 +000096 throw InvalidArgumentException("Invalid value of tuning level specified.");
Derek Lambertief7e6b62020-02-04 14:49:16 +000097 }
Derek Lamberti836b27b2019-11-20 10:51:57 +000098 }
Derek Lambertief7e6b62020-02-04 14:49:16 +000099 };
Derek Lamberti836b27b2019-11-20 10:51:57 +0000100
Derek Lamberti5c510f82020-02-11 12:56:52 +0000101 TuningLevel tuningLevel = ConvertTuningLevel(clTunerParams->m_TuningLevel, clTunerParams->m_Mode);
102 ConfigureTuner(*tuner, tuningLevel);
Derek Lambertief7e6b62020-02-04 14:49:16 +0000103 }
104 }
105 else //New backend options API
106 {
Derek Lamberti5c510f82020-02-11 12:56:52 +0000107 const TuningLevel defaultTuningLevel = TuningLevel::None;
108 auto tuningLevel = defaultTuningLevel;
109
Derek Lambertief7e6b62020-02-04 14:49:16 +0000110 ParseOptions(options.m_BackendOptions, "GpuAcc", [&](std::string name, const BackendOptions::Var& value)
Derek Lamberti836b27b2019-11-20 10:51:57 +0000111 {
Derek Lambertief7e6b62020-02-04 14:49:16 +0000112 if (name == "KernelProfilingEnabled")
113 {
Cathal Corbettd9e55f02023-01-11 13:03:21 +0000114 kernelProfiling |= ParseBooleanBackendOption(value, false);
Derek Lambertief7e6b62020-02-04 14:49:16 +0000115 } else if (name == "TuningFile")
116 {
Cathal Corbettd9e55f02023-01-11 13:03:21 +0000117 m_TuningFile = ParseStringBackendOption(value, "");
Derek Lambertief7e6b62020-02-04 14:49:16 +0000118 } else if (name == "TuningLevel")
119 {
120 tuningLevel = ParseTuningLevel(value, defaultTuningLevel);
121 }
Finn Williams40646322021-02-11 16:16:42 +0000122 else if (name == "MLGOTuningFilePath")
123 {
Cathal Corbettd9e55f02023-01-11 13:03:21 +0000124 m_MLGOTuningFile = ParseStringBackendOption(value, "");
Finn Williams40646322021-02-11 16:16:42 +0000125 }
Derek Lambertief7e6b62020-02-04 14:49:16 +0000126 });
Derek Lamberti836b27b2019-11-20 10:51:57 +0000127
Derek Lambertief7e6b62020-02-04 14:49:16 +0000128 // Create the tuner, in tuning mode initially.
129 m_Tuner = std::make_unique<arm_compute::CLTuner>(true);
130
Derek Lamberti5c510f82020-02-11 12:56:52 +0000131 ConfigureTuner(*(m_Tuner.get()), tuningLevel);
Derek Lambertief7e6b62020-02-04 14:49:16 +0000132
Stuart Taylor06ccd712022-03-15 17:03:58 +0000133 if (!m_TuningFile.empty())
Derek Lambertief7e6b62020-02-04 14:49:16 +0000134 {
Derek Lamberti836b27b2019-11-20 10:51:57 +0000135 try
136 {
Jan Eilers2cd18472020-12-15 10:42:38 +0000137 ARMNN_LOG(info) << "Loading Gpu tuning data from file: " << m_TuningFile;
Derek Lamberti836b27b2019-11-20 10:51:57 +0000138 m_Tuner->load_from_file(m_TuningFile.c_str());
alered01a7227ac2020-05-07 14:58:29 +0100139 }
140 catch (const std::exception& e)
Derek Lamberti836b27b2019-11-20 10:51:57 +0000141 {
Stuart Taylor06ccd712022-03-15 17:03:58 +0000142 // Warn if not tuning, otherwise tuning will generate new params
143 if (tuningLevel == TuningLevel::None)
144 {
145 ARMNN_LOG(warning) << "Could not load GpuAcc tuner data file.";
146 }
Derek Lamberti836b27b2019-11-20 10:51:57 +0000147 }
Derek Lamberti836b27b2019-11-20 10:51:57 +0000148 }
Finn Williams40646322021-02-11 16:16:42 +0000149
150 if (!m_MLGOTuningFile.empty())
151 {
152 try
153 {
154 ARMNN_LOG(info) << "Loading Gpu MLGO tuning data from file: " << m_TuningFile;
155 if(m_MLGOTuner.reload_from_file(m_MLGOTuningFile.c_str()))
156 {
157 mlgoTuner = &m_MLGOTuner;
158 }
159 }
160 catch (const std::exception& e)
161 {
162 ARMNN_LOG(warning) << "Could not load GpuAcc MLGO tuner data file.";
163 }
164 }
165
alered01a7227ac2020-05-07 14:58:29 +0100166 tuner = m_Tuner.get();
Derek Lamberti836b27b2019-11-20 10:51:57 +0000167 }
168
TeresaARM8b4a4832022-12-20 16:28:22 +0000169 m_ClContextControlWrapper = std::make_unique<ClContextControlWrapper>(
170 tuner,
171 mlgoTuner,
172 kernelProfiling
173 );
David Beck1b61be52018-11-08 09:19:14 +0000174}
175
176bool ClBackendContext::BeforeLoadNetwork(NetworkId)
177{
178 return true;
179}
180
181bool ClBackendContext::AfterLoadNetwork(NetworkId networkId)
182{
183 {
184 std::lock_guard<std::mutex> lockGuard(m_Mutex);
185 m_NetworkIds.insert(networkId);
186 }
187 return true;
188}
189
190bool ClBackendContext::BeforeUnloadNetwork(NetworkId)
191{
192 return m_ClContextControlWrapper->Sync();
193}
194
195bool ClBackendContext::AfterUnloadNetwork(NetworkId networkId)
196{
197 bool clearCache = false;
198 {
199 std::lock_guard<std::mutex> lockGuard(m_Mutex);
200 m_NetworkIds.erase(networkId);
201 clearCache = m_NetworkIds.empty();
202 }
203
204 if (clearCache)
205 {
206 m_ClContextControlWrapper->ClearClCache();
207 }
208
209 return true;
210}
211
Narumol Prangnawaratec5463d2022-02-04 17:50:20 +0000212bool ClBackendContext::AfterEnqueueWorkload(NetworkId)
213{
214 return m_ClContextControlWrapper->Sync();
215}
216
David Beck1b61be52018-11-08 09:19:14 +0000217ClBackendContext::~ClBackendContext()
218{
Derek Lamberti836b27b2019-11-20 10:51:57 +0000219 if (m_Tuner && !m_TuningFile.empty())
220 {
221 try
222 {
223 m_Tuner->save_to_file(m_TuningFile.c_str());
224 }
225 catch(const std::exception& e)
226 {
227 ARMNN_LOG(warning) << "Could not save GpuAcc tuner data to file " << m_TuningFile;
228 }
229 }
David Beck1b61be52018-11-08 09:19:14 +0000230}
231
232} // namespace armnn