blob: b23dd06e6fb315ca789545b299b655b717897b40 [file] [log] [blame]
Sadik Armagan8f397a12022-06-17 15:38:22 +01001//
Jim Flynn357add22023-04-10 23:26:40 +01002// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan8f397a12022-06-17 15:38:22 +01003// SPDX-License-Identifier: MIT
4//
5
6#define LOG_TAG "arm-armnn-sl"
7
8#include "DriverOptions.hpp"
9
10#include "CanonicalUtils.hpp"
11
12#include <armnn/Version.hpp>
13#include <log/log.h>
14#include "SystemPropertiesUtils.hpp"
15
16#include <OperationsUtils.h>
17
18#include <cxxopts/cxxopts.hpp>
19
20#include <algorithm>
21#include <cassert>
22#include <functional>
23#include <string>
24#include <sstream>
25
26using namespace android;
27using namespace std;
28
29namespace armnn_driver
30{
31
32DriverOptions::DriverOptions(armnn::Compute computeDevice, bool fp16Enabled)
33 : m_Backends({computeDevice})
34 , m_VerboseLogging(false)
35 , m_RequestInputsAndOutputsDumpDir(std::string(""))
36 , m_ServiceName(std::string("armnn_sl"))
37 , m_ForcedUnsupportedOperations({})
38 , m_ClTunedParametersMode(armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
39 , m_ClTuningLevel(armnn::IGpuAccTunedParameters::TuningLevel::Rapid)
40 , m_EnableGpuProfiling(false)
41 , m_fp16Enabled(fp16Enabled)
42 , m_FastMathEnabled(false)
43 , m_ShouldExit(false)
44 , m_ExitCode(EXIT_SUCCESS)
45 , m_CachedNetworkFilePath(std::string(""))
46 , m_SaveCachedNetwork(false)
47 , m_NumberOfThreads(0)
48 , m_EnableAsyncModelExecution(false)
49 , m_ArmnnNumberOfThreads(1)
50{
51}
52
53DriverOptions::DriverOptions(const std::vector<armnn::BackendId>& backends, bool fp16Enabled)
54 : m_Backends(backends)
55 , m_VerboseLogging(false)
56 , m_RequestInputsAndOutputsDumpDir(std::string(""))
57 , m_ServiceName(std::string("armnn_sl"))
58 , m_ForcedUnsupportedOperations({})
59 , m_ClTunedParametersMode(armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
60 , m_ClTuningLevel(armnn::IGpuAccTunedParameters::TuningLevel::Rapid)
61 , m_EnableGpuProfiling(false)
62 , m_fp16Enabled(fp16Enabled)
63 , m_FastMathEnabled(false)
64 , m_ShouldExit(false)
65 , m_ExitCode(EXIT_SUCCESS)
66 , m_CachedNetworkFilePath(std::string(""))
67 , m_SaveCachedNetwork(false)
68 , m_NumberOfThreads(0)
69 , m_EnableAsyncModelExecution(false)
70 , m_ArmnnNumberOfThreads(1)
71{
72}
73
74// This default constructor will example an environment variable called
75// ARMNN_SL_OPTIONS. It will parse the parameters using the existing cxx
76// opts mechanism.
77DriverOptions::DriverOptions()
78 : m_VerboseLogging(false)
79 , m_RequestInputsAndOutputsDumpDir(std::string(""))
80 , m_ServiceName(std::string("armnn_sl"))
81 , m_ForcedUnsupportedOperations({})
82 , m_ClTunedParametersMode(armnn::IGpuAccTunedParameters::Mode::UseTunedParameters)
83 , m_ClTuningLevel(armnn::IGpuAccTunedParameters::TuningLevel::Rapid)
84 , m_EnableGpuProfiling(false)
85 , m_fp16Enabled(false)
86 , m_FastMathEnabled(false)
87 , m_ShouldExit(false)
88 , m_SaveCachedNetwork(false)
89 , m_NumberOfThreads(0)
90 , m_EnableAsyncModelExecution(false)
91 , m_ArmnnNumberOfThreads(1)
92{
93 std::string unsupportedOperationsAsString;
94 std::string clTunedParametersModeAsString;
95 std::string clTuningLevelAsString;
96 std::vector<std::string> backends;
97 bool showHelp = false;
98 bool showVersion = false;
99
100 const char* rawEnv = std::getenv("ARMNN_SL_OPTIONS");
101 // If the environment variable isn't set we'll continue as if it were an empty string.
102 if (!rawEnv)
103 {
104 rawEnv = "";
105 }
106 string optionsAsString(rawEnv);
107 regex whiteSpaceRegex("\\s+");
108 // Tokienize the string based on whitespace.
Jim Flynn357add22023-04-10 23:26:40 +0100109 sregex_token_iterator iter(optionsAsString.begin(), optionsAsString.end(), whiteSpaceRegex, -1);
Sadik Armagan8f397a12022-06-17 15:38:22 +0100110 sregex_token_iterator end;
111 vector<string> cliAsVector(iter, end);
112 // As we're pretending to be a command line, argv[0] should be an executable name.
113 cliAsVector.insert(cliAsVector.begin(), "ARMNN_SL_OPTIONS");
114 // Convert the vector of string to a vector of char* backed by the existing vector.
115 std::vector<char*> argVector;
116 for (const auto& arg : cliAsVector)
117 {
118 argVector.push_back((char*)arg.data());
119 }
120 // Terminate the array.
121 argVector.push_back(nullptr);
122 // Create usable variables.
123 int argc = argVector.size() - 1; // Ignore the null pointer at the end.
124 char** argv = argVector.data();
125
126 cxxopts::Options optionsDesc(argv[0], "Arm NN Support Library for the Android Neural Networks API."
127 "The support library will convert Android NNAPI requests "
128 "and delegate them to available ArmNN backends.");
129 try
130 {
131 optionsDesc.add_options()
132
133 ("a,enable-fast-math",
134 "Enables fast_math options in backends that support it. Using the fast_math flag can "
135 "lead to performance improvements but may result in reduced or different precision.",
136 cxxopts::value<bool>(m_FastMathEnabled)->default_value("false"))
137
138 ("c,compute","Comma separated list of backends to run layers on. "
139 "Examples of possible values are: CpuRef, CpuAcc, GpuAcc",
140 cxxopts::value<std::vector<std::string>>(backends))
141
142 ("d,request-inputs-and-outputs-dump-dir",
143 "If non-empty, the directory where request inputs and outputs should be dumped",
144 cxxopts::value<std::string>(m_RequestInputsAndOutputsDumpDir)->default_value(""))
145
146 ("f,fp16-enabled", "Enables support for relaxed computation from Float32 to Float16",
147 cxxopts::value<bool>(m_fp16Enabled)->default_value("false"))
148
149 ("h,help", "Show this help",
150 cxxopts::value<bool>(showHelp)->default_value("false")->implicit_value("true"))
151
152 ("m,cl-tuned-parameters-mode",
153 "If 'UseTunedParameters' (the default), will read CL tuned parameters from the file specified by "
154 "--cl-tuned-parameters-file. "
155 "If 'UpdateTunedParameters', will also find the optimum parameters when preparing new networks and update "
156 "the file accordingly.",
157 cxxopts::value<std::string>(clTunedParametersModeAsString)->default_value("UseTunedParameters"))
158
159 ("g,mlgo-cl-tuned-parameters-file",
160 "If non-empty, the given file will be used to load/save MLGO CL tuned parameters. ",
161 cxxopts::value<std::string>(m_ClMLGOTunedParametersFile)->default_value(""))
162
163 ("o,cl-tuning-level",
164 "exhaustive: all lws values are tested "
165 "normal: reduced number of lws values but enough to still have the performance really close to the "
166 "exhaustive approach "
167 "rapid: only 3 lws values should be tested for each kernel ",
168 cxxopts::value<std::string>(clTuningLevelAsString)->default_value("rapid"))
169
170 ("p,gpu-profiling", "Turns GPU profiling on",
171 cxxopts::value<bool>(m_EnableGpuProfiling)->default_value("false"))
172
173 ("q,cached-network-file", "If non-empty, the given file will be used to load/save cached network. "
174 "If save-cached-network option is given will save the cached network to given file."
175 "If save-cached-network option is not given will load the cached network from given "
176 "file.",
177 cxxopts::value<std::string>(m_CachedNetworkFilePath)->default_value(""))
178
179 ("s,save-cached-network",
180 "Enables saving the cached network to the file given with cached-network-file option."
181 " See also --cached-network-file",
182 cxxopts::value<bool>(m_SaveCachedNetwork)->default_value("false"))
183
184 ("number-of-threads",
185 "Assign the number of threads used by the CpuAcc backend. "
186 "Input value must be between 1 and 64. "
187 "Default is set to 0 (Backend will decide number of threads to use).",
188 cxxopts::value<unsigned int>(m_NumberOfThreads)->default_value("0"))
189
190 ("t,cl-tuned-parameters-file",
191 "If non-empty, the given file will be used to load/save CL tuned parameters. "
192 "See also --cl-tuned-parameters-mode",
193 cxxopts::value<std::string>(m_ClTunedParametersFile)->default_value(""))
194
195 ("u,unsupported-operations",
196 "If non-empty, a comma-separated list of operation indices which the driver will forcibly "
197 "consider unsupported",
198 cxxopts::value<std::string>(unsupportedOperationsAsString)->default_value(""))
199
200 ("v,verbose-logging", "Turns verbose logging on",
201 cxxopts::value<bool>(m_VerboseLogging)->default_value("false")->implicit_value("true"))
202
203 ("V,version", "Show version information",
204 cxxopts::value<bool>(showVersion)->default_value("false")->implicit_value("true"))
205 ;
206 }
207 catch (const std::exception& e)
208 {
209 VLOG(DRIVER) << "An error occurred attempting to construct options: " << e.what();
210 std::cout << "An error occurred attempting to construct options: %s" << std::endl;
211 m_ExitCode = EXIT_FAILURE;
212 return;
213 }
214
215 try
216 {
217 cxxopts::ParseResult result = optionsDesc.parse(argc, argv);
218 }
Jim Flynn357add22023-04-10 23:26:40 +0100219 catch (const cxxopts::exceptions::exception& e)
Sadik Armagan8f397a12022-06-17 15:38:22 +0100220 {
221 VLOG(DRIVER) << "An exception occurred attempting to parse program options: " << e.what();
222 std::cout << optionsDesc.help() << std::endl
223 << "An exception occurred while parsing program options: " << std::endl
224 << e.what() << std::endl;
225 m_ShouldExit = true;
226 m_ExitCode = EXIT_FAILURE;
227 return;
228 }
229 if (showHelp)
230 {
231 VLOG(DRIVER) << "Showing help and exiting";
232 std::cout << optionsDesc.help() << std::endl;
233 m_ShouldExit = true;
234 m_ExitCode = EXIT_SUCCESS;
235 return;
236 }
237 if (showVersion)
238 {
239 VLOG(DRIVER) << "Showing version and exiting";
240 std::cout << "ArmNN Android NN driver for the Android Neural Networks API.\n"
241 "ArmNN v" << ARMNN_VERSION << std::endl;
242 m_ShouldExit = true;
243 m_ExitCode = EXIT_SUCCESS;
244 return;
245 }
246
247 // Convert the string backend names into backendId's.
248 m_Backends.reserve(backends.size());
249 for (auto&& backend : backends)
250 {
251 m_Backends.emplace_back(backend);
252 }
253
254 // If no backends have been specified then the default value is GpuAcc.
255 if (backends.empty())
256 {
257 VLOG(DRIVER) << "No backends have been specified:";
258 std::cout << optionsDesc.help() << std::endl
259 << "Unable to start:" << std::endl
260 << "No backends have been specified" << std::endl;
261 m_ShouldExit = true;
262 m_ExitCode = EXIT_FAILURE;
263 return;
264 }
265
266 if (!unsupportedOperationsAsString.empty())
267 {
268 std::istringstream argStream(unsupportedOperationsAsString);
269
270 std::string s;
271 while (!argStream.eof())
272 {
273 std::getline(argStream, s, ',');
274 try
275 {
276 unsigned int operationIdx = std::stoi(s);
277 m_ForcedUnsupportedOperations.insert(operationIdx);
278 }
279 catch (const std::invalid_argument&)
280 {
281 VLOG(DRIVER) << "Ignoring invalid integer argument in -u/--unsupported-operations value: " << s.c_str();
282 }
283 }
284 }
285
286 if (!m_ClTunedParametersFile.empty())
287 {
288 // The mode is only relevant if the file path has been provided
289 if (clTunedParametersModeAsString == "UseTunedParameters")
290 {
291 m_ClTunedParametersMode = armnn::IGpuAccTunedParameters::Mode::UseTunedParameters;
292 }
293 else if (clTunedParametersModeAsString == "UpdateTunedParameters")
294 {
295 m_ClTunedParametersMode = armnn::IGpuAccTunedParameters::Mode::UpdateTunedParameters;
296 }
297 else
298 {
299 VLOG(DRIVER) << "Requested unknown cl-tuned-parameters-mode "
300 << clTunedParametersModeAsString.c_str() << ". Defaulting to UseTunedParameters";
301 }
302
303 if (clTuningLevelAsString == "exhaustive")
304 {
305 m_ClTuningLevel = armnn::IGpuAccTunedParameters::TuningLevel::Exhaustive;
306 }
307 else if (clTuningLevelAsString == "normal")
308 {
309 m_ClTuningLevel = armnn::IGpuAccTunedParameters::TuningLevel::Normal;
310 }
311 else if (clTuningLevelAsString == "rapid")
312 {
313 m_ClTuningLevel = armnn::IGpuAccTunedParameters::TuningLevel::Rapid;
314 }
315 else
316 {
317 VLOG(DRIVER) << "Requested unknown cl-tuner-mode '%s'. "
318 "Defaulting to rapid" << clTuningLevelAsString.c_str();
319 }
320 }
321}
322
323} // namespace armnn_driver