blob: 34eca961b49253967745b92c63d575b85f150e53 [file] [log] [blame]
Laurent Carlier749294b2020-06-01 09:03:17 +01001//
Cathal Corbettd9e55f02023-01-11 13:03:21 +00002// Copyright © 2017, 2023 Arm Ltd and Contributors. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
surmeh013537c2c2018-05-18 16:31:43 +01004//
5
6#include "ClContextControl.hpp"
7
Aron Virginas-Tar74ba3dc2018-11-15 17:44:36 +00008#include <armnn/Exceptions.hpp>
surmeh013537c2c2018-05-18 16:31:43 +01009
Aron Virginas-Tar74ba3dc2018-11-15 17:44:36 +000010#include <LeakChecking.hpp>
11
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010012#include <armnn/utility/Assert.hpp>
Jan Eilers8eb25602020-03-09 12:13:48 +000013#include <armnn/utility/IgnoreUnused.hpp>
14
surmeh013537c2c2018-05-18 16:31:43 +010015#include <arm_compute/core/CL/CLKernelLibrary.h>
16#include <arm_compute/runtime/CL/CLScheduler.h>
surmeh013537c2c2018-05-18 16:31:43 +010017
James Ward47fce872020-09-10 11:57:28 +010018#include <fmt/format.h>
surmeh013537c2c2018-05-18 16:31:43 +010019
surmeh013537c2c2018-05-18 16:31:43 +010020namespace cl
21{
22class Context;
23class CommandQueue;
24class Device;
25}
26
27namespace armnn
28{
29
Derek Lamberti836b27b2019-11-20 10:51:57 +000030ClContextControl::ClContextControl(arm_compute::CLTuner *tuner,
Finn Williams40646322021-02-11 16:16:42 +000031 arm_compute::CLGEMMHeuristicsHandle* heuristicsHandle,
telsoa01c577f2c2018-08-31 09:22:23 +010032 bool profilingEnabled)
Derek Lamberti836b27b2019-11-20 10:51:57 +000033 : m_Tuner(tuner)
Finn Williams40646322021-02-11 16:16:42 +000034 , m_HeuristicsHandle(heuristicsHandle)
telsoa01c577f2c2018-08-31 09:22:23 +010035 , m_ProfilingEnabled(profilingEnabled)
surmeh013537c2c2018-05-18 16:31:43 +010036{
telsoa01c577f2c2018-08-31 09:22:23 +010037 // Ignore m_ProfilingEnabled if unused to avoid compiling problems when ArmCompute is disabled.
Jan Eilers8eb25602020-03-09 12:13:48 +000038 IgnoreUnused(m_ProfilingEnabled);
telsoa01c577f2c2018-08-31 09:22:23 +010039
surmeh013537c2c2018-05-18 16:31:43 +010040 try
41 {
42 std::vector<cl::Platform> platforms;
43 cl::Platform::get(&platforms);
44
telsoa01c577f2c2018-08-31 09:22:23 +010045 // Selects default platform for the first element.
surmeh013537c2c2018-05-18 16:31:43 +010046 cl::Platform::setDefault(platforms[0]);
47
48 std::vector<cl::Device> devices;
49 platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
50
telsoa01c577f2c2018-08-31 09:22:23 +010051 // Selects default device for the first element.
surmeh013537c2c2018-05-18 16:31:43 +010052 cl::Device::setDefault(devices[0]);
53 }
54 catch (const cl::Error& clError)
55 {
James Ward47fce872020-09-10 11:57:28 +010056 throw ClRuntimeUnavailableException(fmt::format(
57 "Could not initialize the CL runtime. Error description: {0}. CL error code: {1}",
58 clError.what(), clError.err()));
surmeh013537c2c2018-05-18 16:31:43 +010059 }
60
telsoa01c577f2c2018-08-31 09:22:23 +010061 // Removes the use of global CL context.
surmeh013537c2c2018-05-18 16:31:43 +010062 cl::Context::setDefault(cl::Context{});
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010063 ARMNN_ASSERT(cl::Context::getDefault()() == NULL);
surmeh013537c2c2018-05-18 16:31:43 +010064
telsoa01c577f2c2018-08-31 09:22:23 +010065 // Removes the use of global CL command queue.
surmeh013537c2c2018-05-18 16:31:43 +010066 cl::CommandQueue::setDefault(cl::CommandQueue{});
Narumol Prangnawaratac2770a2020-04-01 16:51:23 +010067 ARMNN_ASSERT(cl::CommandQueue::getDefault()() == NULL);
surmeh013537c2c2018-05-18 16:31:43 +010068
telsoa01c577f2c2018-08-31 09:22:23 +010069 // Always load the OpenCL runtime.
surmeh013537c2c2018-05-18 16:31:43 +010070 LoadOpenClRuntime();
surmeh013537c2c2018-05-18 16:31:43 +010071}
72
73ClContextControl::~ClContextControl()
74{
telsoa01c577f2c2018-08-31 09:22:23 +010075 // Load the OpencCL runtime without the tuned parameters to free the memory for them.
surmeh013537c2c2018-05-18 16:31:43 +010076 try
77 {
78 UnloadOpenClRuntime();
79 }
80 catch (const cl::Error& clError)
81 {
telsoa01c577f2c2018-08-31 09:22:23 +010082 // This should not happen, it is ignored if it does.
surmeh013537c2c2018-05-18 16:31:43 +010083
84 // Coverity fix: BOOST_LOG_TRIVIAL (previously used here to report the error) may throw an
85 // exception of type std::length_error.
86 // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
87 std::cerr << "A CL error occurred unloading the runtime tuner parameters: "
88 << clError.what() << ". CL error code is: " << clError.err() << std::endl;
89 }
surmeh013537c2c2018-05-18 16:31:43 +010090}
91
92void ClContextControl::LoadOpenClRuntime()
93{
94 DoLoadOpenClRuntime(true);
95}
96
97void ClContextControl::UnloadOpenClRuntime()
98{
99 DoLoadOpenClRuntime(false);
100}
101
Derek Lamberti836b27b2019-11-20 10:51:57 +0000102void ClContextControl::DoLoadOpenClRuntime(bool updateTunedParameters)
surmeh013537c2c2018-05-18 16:31:43 +0100103{
surmeh013537c2c2018-05-18 16:31:43 +0100104 cl::Device device = cl::Device::getDefault();
105 cl::Context context;
106 cl::CommandQueue commandQueue;
107
James Conroy663c1842019-11-01 15:21:48 +0000108 if (arm_compute::CLScheduler::get().is_initialised() && arm_compute::CLScheduler::get().context()() != NULL)
surmeh013537c2c2018-05-18 16:31:43 +0100109 {
telsoa01c577f2c2018-08-31 09:22:23 +0100110 // Wait for all queued CL requests to finish before reinitialising it.
surmeh013537c2c2018-05-18 16:31:43 +0100111 arm_compute::CLScheduler::get().sync();
112 }
113
114 try
115 {
116 arm_compute::CLKernelLibrary::get().clear_programs_cache();
telsoa01c577f2c2018-08-31 09:22:23 +0100117 // Initialise the scheduler with a dummy context to release the LLVM data (which only happens when there are no
surmeh013537c2c2018-05-18 16:31:43 +0100118 // context references); it is initialised again, with a proper context, later.
119 arm_compute::CLScheduler::get().init(context, commandQueue, device);
120 arm_compute::CLKernelLibrary::get().init(".", context, device);
121
122 {
123 //
telsoa01c577f2c2018-08-31 09:22:23 +0100124 // Here we replace the context with a new one in which
125 // the memory leak checks show it as an extra allocation but
126 // because of the scope of the leak checks, it doesn't count
surmeh013537c2c2018-05-18 16:31:43 +0100127 // the disposal of the original object. On the other hand it
128 // does count the creation of this context which it flags
129 // as a memory leak. By adding the following line we prevent
130 // this to happen.
131 //
132 ARMNN_DISABLE_LEAK_CHECKING_IN_SCOPE();
133 context = cl::Context(device);
134 }
135
telsoa01c577f2c2018-08-31 09:22:23 +0100136 // NOTE: In this specific case profiling has to be enabled on the command queue
137 // in order for the CLTuner to work.
Derek Lamberti836b27b2019-11-20 10:51:57 +0000138 bool profilingNeededForClTuner = updateTunedParameters && m_Tuner &&
139 m_Tuner->tune_new_kernels();
surmeh013537c2c2018-05-18 16:31:43 +0100140
telsoa01c577f2c2018-08-31 09:22:23 +0100141 if (m_ProfilingEnabled || profilingNeededForClTuner)
surmeh013537c2c2018-05-18 16:31:43 +0100142 {
telsoa01c577f2c2018-08-31 09:22:23 +0100143 // Create a new queue with profiling enabled.
surmeh013537c2c2018-05-18 16:31:43 +0100144 commandQueue = cl::CommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE);
145 }
146 else
147 {
telsoa01c577f2c2018-08-31 09:22:23 +0100148 // Use default queue.
surmeh013537c2c2018-05-18 16:31:43 +0100149 commandQueue = cl::CommandQueue(context, device);
150 }
151 }
152 catch (const cl::Error& clError)
153 {
James Ward47fce872020-09-10 11:57:28 +0100154 throw ClRuntimeUnavailableException(fmt::format(
155 "Could not initialize the CL runtime. Error description: {0}. CL error code: {1}",
156 clError.what(), clError.err()));
surmeh013537c2c2018-05-18 16:31:43 +0100157 }
158
159 // Note the first argument (path to cl source code) will be ignored as they should be embedded in the armcompute.
160 arm_compute::CLKernelLibrary::get().init(".", context, device);
Finn Williams40646322021-02-11 16:16:42 +0000161 arm_compute::CLScheduler::get().init(context, commandQueue, device, m_Tuner, m_HeuristicsHandle);
surmeh013537c2c2018-05-18 16:31:43 +0100162}
163
164void ClContextControl::ClearClCache()
165{
166 DoLoadOpenClRuntime(true);
167}
168
surmeh013537c2c2018-05-18 16:31:43 +0100169} // namespace armnn