xref: /aosp_15_r20/external/armnn/src/backends/cl/ClBackendContext.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
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