1*89c4ff92SAndroid Build Coastguard Worker //
2*89c4ff92SAndroid Build Coastguard Worker // Copyright © 2017, 2023 Arm Ltd and Contributors. All rights reserved.
3*89c4ff92SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
4*89c4ff92SAndroid Build Coastguard Worker //
5*89c4ff92SAndroid Build Coastguard Worker
6*89c4ff92SAndroid Build Coastguard Worker #include "ClBackendContext.hpp"
7*89c4ff92SAndroid Build Coastguard Worker #include "ClContextControl.hpp"
8*89c4ff92SAndroid Build Coastguard Worker
9*89c4ff92SAndroid Build Coastguard Worker #include <armnn/Logging.hpp>
10*89c4ff92SAndroid Build Coastguard Worker #include <armnn/utility/Assert.hpp>
11*89c4ff92SAndroid Build Coastguard Worker #include <armnn/utility/PolymorphicDowncast.hpp>
12*89c4ff92SAndroid Build Coastguard Worker
13*89c4ff92SAndroid Build Coastguard Worker #include <arm_compute/core/CL/OpenCL.h>
14*89c4ff92SAndroid Build Coastguard Worker #include <arm_compute/core/CL/CLKernelLibrary.h>
15*89c4ff92SAndroid Build Coastguard Worker #include <arm_compute/runtime/CL/CLScheduler.h>
16*89c4ff92SAndroid Build Coastguard Worker #include <arm_compute/runtime/CL/CLTunerTypes.h>
17*89c4ff92SAndroid Build Coastguard Worker
18*89c4ff92SAndroid Build Coastguard Worker namespace armnn
19*89c4ff92SAndroid Build Coastguard Worker {
20*89c4ff92SAndroid Build Coastguard Worker
21*89c4ff92SAndroid Build Coastguard Worker struct ClBackendContext::ClContextControlWrapper
22*89c4ff92SAndroid Build Coastguard Worker {
ClContextControlWrapperarmnn::ClBackendContext::ClContextControlWrapper23*89c4ff92SAndroid Build Coastguard Worker ClContextControlWrapper(arm_compute::CLTuner* tuner,
24*89c4ff92SAndroid Build Coastguard Worker arm_compute::CLGEMMHeuristicsHandle* heuristicsHandle,
25*89c4ff92SAndroid Build Coastguard Worker bool profilingEnabled)
26*89c4ff92SAndroid Build Coastguard Worker : m_ClContextControl(tuner, heuristicsHandle, profilingEnabled)
27*89c4ff92SAndroid Build Coastguard Worker {}
28*89c4ff92SAndroid Build Coastguard Worker
Syncarmnn::ClBackendContext::ClContextControlWrapper29*89c4ff92SAndroid Build Coastguard Worker bool Sync()
30*89c4ff92SAndroid Build Coastguard Worker {
31*89c4ff92SAndroid Build Coastguard Worker if (arm_compute::CLScheduler::get().context()() != NULL)
32*89c4ff92SAndroid Build Coastguard Worker {
33*89c4ff92SAndroid Build Coastguard Worker // Waits for all queued CL requests to finish before unloading the network they may be using.
34*89c4ff92SAndroid Build Coastguard Worker try
35*89c4ff92SAndroid Build Coastguard Worker {
36*89c4ff92SAndroid Build Coastguard Worker // Coverity fix: arm_compute::CLScheduler::sync() may throw an exception of type cl::Error.
37*89c4ff92SAndroid Build Coastguard Worker arm_compute::CLScheduler::get().sync();
38*89c4ff92SAndroid Build Coastguard Worker }
39*89c4ff92SAndroid Build Coastguard Worker catch (const cl::Error&)
40*89c4ff92SAndroid Build Coastguard Worker {
41*89c4ff92SAndroid Build Coastguard Worker ARMNN_LOG(warning) << "Runtime::UnloadNetwork(): an error occurred while waiting for "
42*89c4ff92SAndroid Build Coastguard Worker "the queued CL requests to finish";
43*89c4ff92SAndroid Build Coastguard Worker return false;
44*89c4ff92SAndroid Build Coastguard Worker }
45*89c4ff92SAndroid Build Coastguard Worker }
46*89c4ff92SAndroid Build Coastguard Worker
47*89c4ff92SAndroid Build Coastguard Worker return true;
48*89c4ff92SAndroid Build Coastguard Worker }
49*89c4ff92SAndroid Build Coastguard Worker
ClearClCachearmnn::ClBackendContext::ClContextControlWrapper50*89c4ff92SAndroid Build Coastguard Worker void ClearClCache()
51*89c4ff92SAndroid Build Coastguard Worker {
52*89c4ff92SAndroid Build Coastguard Worker if (arm_compute::CLScheduler::get().context()() != NULL)
53*89c4ff92SAndroid Build Coastguard Worker {
54*89c4ff92SAndroid Build Coastguard Worker // There are no loaded networks left, so clear the CL cache to free up memory
55*89c4ff92SAndroid Build Coastguard Worker m_ClContextControl.ClearClCache();
56*89c4ff92SAndroid Build Coastguard Worker }
57*89c4ff92SAndroid Build Coastguard Worker }
58*89c4ff92SAndroid Build Coastguard Worker
59*89c4ff92SAndroid Build Coastguard Worker ClContextControl m_ClContextControl;
60*89c4ff92SAndroid Build Coastguard Worker };
61*89c4ff92SAndroid Build Coastguard Worker
ClBackendContext(const IRuntime::CreationOptions & options)62*89c4ff92SAndroid Build Coastguard Worker ClBackendContext::ClBackendContext(const IRuntime::CreationOptions& options)
63*89c4ff92SAndroid Build Coastguard Worker : IBackendContext(options)
64*89c4ff92SAndroid Build Coastguard Worker , m_TuningFile()
65*89c4ff92SAndroid Build Coastguard Worker {
66*89c4ff92SAndroid Build Coastguard Worker bool kernelProfiling = options.m_EnableGpuProfiling;
67*89c4ff92SAndroid Build Coastguard Worker
68*89c4ff92SAndroid Build Coastguard Worker arm_compute::CLTuner* tuner = nullptr;
69*89c4ff92SAndroid Build Coastguard Worker arm_compute::CLGEMMHeuristicsHandle* mlgoTuner = nullptr;
70*89c4ff92SAndroid Build Coastguard Worker bool useLegacyTunerAPI = options.m_GpuAccTunedParameters.get() != nullptr;
71*89c4ff92SAndroid Build Coastguard Worker if (useLegacyTunerAPI)
72*89c4ff92SAndroid Build Coastguard Worker {
73*89c4ff92SAndroid Build Coastguard Worker auto clTunerParams = PolymorphicDowncast<ClTunedParameters*>(
74*89c4ff92SAndroid Build Coastguard Worker options.m_GpuAccTunedParameters.get());
75*89c4ff92SAndroid Build Coastguard Worker tuner = &clTunerParams->m_Tuner;
76*89c4ff92SAndroid Build Coastguard Worker
77*89c4ff92SAndroid Build Coastguard Worker if (tuner)
78*89c4ff92SAndroid Build Coastguard Worker {
79*89c4ff92SAndroid Build Coastguard Worker auto ConvertTuningLevel = [](IGpuAccTunedParameters::TuningLevel level,
80*89c4ff92SAndroid Build Coastguard Worker armnn::IGpuAccTunedParameters::Mode mode)
81*89c4ff92SAndroid Build Coastguard Worker {
82*89c4ff92SAndroid Build Coastguard Worker if (mode == armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
83*89c4ff92SAndroid Build Coastguard Worker {
84*89c4ff92SAndroid Build Coastguard Worker return TuningLevel::None;
85*89c4ff92SAndroid Build Coastguard Worker }
86*89c4ff92SAndroid Build Coastguard Worker
87*89c4ff92SAndroid Build Coastguard Worker switch(level)
88*89c4ff92SAndroid Build Coastguard Worker {
89*89c4ff92SAndroid Build Coastguard Worker case IGpuAccTunedParameters::TuningLevel::Rapid:
90*89c4ff92SAndroid Build Coastguard Worker return TuningLevel::Rapid;
91*89c4ff92SAndroid Build Coastguard Worker case IGpuAccTunedParameters::TuningLevel::Normal:
92*89c4ff92SAndroid Build Coastguard Worker return TuningLevel::Normal;
93*89c4ff92SAndroid Build Coastguard Worker case IGpuAccTunedParameters::TuningLevel::Exhaustive:
94*89c4ff92SAndroid Build Coastguard Worker return TuningLevel::Exhaustive;
95*89c4ff92SAndroid Build Coastguard Worker default:
96*89c4ff92SAndroid Build Coastguard Worker {
97*89c4ff92SAndroid Build Coastguard Worker ARMNN_ASSERT_MSG(false, "Tuning level not recognised.");
98*89c4ff92SAndroid Build Coastguard Worker return TuningLevel::None;
99*89c4ff92SAndroid Build Coastguard Worker }
100*89c4ff92SAndroid Build Coastguard Worker }
101*89c4ff92SAndroid Build Coastguard Worker };
102*89c4ff92SAndroid Build Coastguard Worker
103*89c4ff92SAndroid Build Coastguard Worker TuningLevel tuningLevel = ConvertTuningLevel(clTunerParams->m_TuningLevel, clTunerParams->m_Mode);
104*89c4ff92SAndroid Build Coastguard Worker ConfigureTuner(*tuner, tuningLevel);
105*89c4ff92SAndroid Build Coastguard Worker }
106*89c4ff92SAndroid Build Coastguard Worker }
107*89c4ff92SAndroid Build Coastguard Worker else //New backend options API
108*89c4ff92SAndroid Build Coastguard Worker {
109*89c4ff92SAndroid Build Coastguard Worker const TuningLevel defaultTuningLevel = TuningLevel::None;
110*89c4ff92SAndroid Build Coastguard Worker auto tuningLevel = defaultTuningLevel;
111*89c4ff92SAndroid Build Coastguard Worker
112*89c4ff92SAndroid Build Coastguard Worker ParseOptions(options.m_BackendOptions, "GpuAcc", [&](std::string name, const BackendOptions::Var& value)
113*89c4ff92SAndroid Build Coastguard Worker {
114*89c4ff92SAndroid Build Coastguard Worker if (name == "KernelProfilingEnabled")
115*89c4ff92SAndroid Build Coastguard Worker {
116*89c4ff92SAndroid Build Coastguard Worker kernelProfiling |= ParseBooleanBackendOption(value, false);
117*89c4ff92SAndroid Build Coastguard Worker } else if (name == "TuningFile")
118*89c4ff92SAndroid Build Coastguard Worker {
119*89c4ff92SAndroid Build Coastguard Worker m_TuningFile = ParseStringBackendOption(value, "");
120*89c4ff92SAndroid Build Coastguard Worker } else if (name == "TuningLevel")
121*89c4ff92SAndroid Build Coastguard Worker {
122*89c4ff92SAndroid Build Coastguard Worker tuningLevel = ParseTuningLevel(value, defaultTuningLevel);
123*89c4ff92SAndroid Build Coastguard Worker }
124*89c4ff92SAndroid Build Coastguard Worker else if (name == "MLGOTuningFilePath")
125*89c4ff92SAndroid Build Coastguard Worker {
126*89c4ff92SAndroid Build Coastguard Worker m_MLGOTuningFile = ParseStringBackendOption(value, "");
127*89c4ff92SAndroid Build Coastguard Worker }
128*89c4ff92SAndroid Build Coastguard Worker });
129*89c4ff92SAndroid Build Coastguard Worker
130*89c4ff92SAndroid Build Coastguard Worker // Create the tuner, in tuning mode initially.
131*89c4ff92SAndroid Build Coastguard Worker m_Tuner = std::make_unique<arm_compute::CLTuner>(true);
132*89c4ff92SAndroid Build Coastguard Worker
133*89c4ff92SAndroid Build Coastguard Worker ConfigureTuner(*(m_Tuner.get()), tuningLevel);
134*89c4ff92SAndroid Build Coastguard Worker
135*89c4ff92SAndroid Build Coastguard Worker if (!m_TuningFile.empty())
136*89c4ff92SAndroid Build Coastguard Worker {
137*89c4ff92SAndroid Build Coastguard Worker try
138*89c4ff92SAndroid Build Coastguard Worker {
139*89c4ff92SAndroid Build Coastguard Worker ARMNN_LOG(info) << "Loading Gpu tuning data from file: " << m_TuningFile;
140*89c4ff92SAndroid Build Coastguard Worker m_Tuner->load_from_file(m_TuningFile.c_str());
141*89c4ff92SAndroid Build Coastguard Worker }
142*89c4ff92SAndroid Build Coastguard Worker catch (const std::exception& e)
143*89c4ff92SAndroid Build Coastguard Worker {
144*89c4ff92SAndroid Build Coastguard Worker // Warn if not tuning, otherwise tuning will generate new params
145*89c4ff92SAndroid Build Coastguard Worker if (tuningLevel == TuningLevel::None)
146*89c4ff92SAndroid Build Coastguard Worker {
147*89c4ff92SAndroid Build Coastguard Worker ARMNN_LOG(warning) << "Could not load GpuAcc tuner data file.";
148*89c4ff92SAndroid Build Coastguard Worker }
149*89c4ff92SAndroid Build Coastguard Worker }
150*89c4ff92SAndroid Build Coastguard Worker }
151*89c4ff92SAndroid Build Coastguard Worker
152*89c4ff92SAndroid Build Coastguard Worker if (!m_MLGOTuningFile.empty())
153*89c4ff92SAndroid Build Coastguard Worker {
154*89c4ff92SAndroid Build Coastguard Worker try
155*89c4ff92SAndroid Build Coastguard Worker {
156*89c4ff92SAndroid Build Coastguard Worker ARMNN_LOG(info) << "Loading Gpu MLGO tuning data from file: " << m_TuningFile;
157*89c4ff92SAndroid Build Coastguard Worker if(m_MLGOTuner.reload_from_file(m_MLGOTuningFile.c_str()))
158*89c4ff92SAndroid Build Coastguard Worker {
159*89c4ff92SAndroid Build Coastguard Worker mlgoTuner = &m_MLGOTuner;
160*89c4ff92SAndroid Build Coastguard Worker }
161*89c4ff92SAndroid Build Coastguard Worker }
162*89c4ff92SAndroid Build Coastguard Worker catch (const std::exception& e)
163*89c4ff92SAndroid Build Coastguard Worker {
164*89c4ff92SAndroid Build Coastguard Worker ARMNN_LOG(warning) << "Could not load GpuAcc MLGO tuner data file.";
165*89c4ff92SAndroid Build Coastguard Worker }
166*89c4ff92SAndroid Build Coastguard Worker }
167*89c4ff92SAndroid Build Coastguard Worker
168*89c4ff92SAndroid Build Coastguard Worker tuner = m_Tuner.get();
169*89c4ff92SAndroid Build Coastguard Worker }
170*89c4ff92SAndroid Build Coastguard Worker
171*89c4ff92SAndroid Build Coastguard Worker m_ClContextControlWrapper = std::make_unique<ClContextControlWrapper>(
172*89c4ff92SAndroid Build Coastguard Worker tuner,
173*89c4ff92SAndroid Build Coastguard Worker mlgoTuner,
174*89c4ff92SAndroid Build Coastguard Worker kernelProfiling
175*89c4ff92SAndroid Build Coastguard Worker );
176*89c4ff92SAndroid Build Coastguard Worker }
177*89c4ff92SAndroid Build Coastguard Worker
BeforeLoadNetwork(NetworkId)178*89c4ff92SAndroid Build Coastguard Worker bool ClBackendContext::BeforeLoadNetwork(NetworkId)
179*89c4ff92SAndroid Build Coastguard Worker {
180*89c4ff92SAndroid Build Coastguard Worker return true;
181*89c4ff92SAndroid Build Coastguard Worker }
182*89c4ff92SAndroid Build Coastguard Worker
AfterLoadNetwork(NetworkId networkId)183*89c4ff92SAndroid Build Coastguard Worker bool ClBackendContext::AfterLoadNetwork(NetworkId networkId)
184*89c4ff92SAndroid Build Coastguard Worker {
185*89c4ff92SAndroid Build Coastguard Worker {
186*89c4ff92SAndroid Build Coastguard Worker std::lock_guard<std::mutex> lockGuard(m_Mutex);
187*89c4ff92SAndroid Build Coastguard Worker m_NetworkIds.insert(networkId);
188*89c4ff92SAndroid Build Coastguard Worker }
189*89c4ff92SAndroid Build Coastguard Worker return true;
190*89c4ff92SAndroid Build Coastguard Worker }
191*89c4ff92SAndroid Build Coastguard Worker
BeforeUnloadNetwork(NetworkId)192*89c4ff92SAndroid Build Coastguard Worker bool ClBackendContext::BeforeUnloadNetwork(NetworkId)
193*89c4ff92SAndroid Build Coastguard Worker {
194*89c4ff92SAndroid Build Coastguard Worker return m_ClContextControlWrapper->Sync();
195*89c4ff92SAndroid Build Coastguard Worker }
196*89c4ff92SAndroid Build Coastguard Worker
AfterUnloadNetwork(NetworkId networkId)197*89c4ff92SAndroid Build Coastguard Worker bool ClBackendContext::AfterUnloadNetwork(NetworkId networkId)
198*89c4ff92SAndroid Build Coastguard Worker {
199*89c4ff92SAndroid Build Coastguard Worker bool clearCache = false;
200*89c4ff92SAndroid Build Coastguard Worker {
201*89c4ff92SAndroid Build Coastguard Worker std::lock_guard<std::mutex> lockGuard(m_Mutex);
202*89c4ff92SAndroid Build Coastguard Worker m_NetworkIds.erase(networkId);
203*89c4ff92SAndroid Build Coastguard Worker clearCache = m_NetworkIds.empty();
204*89c4ff92SAndroid Build Coastguard Worker }
205*89c4ff92SAndroid Build Coastguard Worker
206*89c4ff92SAndroid Build Coastguard Worker if (clearCache)
207*89c4ff92SAndroid Build Coastguard Worker {
208*89c4ff92SAndroid Build Coastguard Worker m_ClContextControlWrapper->ClearClCache();
209*89c4ff92SAndroid Build Coastguard Worker }
210*89c4ff92SAndroid Build Coastguard Worker
211*89c4ff92SAndroid Build Coastguard Worker return true;
212*89c4ff92SAndroid Build Coastguard Worker }
213*89c4ff92SAndroid Build Coastguard Worker
AfterEnqueueWorkload(NetworkId)214*89c4ff92SAndroid Build Coastguard Worker bool ClBackendContext::AfterEnqueueWorkload(NetworkId)
215*89c4ff92SAndroid Build Coastguard Worker {
216*89c4ff92SAndroid Build Coastguard Worker return m_ClContextControlWrapper->Sync();
217*89c4ff92SAndroid Build Coastguard Worker }
218*89c4ff92SAndroid Build Coastguard Worker
~ClBackendContext()219*89c4ff92SAndroid Build Coastguard Worker ClBackendContext::~ClBackendContext()
220*89c4ff92SAndroid Build Coastguard Worker {
221*89c4ff92SAndroid Build Coastguard Worker if (m_Tuner && !m_TuningFile.empty())
222*89c4ff92SAndroid Build Coastguard Worker {
223*89c4ff92SAndroid Build Coastguard Worker try
224*89c4ff92SAndroid Build Coastguard Worker {
225*89c4ff92SAndroid Build Coastguard Worker m_Tuner->save_to_file(m_TuningFile.c_str());
226*89c4ff92SAndroid Build Coastguard Worker }
227*89c4ff92SAndroid Build Coastguard Worker catch(const std::exception& e)
228*89c4ff92SAndroid Build Coastguard Worker {
229*89c4ff92SAndroid Build Coastguard Worker ARMNN_LOG(warning) << "Could not save GpuAcc tuner data to file " << m_TuningFile;
230*89c4ff92SAndroid Build Coastguard Worker }
231*89c4ff92SAndroid Build Coastguard Worker }
232*89c4ff92SAndroid Build Coastguard Worker }
233*89c4ff92SAndroid Build Coastguard Worker
234*89c4ff92SAndroid Build Coastguard Worker } // namespace armnn