blob: 5c1337f7698c28584b943760968604f76aa8c146 [file] [log] [blame]
Jan Eilers45274902020-10-15 18:34:43 +01001//
Colm Donelane4ccada2024-03-05 14:38:53 +00002// Copyright © 2022-2024 Arm Ltd and Contributors. All rights reserved.
Jan Eilers45274902020-10-15 18:34:43 +01003// SPDX-License-Identifier: MIT
4//
5
6#include "ExecuteNetworkProgramOptions.hpp"
7#include "NetworkExecutionUtils/NetworkExecutionUtils.hpp"
Jan Eilers45274902020-10-15 18:34:43 +01008
9#include <armnn/BackendRegistry.hpp>
10#include <armnn/Exceptions.hpp>
11#include <armnn/utility/Assert.hpp>
12#include <armnn/utility/StringUtils.hpp>
13#include <armnn/Logging.hpp>
14
15#include <fmt/format.h>
16
17bool CheckOption(const cxxopts::ParseResult& result,
18 const char* option)
19{
20 // Check that the given option is valid.
21 if (option == nullptr)
22 {
23 return false;
24 }
25
26 // Check whether 'option' is provided.
27 return ((result.count(option)) ? true : false);
28}
29
30void CheckOptionDependency(const cxxopts::ParseResult& result,
31 const char* option,
32 const char* required)
33{
34 // Check that the given options are valid.
35 if (option == nullptr || required == nullptr)
36 {
Jim Flynn357add22023-04-10 23:26:40 +010037 throw cxxopts::exceptions::exception("Invalid option to check dependency for");
Jan Eilers45274902020-10-15 18:34:43 +010038 }
39
40 // Check that if 'option' is provided, 'required' is also provided.
41 if (CheckOption(result, option) && !result[option].has_default())
42 {
43 if (CheckOption(result, required) == 0 || result[required].has_default())
44 {
Jim Flynn357add22023-04-10 23:26:40 +010045 throw cxxopts::exceptions::exception(
Jan Eilers45274902020-10-15 18:34:43 +010046 std::string("Option '") + option + "' requires option '" + required + "'.");
47 }
48 }
49}
50
51void CheckOptionDependencies(const cxxopts::ParseResult& result)
52{
Jan Eilers45274902020-10-15 18:34:43 +010053 CheckOptionDependency(result, "tuning-level", "tuning-path");
54}
55
56void RemoveDuplicateDevices(std::vector<armnn::BackendId>& computeDevices)
57{
58 // Mark the duplicate devices as 'Undefined'.
59 for (auto i = computeDevices.begin(); i != computeDevices.end(); ++i)
60 {
61 for (auto j = std::next(i); j != computeDevices.end(); ++j)
62 {
63 if (*j == *i)
64 {
65 *j = armnn::Compute::Undefined;
66 }
67 }
68 }
69
70 // Remove 'Undefined' devices.
71 computeDevices.erase(std::remove(computeDevices.begin(), computeDevices.end(), armnn::Compute::Undefined),
72 computeDevices.end());
73}
74
Jan Eilersc5b84b52021-02-16 12:40:43 +000075/// Takes a vector of backend strings and returns a vector of backendIDs.
76/// Removes duplicate entries.
77/// Can handle backend strings that contain multiple backends separated by comma e.g "CpuRef,CpuAcc"
78std::vector<armnn::BackendId> GetBackendIDs(const std::vector<std::string>& backendStringsVec)
Jan Eilers45274902020-10-15 18:34:43 +010079{
80 std::vector<armnn::BackendId> backendIDs;
Jan Eilersc5b84b52021-02-16 12:40:43 +000081 for (const auto& backendStrings : backendStringsVec)
Jan Eilers45274902020-10-15 18:34:43 +010082 {
Jan Eilersc5b84b52021-02-16 12:40:43 +000083 // Each backendStrings might contain multiple backends separated by comma e.g "CpuRef,CpuAcc"
84 std::vector<std::string> backendStringVec = ParseStringList(backendStrings, ",");
85 for (const auto& b : backendStringVec)
86 {
87 backendIDs.push_back(armnn::BackendId(b));
88 }
Jan Eilers45274902020-10-15 18:34:43 +010089 }
90
91 RemoveDuplicateDevices(backendIDs);
92
93 return backendIDs;
94}
95
96/// Provides a segfault safe way to get cxxopts option values by checking if the option was defined.
97/// If the option wasn't defined it returns an empty object.
98template<typename optionType>
99optionType GetOptionValue(std::string&& optionName, const cxxopts::ParseResult& result)
100{
101 optionType out;
102 if(result.count(optionName))
103 {
104 out = result[optionName].as<optionType>();
105 }
106 return out;
107}
108
109void LogAndThrowFatal(std::string errorMessage)
110{
111 throw armnn::InvalidArgumentException (errorMessage);
112}
113
114void CheckRequiredOptions(const cxxopts::ParseResult& result)
115{
116
117 // For each option in option-group "a) Required
118 std::vector<std::string> requiredOptions{"compute",
Teresa Charlin83b42912022-07-07 14:24:59 +0100119 "model-path"
120 };
Jan Eilers45274902020-10-15 18:34:43 +0100121
122 bool requiredMissing = false;
123 for(auto const& str : requiredOptions)
124 {
125 if(!(result.count(str) > 0))
126 {
127 ARMNN_LOG(error) << fmt::format("The program option '{}' is mandatory but wasn't provided.", str);
128 requiredMissing = true;
129 }
130 }
131 if(requiredMissing)
132 {
133 throw armnn::InvalidArgumentException ("Some required arguments are missing");
134 }
135}
136
Jan Eilersf17fcd52021-07-26 22:20:00 +0100137void CheckForDeprecatedOptions(const cxxopts::ParseResult& result)
138{
Jan Eilersf17fcd52021-07-26 22:20:00 +0100139 if(result.count("armnn-tflite-delegate") > 0)
140 {
141 ARMNN_LOG(warning) << "DEPRECATED: The program option 'armnn-tflite-delegate' is deprecated and will be "
142 "removed soon. Please use the option 'tflite-executor' instead.";
143 }
Teresa Charlin83b42912022-07-07 14:24:59 +0100144 if(result.count("concurrent") > 0)
145 {
146 ARMNN_LOG(warning) << "DEPRECATED: The program option 'concurrent' is deprecated and will be "
147 "removed soon. Please use the option '\"P, thread-pool-size\"' instead.";
148 }
149 if(result.count("input-type") > 0)
150 {
151 ARMNN_LOG(warning) << "DEPRECATED: The program option 'input-type' is deprecated and will be "
152 "removed soon. The input-types are now automatically set.";
153 }
154 if(result.count("input-name") > 0)
155 {
156 ARMNN_LOG(warning) << "DEPRECATED: The program option 'input-name' is deprecated and will be "
157 "removed soon. The input-names are now automatically set.";
158 }
159 if(result.count("output-type") > 0)
160 {
161 ARMNN_LOG(warning) << "DEPRECATED: The program option 'output-type' is deprecated and will be "
162 "removed soon. The output-types are now automatically set.";
163 }
164 if(result.count("output-name") > 0)
165 {
166 ARMNN_LOG(warning) << "DEPRECATED: The program option 'output-name' is deprecated and will be "
167 "removed soon. The output-names are now automatically set.";
168 }
169 if(result.count("model-format") > 0)
170 {
171 ARMNN_LOG(warning) << "DEPRECATED: The program option 'model-format' is deprecated and will be "
172 "removed soon. The model-format is now automatically set.";
173 }
174
Jan Eilersf17fcd52021-07-26 22:20:00 +0100175}
176
Jan Eilers45274902020-10-15 18:34:43 +0100177void ProgramOptions::ValidateExecuteNetworkParams()
178{
179 m_ExNetParams.ValidateParams();
180}
181
182void ProgramOptions::ValidateRuntimeOptions()
183{
184 if (m_RuntimeOptions.m_ProfilingOptions.m_TimelineEnabled &&
185 !m_RuntimeOptions.m_ProfilingOptions.m_EnableProfiling)
186 {
187 LogAndThrowFatal("Timeline profiling requires external profiling to be turned on");
188 }
189}
190
191
192ProgramOptions::ProgramOptions() : m_CxxOptions{"ExecuteNetwork",
193 "Executes a neural network model using the provided input "
Tracy Narinec4f42342023-08-15 16:09:24 +0100194 "tensor(s). Prints the resulting output tensor(s).\n"
195 "\n"
196 "The Execution Time generated by the Arm NN Core code is a\n"
197 "more accurate measure of the time taken overall to run the model.\n"
198 "The Inference Time printed in an Execute Network run is doing\n"
199 "a crude measurement of overall time to check against a very inexact\n"
200 "upper threshold and should not be used for performance analysis.\n"}
Jan Eilers45274902020-10-15 18:34:43 +0100201{
202 try
203 {
204 // cxxopts doesn't provide a mechanism to ensure required options are given. There is a
205 // separate function CheckRequiredOptions() for that.
206 m_CxxOptions.add_options("a) Required")
207 ("c,compute",
Tracy Narinec4f42342023-08-15 16:09:24 +0100208 "Which device to run layers on by default. If a single device doesn't support all layers in the "
209 "model you can specify a second or third to fall back on. "
210 "NOTE: Multiple compute devices need to be passed as a comma separated list without whitespaces "
211 "e.g. GpuAcc,CpuAcc,CpuRef or by repeating the program option e.g. '-c CpuAcc -c CpuRef'. "
212 "Duplicates are ignored.\n"
213 "Possible choices for current machine: [ "
214 + armnn::BackendRegistryInstance().GetBackendIdsAsString() + " ]",
Jan Eilers3dda41d2020-11-11 11:44:14 +0000215 cxxopts::value<std::vector<std::string>>())
Jan Eilers45274902020-10-15 18:34:43 +0100216
Jan Eilers45274902020-10-15 18:34:43 +0100217 ("m,model-path",
Tracy Narinec4f42342023-08-15 16:09:24 +0100218 "Path to model file, e.g. .armnn, .tflite, .onnx. "
219 "DEPRECATED: .pb and .prototxt model files no longer load and are deprecated.",
220 cxxopts::value<std::string>(m_ExNetParams.m_ModelPath));
Jan Eilers45274902020-10-15 18:34:43 +0100221
Tracy Narinec4f42342023-08-15 16:09:24 +0100222 m_CxxOptions.add_options("b) Ordering")
Jan Eilers45274902020-10-15 18:34:43 +0100223 ("i,input-name",
Tracy Narinec4f42342023-08-15 16:09:24 +0100224 "Identifier of the input tensors in the network separated by a comma "
225 "and is only required for ordering input files",
Jan Eilers45274902020-10-15 18:34:43 +0100226 cxxopts::value<std::string>())
227
228 ("o,output-name",
Tracy Narinec4f42342023-08-15 16:09:24 +0100229 "Identifier of the output tensors in the network separated by a comma "
230 "and is only required for ordering output files.",
Jan Eilers45274902020-10-15 18:34:43 +0100231 cxxopts::value<std::string>());
232
Tracy Narinec4f42342023-08-15 16:09:24 +0100233 m_CxxOptions.add_options("c) General")
Jan Eilers45274902020-10-15 18:34:43 +0100234 ("b,dynamic-backends-path",
235 "Path where to load any available dynamic backend from. "
236 "If left empty (the default), dynamic backends will not be used.",
237 cxxopts::value<std::string>(m_RuntimeOptions.m_DynamicBackendsPath))
238
Teresa Charlin83b42912022-07-07 14:24:59 +0100239 ("P, thread-pool-size",
240 "Run the network using the Arm NN thread pool with the number of threads provided. ",
241 cxxopts::value<size_t>(m_ExNetParams.m_ThreadPoolSize)->default_value("0"))
242
Jan Eilers45274902020-10-15 18:34:43 +0100243 ("d,input-tensor-data",
244 "Path to files containing the input data as a flat array separated by whitespace. "
Jan Eilersf17fcd52021-07-26 22:20:00 +0100245 "Several paths can be passed by separating them with a comma if the network has multiple inputs "
246 "or you wish to run the model multiple times with different input data using the 'iterations' option. "
247 "If not specified, the network will be run with dummy data (useful for profiling).",
Jan Eilers45274902020-10-15 18:34:43 +0100248 cxxopts::value<std::string>()->default_value(""))
249
250 ("h,help", "Display usage information")
251
252 ("infer-output-shape",
253 "Infers output tensor shape from input tensor shape and validate where applicable (where supported by "
254 "parser)",
255 cxxopts::value<bool>(m_ExNetParams.m_InferOutputShape)->default_value("false")->implicit_value("true"))
256
Mike Kelly80512b02022-05-16 23:10:42 +0100257 ("allow-expanded-dims",
258 "If true will disregard dimensions with a size of 1 when validating tensor shapes. Tensor sizes must "
259 "still match. This is an Experimental parameter that is incompatible with infer-output-shape. "
260 "This parameter may be removed in a later update. ",
261 cxxopts::value<bool>(m_ExNetParams.m_AllowExpandedDims)->default_value("false")
Teresa Charlin83b42912022-07-07 14:24:59 +0100262 ->implicit_value("true"))
Mike Kelly80512b02022-05-16 23:10:42 +0100263
Teresa Charlin83b42912022-07-07 14:24:59 +0100264 ("I,iterations",
Jan Eilersf17fcd52021-07-26 22:20:00 +0100265 "Number of iterations to run the network for, default is set to 1. "
266 "If you wish to run the model with different input data for every execution you can do so by "
267 "supplying more input file paths to the 'input-tensor-data' option. "
268 "Note: The number of input files provided must be divisible by the number of inputs of the model. "
269 "e.g. Your model has 2 inputs and you supply 4 input files. If you set 'iterations' to 6 the first "
270 "run will consume the first two inputs, the second the next two and the last will begin from the "
271 "start and use the first two inputs again. "
272 "Note: If the 'concurrent' option is enabled all iterations will be run asynchronously.",
Jan Eilers45274902020-10-15 18:34:43 +0100273 cxxopts::value<size_t>(m_ExNetParams.m_Iterations)->default_value("1"))
274
275 ("l,dequantize-output",
276 "If this option is enabled, all quantized outputs will be dequantized to float. "
277 "If unset, default to not get dequantized. "
Colm Donelan3cff15a2021-10-12 15:06:19 +0100278 " (Not available when executing ArmNNTfLiteDelegate or TfliteInterpreter)",
Jan Eilers45274902020-10-15 18:34:43 +0100279 cxxopts::value<bool>(m_ExNetParams.m_DequantizeOutput)->default_value("false")->implicit_value("true"))
280
281 ("p,print-intermediate-layers",
282 "If this option is enabled, the output of every graph layer will be printed.",
283 cxxopts::value<bool>(m_ExNetParams.m_PrintIntermediate)->default_value("false")
Teresa Charlin83b42912022-07-07 14:24:59 +0100284 ->implicit_value("true"))
Jan Eilers45274902020-10-15 18:34:43 +0100285
Keith Davis15f9c682022-10-14 15:50:33 +0100286 ("F,print-intermediate-layers-to-file",
287 "If this option is enabled, the output of every graph layer will be printed within separate files.",
288 cxxopts::value<bool>(m_ExNetParams.m_PrintIntermediateOutputsToFile)->default_value("false")
289 ->implicit_value("true"))
290
Jan Eilers45274902020-10-15 18:34:43 +0100291 ("parse-unsupported",
292 "Add unsupported operators as stand-in layers (where supported by parser)",
293 cxxopts::value<bool>(m_ExNetParams.m_ParseUnsupported)->default_value("false")->implicit_value("true"))
294
Ryan OSheadfbec2d2022-03-28 10:55:48 +0100295 ("N,do-not-print-output",
Jan Eilers284b5d12021-09-07 12:46:15 +0100296 "The default behaviour of ExecuteNetwork is to print the resulting outputs on the console. "
297 "This behaviour can be changed by adding this flag to your command.",
298 cxxopts::value<bool>(m_ExNetParams.m_DontPrintOutputs)->default_value("false")->implicit_value("true"))
299
Jan Eilers45274902020-10-15 18:34:43 +0100300 ("q,quantize-input",
Mike Kellyd7ed6d42021-07-21 09:42:43 +0100301 "If this option is enabled, all float inputs will be quantized as appropriate for the model's inputs. "
Colm Donelan3cff15a2021-10-12 15:06:19 +0100302 " (Not available when executing ArmNNTfLiteDelegate or TfliteInterpreter)",
Jan Eilers45274902020-10-15 18:34:43 +0100303 cxxopts::value<bool>(m_ExNetParams.m_QuantizeInput)->default_value("false")->implicit_value("true"))
Teresa Charlin83b42912022-07-07 14:24:59 +0100304
Jan Eilers45274902020-10-15 18:34:43 +0100305 ("r,threshold-time",
306 "Threshold time is the maximum allowed time for inference measured in milliseconds. If the actual "
307 "inference time is greater than the threshold time, the test will fail. By default, no threshold "
308 "time is used.",
309 cxxopts::value<double>(m_ExNetParams.m_ThresholdTime)->default_value("0.0"))
310
311 ("s,input-tensor-shape",
312 "The shape of the input tensors in the network as a flat array of integers separated by comma."
313 "Several shapes can be passed by separating them with a colon (:).",
314 cxxopts::value<std::string>())
315
316 ("v,visualize-optimized-model",
317 "Enables built optimized model visualizer. If unset, defaults to off.",
318 cxxopts::value<bool>(m_ExNetParams.m_EnableLayerDetails)->default_value("false")
Teresa Charlin83b42912022-07-07 14:24:59 +0100319 ->implicit_value("true"))
Jan Eilers45274902020-10-15 18:34:43 +0100320
321 ("w,write-outputs-to-file",
322 "Comma-separated list of output file paths keyed with the binding-id of the output slot. "
323 "If left empty (the default), the output tensors will not be written to a file.",
324 cxxopts::value<std::string>())
325
326 ("x,subgraph-number",
Colm Donelan3cff15a2021-10-12 15:06:19 +0100327 "Id of the subgraph to be executed. Defaults to 0."
328 " (Not available when executing ArmNNTfLiteDelegate or TfliteInterpreter)",
Jan Eilers45274902020-10-15 18:34:43 +0100329 cxxopts::value<size_t>(m_ExNetParams.m_SubgraphId)->default_value("0"))
330
Finn Williamsf806c4d2021-02-22 15:13:12 +0000331 ("T,tflite-executor",
Tracy Narinec4f42342023-08-15 16:09:24 +0100332 "Set the executor for the tflite model: parser, delegate, opaquedelegate, tflite.\n"
333 "parser is the ArmNNTfLiteParser, \n"
334 "delegate is the ArmNNTfLiteDelegate, \n"
335 "opaquedelegate is the ArmNNTfLiteOpaqueDelegate, \n"
336 "tflite is the TfliteInterpreter (Bypasses Arm NN and runs model in Tensorflow Lite directly)\n",
Finn Williamsf806c4d2021-02-22 15:13:12 +0000337 cxxopts::value<std::string>()->default_value("parser"))
338
Teresa Charlin83b42912022-07-07 14:24:59 +0100339 ("C, compare-output",
Colm Doneland0472622023-03-06 12:34:54 +0000340 "Perform a per byte root mean square error calculation of the inference output with an output"
Colm Donelan0dfb2652023-06-22 10:19:17 +0100341 " file(s) that has been previously produced by running a network through ExecuteNetwork."
342 " See --write-outputs-to-file to produce an output file(s) for an execution.",
Teresa Charlin83b42912022-07-07 14:24:59 +0100343 cxxopts::value<std::string>(m_ExNetParams.m_ComparisonFile))
344
345 ("B, compare-output-with-backend",
Colm Doneland0472622023-03-06 12:34:54 +0000346 "Perform a per byte root mean square error calculation of the output of the inference with a"
347 " different backend.",
Teresa Charlin83b42912022-07-07 14:24:59 +0100348 cxxopts::value<std::vector<std::string>>())
349
350 ("A, compare-with-tflite",
Colm Doneland0472622023-03-06 12:34:54 +0000351 "Perform an per byte root mean square error calculation of the output of the inference with"
352 " the tflite ref model.",
Teresa Charlin83b42912022-07-07 14:24:59 +0100353 cxxopts::value<bool>(m_ExNetParams.m_CompareWithTflite)->default_value("false")
354 ->implicit_value("true"));
Jan Eilers45274902020-10-15 18:34:43 +0100355
Tracy Narinec4f42342023-08-15 16:09:24 +0100356 m_CxxOptions.add_options("d) Optimization")
Jan Eilers45274902020-10-15 18:34:43 +0100357 ("enable-fast-math",
Tracy Narinec4f42342023-08-15 16:09:24 +0100358 "Enables fast_math options in backends that support it. Using the fast_math flag "
359 "can lead to performance improvements but may result in reduced or different precision. "
360 "Supported on CpuAcc and GpuAcc only.",
Jan Eilers45274902020-10-15 18:34:43 +0100361 cxxopts::value<bool>(m_ExNetParams.m_EnableFastMath)->default_value("false")->implicit_value("true"))
362
Matthew Sloyan0a7dc6b2021-02-10 16:50:53 +0000363 ("number-of-threads",
364 "Assign the number of threads used by the CpuAcc backend. "
365 "Input value must be between 1 and 64. "
366 "Default is set to 0 (Backend will decide number of threads to use).",
367 cxxopts::value<unsigned int>(m_ExNetParams.m_NumberOfThreads)->default_value("0"))
368
Matthew Sloyan42432112021-01-08 10:30:51 +0000369 ("save-cached-network",
Tracy Narinec4f42342023-08-15 16:09:24 +0100370 "Enables saving of the cached network to a file given with the cached-network-filepath option.\n"
371 "Supported on GpuAcc only.\n"
Matthew Sloyan42432112021-01-08 10:30:51 +0000372 "See also --cached-network-filepath",
373 cxxopts::value<bool>(m_ExNetParams.m_SaveCachedNetwork)
Teresa Charlin83b42912022-07-07 14:24:59 +0100374 ->default_value("false")->implicit_value("true"))
Matthew Sloyan42432112021-01-08 10:30:51 +0000375
376 ("cached-network-filepath",
Matthew Sloyan9d7a3322021-01-12 16:19:43 +0000377 "If non-empty, the given file will be used to load/save the cached network. "
378 "If save-cached-network is given then the cached network will be saved to the given file. "
379 "To save the cached network a file must already exist. "
380 "If save-cached-network is not given then the cached network will be loaded from the given file. "
Tracy Narinec4f42342023-08-15 16:09:24 +0100381 "This will remove initial compilation time of kernels and speed up the first execution.\n"
382 "Supported on GpuAcc only.",
Matthew Sloyan42432112021-01-08 10:30:51 +0000383 cxxopts::value<std::string>(m_ExNetParams.m_CachedNetworkFilePath)->default_value(""))
384
Jan Eilers45274902020-10-15 18:34:43 +0100385 ("fp16-turbo-mode",
386 "If this option is enabled, FP32 layers, "
Ryan OSheab4c49342023-07-25 14:28:27 +0100387 "weights and biases will be converted to FP16 where the backend supports it. "
388 "If the first preferred backend does not have FP16 support, this option will be disabled. "
Tracy Narinec4f42342023-08-15 16:09:24 +0100389 "If the value of converted FP16 is infinity, round to the closest finite FP16 value."
390 "Supported on CpuAcc and GpuAcc only.",
Jan Eilers45274902020-10-15 18:34:43 +0100391 cxxopts::value<bool>(m_ExNetParams.m_EnableFp16TurboMode)
Teresa Charlin83b42912022-07-07 14:24:59 +0100392 ->default_value("false")->implicit_value("true"))
Jan Eilers45274902020-10-15 18:34:43 +0100393
394 ("tuning-level",
395 "Sets the tuning level which enables a tuning run which will update/create a tuning file. "
396 "Available options are: 1 (Rapid), 2 (Normal), 3 (Exhaustive). "
397 "Requires tuning-path to be set, default is set to 0 (No tuning run)",
398 cxxopts::value<int>(m_ExNetParams.m_TuningLevel)->default_value("0"))
399
400 ("tuning-path",
401 "Path to tuning file. Enables use of CL tuning",
Finn Williams40646322021-02-11 16:16:42 +0000402 cxxopts::value<std::string>(m_ExNetParams.m_TuningPath))
403
404 ("MLGOTuningFilePath",
Tracy Narinec4f42342023-08-15 16:09:24 +0100405 "Path to tuning file. Enables use of CL MLGO tuning.\n"
406 "Supported on GpuAcc only.",
Teresa Charlin83b42912022-07-07 14:24:59 +0100407 cxxopts::value<std::string>(m_ExNetParams.m_MLGOTuningFilePath))
Ryan OSheadfbec2d2022-03-28 10:55:48 +0100408
409 ("R, reuse-buffers",
Teresa Charlin83b42912022-07-07 14:24:59 +0100410 "If enabled then the IO buffers will be reused for each inference",
411 cxxopts::value<bool>(m_ExNetParams.m_ReuseBuffers)->default_value("false")->implicit_value("true"));
Jan Eilers45274902020-10-15 18:34:43 +0100412
Tracy Narinec4f42342023-08-15 16:09:24 +0100413 m_CxxOptions.add_options("e) Profiling")
Jan Eilers45274902020-10-15 18:34:43 +0100414 ("a,enable-external-profiling",
415 "If enabled external profiling will be switched on",
416 cxxopts::value<bool>(m_RuntimeOptions.m_ProfilingOptions.m_EnableProfiling)
417 ->default_value("false")->implicit_value("true"))
418
Jan Eilers45274902020-10-15 18:34:43 +0100419 ("g,file-only-external-profiling",
420 "If enabled then the 'file-only' test mode of external profiling will be enabled",
421 cxxopts::value<bool>(m_RuntimeOptions.m_ProfilingOptions.m_FileOnly)
Teresa Charlin83b42912022-07-07 14:24:59 +0100422 ->default_value("false")->implicit_value("true"))
Jan Eilers45274902020-10-15 18:34:43 +0100423
424 ("file-format",
425 "If profiling is enabled specifies the output file format",
426 cxxopts::value<std::string>(m_RuntimeOptions.m_ProfilingOptions.m_FileFormat)->default_value("binary"))
427
428 ("j,outgoing-capture-file",
429 "If specified the outgoing external profiling packets will be captured in this binary file",
430 cxxopts::value<std::string>(m_RuntimeOptions.m_ProfilingOptions.m_OutgoingCaptureFile))
431
432 ("k,incoming-capture-file",
433 "If specified the incoming external profiling packets will be captured in this binary file",
434 cxxopts::value<std::string>(m_RuntimeOptions.m_ProfilingOptions.m_IncomingCaptureFile))
435
436 ("timeline-profiling",
437 "If enabled timeline profiling will be switched on, requires external profiling",
438 cxxopts::value<bool>(m_RuntimeOptions.m_ProfilingOptions.m_TimelineEnabled)
Teresa Charlin83b42912022-07-07 14:24:59 +0100439 ->default_value("false")->implicit_value("true"))
Jan Eilers45274902020-10-15 18:34:43 +0100440
441 ("u,counter-capture-period",
442 "If profiling is enabled in 'file-only' mode this is the capture period that will be used in the test",
Keith Davisf4874862021-08-09 16:49:18 +0100443 cxxopts::value<uint32_t>(m_RuntimeOptions.m_ProfilingOptions.m_CapturePeriod)->default_value("150"))
444
Tracy Narinec4f42342023-08-15 16:09:24 +0100445 ("e,event-based-profiling",
446 "Enables built in profiler.",
447 cxxopts::value<bool>(m_ExNetParams.m_EnableProfiling)->default_value("false")->implicit_value("true"))
448
Keith Davisf4874862021-08-09 16:49:18 +0100449 ("output-network-details",
Tracy Narinec4f42342023-08-15 16:09:24 +0100450 "Outputs layer tensor infos and descriptors to std out along with profiling events.",
Keith Davisf4874862021-08-09 16:49:18 +0100451 cxxopts::value<bool>(m_ExNetParams.m_OutputDetailsToStdOut)->default_value("false")
Teresa Charlin83b42912022-07-07 14:24:59 +0100452 ->implicit_value("true"))
453
Keith Davis4914d0c2021-08-18 17:14:05 +0100454 ("output-network-details-only",
Tracy Narinec4f42342023-08-15 16:09:24 +0100455 "Outputs layer tensor infos and descriptors to std out without profiling events.",
Keith Davis4914d0c2021-08-18 17:14:05 +0100456 cxxopts::value<bool>(m_ExNetParams.m_OutputDetailsOnlyToStdOut)->default_value("false")
Teresa Charlin83b42912022-07-07 14:24:59 +0100457 ->implicit_value("true"))
Keith Davis4914d0c2021-08-18 17:14:05 +0100458
Jim Flynn15425812022-02-15 16:53:13 +0000459 ("import-inputs-if-aligned",
Tracy Narinec4f42342023-08-15 16:09:24 +0100460 "In & Out tensors will be imported per inference if the memory alignment allows.",
Jim Flynn15425812022-02-15 16:53:13 +0000461 cxxopts::value<bool>(m_ExNetParams.m_ImportInputsIfAligned)->default_value("false")
462 ->implicit_value("true"));
Tracy Narinec4f42342023-08-15 16:09:24 +0100463
464 m_CxxOptions.add_options("f) Deprecated or unused")
465 ("f,model-format",
466 "armnn-binary, onnx-binary, onnx-text, tflite-binary"
467 "DEPRECATED: The program option 'model-format' is deprecated and will be "
468 "removed soon. The model-format is now automatically set.",
469 cxxopts::value<std::string>())
470
471 ("n,concurrent",
472 "This option is for Arm NN internal asynchronous testing purposes. "
473 "False by default. If set to true will use std::launch::async or the Arm NN thread pool, "
474 "if 'thread-pool-size' is greater than 0, for asynchronous execution."
475 "DEPRECATED: The program option 'concurrent' is deprecated and will be "
476 "removed soon. Please use the option '\"P, thread-pool-size\"' instead.",
477 cxxopts::value<bool>(m_ExNetParams.m_Concurrent)->default_value("false")->implicit_value("true"))
478
479 ("y,input-type",
480 "The type of the input tensors in the network separated by comma. "
481 "If unset, defaults to \"float\" for all defined inputs. "
482 "Accepted values (float, int, qasymms8 or qasymmu8)."
483 "DEPRECATED: The program option 'input-type' is deprecated and will be "
484 "removed soon. The input-types are now automatically set.",
485 cxxopts::value<std::string>())
486
487 ("z,output-type",
488 "The type of the output tensors in the network separated by comma. "
489 "If unset, defaults to \"float\" for all defined outputs. "
490 "Accepted values (float, int, qasymms8 or qasymmu8)."
491 "DEPRECATED: The program option 'output-type' is deprecated and will be "
492 "removed soon. The output-types are now automatically set.",
493 cxxopts::value<std::string>())
494
495 ("bf16-turbo-mode",
496 "This option is no longer being used. In order to use bf16 please set enable-fast-math "
497 "to true",
498 cxxopts::value<bool>(m_ExNetParams.m_EnableBf16TurboMode)
499 ->default_value("false")->implicit_value("true"));
Jan Eilers45274902020-10-15 18:34:43 +0100500 }
501 catch (const std::exception& e)
502 {
503 ARMNN_ASSERT_MSG(false, "Caught unexpected exception");
504 ARMNN_LOG(fatal) << "Fatal internal error: " << e.what();
505 exit(EXIT_FAILURE);
506 }
507}
508
509ProgramOptions::ProgramOptions(int ac, const char* av[]): ProgramOptions()
510{
511 ParseOptions(ac, av);
512}
513
514void ProgramOptions::ParseOptions(int ac, const char* av[])
515{
516 // Parses the command-line.
517 m_CxxResult = m_CxxOptions.parse(ac, av);
518
519 if (m_CxxResult.count("help") || ac <= 1)
520 {
521 std::cout << m_CxxOptions.help() << std::endl;
522 exit(EXIT_SUCCESS);
523 }
524
525 CheckRequiredOptions(m_CxxResult);
526 CheckOptionDependencies(m_CxxResult);
Jan Eilersf17fcd52021-07-26 22:20:00 +0100527 CheckForDeprecatedOptions(m_CxxResult);
Jan Eilers45274902020-10-15 18:34:43 +0100528
Teresa Charlin83b42912022-07-07 14:24:59 +0100529 if ((m_ExNetParams.m_OutputDetailsToStdOut ||
530 m_ExNetParams.m_OutputDetailsOnlyToStdOut) &&
531 !m_ExNetParams.m_EnableProfiling)
532 {
Jim Flynn357add22023-04-10 23:26:40 +0100533 throw cxxopts::exceptions::exception("You must enable profiling if you would like to output layer details");
Teresa Charlin83b42912022-07-07 14:24:59 +0100534 }
535
Jan Eilers45274902020-10-15 18:34:43 +0100536 // Some options can't be assigned directly because they need some post-processing:
Jan Eilers3dda41d2020-11-11 11:44:14 +0000537 auto computeDevices = GetOptionValue<std::vector<std::string>>("compute", m_CxxResult);
538 m_ExNetParams.m_ComputeDevices = GetBackendIDs(computeDevices);
Jan Eilers45274902020-10-15 18:34:43 +0100539 m_ExNetParams.m_InputNames =
540 ParseStringList(GetOptionValue<std::string>("input-name", m_CxxResult), ",");
541 m_ExNetParams.m_InputTensorDataFilePaths =
542 ParseStringList(GetOptionValue<std::string>("input-tensor-data", m_CxxResult), ",");
543 m_ExNetParams.m_OutputNames =
544 ParseStringList(GetOptionValue<std::string>("output-name", m_CxxResult), ",");
Jan Eilers45274902020-10-15 18:34:43 +0100545 m_ExNetParams.m_OutputTensorFiles =
546 ParseStringList(GetOptionValue<std::string>("write-outputs-to-file", m_CxxResult), ",");
Teresa Charlin83b42912022-07-07 14:24:59 +0100547 m_ExNetParams.m_GenerateTensorData = m_ExNetParams.m_InputTensorDataFilePaths.empty();
Francis Murtaghbf18a262020-10-27 15:20:40 +0000548 m_ExNetParams.m_DynamicBackendsPath = m_RuntimeOptions.m_DynamicBackendsPath;
Jan Eilers45274902020-10-15 18:34:43 +0100549
Sadik Armagan8c7a28b2021-04-01 17:27:21 +0100550 m_RuntimeOptions.m_EnableGpuProfiling = m_ExNetParams.m_EnableProfiling;
Finn Williamsf806c4d2021-02-22 15:13:12 +0000551
552 std::string tfliteExecutor = GetOptionValue<std::string>("tflite-executor", m_CxxResult);
553
554 if (tfliteExecutor.size() == 0 || tfliteExecutor == "parser")
555 {
556 m_ExNetParams.m_TfLiteExecutor = ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteParser;
557 }
Narumol Prangnawarat46e574e2023-05-05 16:39:05 +0100558 else if (tfliteExecutor == "opaquedelegate")
559 {
560 m_ExNetParams.m_TfLiteExecutor = ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteOpaqueDelegate;
561 }
Finn Williamsf806c4d2021-02-22 15:13:12 +0000562 else if (tfliteExecutor == "delegate")
563 {
564 m_ExNetParams.m_TfLiteExecutor = ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteDelegate;
565 }
566 else if (tfliteExecutor == "tflite")
567 {
568 m_ExNetParams.m_TfLiteExecutor = ExecuteNetworkParams::TfLiteExecutor::TfliteInterpreter;
569 }
570 else
571 {
572 ARMNN_LOG(info) << fmt::format("Invalid tflite-executor option '{}'.", tfliteExecutor);
573 throw armnn::InvalidArgumentException ("Invalid tflite-executor option");
574 }
575
Jan Eilersf17fcd52021-07-26 22:20:00 +0100576 // For backwards compatibility when deprecated options are used
Finn Williamsf806c4d2021-02-22 15:13:12 +0000577 if (m_ExNetParams.m_EnableDelegate)
578 {
579 m_ExNetParams.m_TfLiteExecutor = ExecuteNetworkParams::TfLiteExecutor::ArmNNTfLiteDelegate;
Jan Eilersf17fcd52021-07-26 22:20:00 +0100580 }
Finn Williams452c5802022-06-20 13:48:20 +0100581
Nikhil Raj Armf4ccb1f2022-07-05 09:29:18 +0000582 // Set concurrent to true if the user expects to run inferences asynchronously
Teresa Charlin83b42912022-07-07 14:24:59 +0100583 if (m_ExNetParams.m_Concurrent)
584 {
585 m_ExNetParams.m_ThreadPoolSize = 1;
586 }
587
Colm Donelane4ccada2024-03-05 14:38:53 +0000588 // There's an odd combination of parameters to be handled here. It appears that setting m_ThreadPoolSize greater
589 // than 0 implies using the asynchronous mode. However, TfLite executor does not support an asynchronous mode of
590 // execution
Jan Eilersf17fcd52021-07-26 22:20:00 +0100591 if (m_ExNetParams.m_ThreadPoolSize > 0)
Kevin Mayb4b3ac92021-05-21 16:42:21 +0100592 {
593 m_ExNetParams.m_Concurrent = true;
594 }
Colm Donelane4ccada2024-03-05 14:38:53 +0000595 if (m_ExNetParams.m_Concurrent &&
596 m_ExNetParams.m_TfLiteExecutor == ExecuteNetworkParams::TfLiteExecutor::TfliteInterpreter)
597 {
598 ARMNN_LOG(info) << "The TfLite runtime does not support an asynchronous mode of execution. Parameters "
599 "\"n,concurrent\" or \"P, thread-pool-size\" will be ignored.";
600 }
Finn Williamsf806c4d2021-02-22 15:13:12 +0000601
Jan Eilers45274902020-10-15 18:34:43 +0100602 // Parse input tensor shape from the string we got from the command-line.
603 std::vector<std::string> inputTensorShapesVector =
604 ParseStringList(GetOptionValue<std::string>("input-tensor-shape", m_CxxResult), ":");
605
606 if (!inputTensorShapesVector.empty())
607 {
608 m_ExNetParams.m_InputTensorShapes.reserve(inputTensorShapesVector.size());
609
610 for(const std::string& shape : inputTensorShapesVector)
611 {
612 std::stringstream ss(shape);
613 std::vector<unsigned int> dims = ParseArray(ss);
614
615 m_ExNetParams.m_InputTensorShapes.push_back(
Teresa Charlin83b42912022-07-07 14:24:59 +0100616 armnn::TensorShape{static_cast<unsigned int>(dims.size()), dims.data()});
Jan Eilers45274902020-10-15 18:34:43 +0100617 }
618 }
619
620 // We have to validate ExecuteNetworkParams first so that the tuning path and level is validated
621 ValidateExecuteNetworkParams();
622
623 // Parse CL tuning parameters to runtime options
624 if (!m_ExNetParams.m_TuningPath.empty())
625 {
626 m_RuntimeOptions.m_BackendOptions.emplace_back(
627 armnn::BackendOptions
628 {
629 "GpuAcc",
630 {
631 {"TuningLevel", m_ExNetParams.m_TuningLevel},
632 {"TuningFile", m_ExNetParams.m_TuningPath.c_str()},
Finn Williams40646322021-02-11 16:16:42 +0000633 {"KernelProfilingEnabled", m_ExNetParams.m_EnableProfiling},
634 {"MLGOTuningFilePath", m_ExNetParams.m_MLGOTuningFilePath}
Jan Eilers45274902020-10-15 18:34:43 +0100635 }
636 }
637 );
638 }
639
640 ValidateRuntimeOptions();
Teresa Charlin83b42912022-07-07 14:24:59 +0100641
642 auto comparisonComputDevices = GetOptionValue<std::vector<std::string>>("compare-output-with-backend", m_CxxResult);
643
644 if (!comparisonComputDevices.empty())
645 {
646 m_ExNetParams.m_ComparisonComputeDevices = GetBackendIDs(comparisonComputDevices);
647 }
Jan Eilers45274902020-10-15 18:34:43 +0100648}