xref: /aosp_15_r20/external/armnn/shim/sl/canonical/DriverOptions.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1 //
2 // Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
3 // 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 
26 using namespace android;
27 using namespace std;
28 
29 namespace armnn_driver
30 {
31 
DriverOptions(armnn::Compute computeDevice,bool fp16Enabled)32 DriverOptions::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 
DriverOptions(const std::vector<armnn::BackendId> & backends,bool fp16Enabled)53 DriverOptions::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.
DriverOptions()77 DriverOptions::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.
109     sregex_token_iterator iter(optionsAsString.begin(), optionsAsString.end(), whiteSpaceRegex, -1);
110     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     }
219     catch (const cxxopts::OptionException& e)
220     {
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, defaulting to GpuAcc.";
258         m_Backends.emplace_back("GpuAcc");
259     }
260 
261     if (!unsupportedOperationsAsString.empty())
262     {
263         std::istringstream argStream(unsupportedOperationsAsString);
264 
265         std::string s;
266         while (!argStream.eof())
267         {
268             std::getline(argStream, s, ',');
269             try
270             {
271                 unsigned int operationIdx = std::stoi(s);
272                 m_ForcedUnsupportedOperations.insert(operationIdx);
273             }
274             catch (const std::invalid_argument&)
275             {
276                 VLOG(DRIVER) << "Ignoring invalid integer argument in -u/--unsupported-operations value: " << s.c_str();
277             }
278         }
279     }
280 
281     if (!m_ClTunedParametersFile.empty())
282     {
283         // The mode is only relevant if the file path has been provided
284         if (clTunedParametersModeAsString == "UseTunedParameters")
285         {
286             m_ClTunedParametersMode = armnn::IGpuAccTunedParameters::Mode::UseTunedParameters;
287         }
288         else if (clTunedParametersModeAsString == "UpdateTunedParameters")
289         {
290             m_ClTunedParametersMode = armnn::IGpuAccTunedParameters::Mode::UpdateTunedParameters;
291         }
292         else
293         {
294             VLOG(DRIVER) << "Requested unknown cl-tuned-parameters-mode "
295                           << clTunedParametersModeAsString.c_str() << ". Defaulting to UseTunedParameters";
296         }
297 
298         if (clTuningLevelAsString == "exhaustive")
299         {
300             m_ClTuningLevel = armnn::IGpuAccTunedParameters::TuningLevel::Exhaustive;
301         }
302         else if (clTuningLevelAsString == "normal")
303         {
304             m_ClTuningLevel = armnn::IGpuAccTunedParameters::TuningLevel::Normal;
305         }
306         else if (clTuningLevelAsString == "rapid")
307         {
308             m_ClTuningLevel = armnn::IGpuAccTunedParameters::TuningLevel::Rapid;
309         }
310         else
311         {
312             VLOG(DRIVER) << "Requested unknown cl-tuner-mode '%s'. "
313                             "Defaulting to rapid" << clTuningLevelAsString.c_str();
314         }
315     }
316 }
317 
318 } // namespace armnn_driver
319