ArmNN
 21.11
ExecuteNetworkParams.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
7 
9 #include <InferenceModel.hpp>
10 #include <armnn/Logging.hpp>
11 
12 #include <fmt/format.h>
13 
14 bool IsModelBinary(const std::string& modelFormat)
15 {
16  // Parse model binary flag from the model-format string we got from the command-line
17  if (modelFormat.find("binary") != std::string::npos)
18  {
19  return true;
20  }
21  else if (modelFormat.find("txt") != std::string::npos || modelFormat.find("text") != std::string::npos)
22  {
23  return false;
24  }
25  else
26  {
27  throw armnn::InvalidArgumentException(fmt::format("Unknown model format: '{}'. "
28  "Please include 'binary' or 'text'",
29  modelFormat));
30  }
31 }
32 
33 void CheckModelFormat(const std::string& modelFormat)
34 {
35  // Forward to implementation based on the parser type
36  if (modelFormat.find("armnn") != std::string::npos)
37  {
38 #if defined(ARMNN_SERIALIZER)
39 #else
40  throw armnn::InvalidArgumentException("Can't run model in armnn format without a "
41  "built with serialization support.");
42 #endif
43  }
44  else if (modelFormat.find("onnx") != std::string::npos)
45  {
46 #if defined(ARMNN_ONNX_PARSER)
47 #else
48  throw armnn::InvalidArgumentException("Can't run model in onnx format without a "
49  "built with Onnx parser support.");
50 #endif
51  }
52  else if (modelFormat.find("tflite") != std::string::npos)
53  {
54 #if defined(ARMNN_TF_LITE_PARSER)
55  if (!IsModelBinary(modelFormat))
56  {
57  throw armnn::InvalidArgumentException(fmt::format("Unknown model format: '{}'. Only 'binary' "
58  "format supported for tflite files",
59  modelFormat));
60  }
61 #elif defined(ARMNN_TFLITE_DELEGATE)
62 #else
63  throw armnn::InvalidArgumentException("Can't run model in tflite format without a "
64  "built with Tensorflow Lite parser support.");
65 #endif
66  }
67  else
68  {
69  throw armnn::InvalidArgumentException(fmt::format("Unknown model format: '{}'. "
70  "Please include 'tflite' or 'onnx'",
71  modelFormat));
72  }
73 }
74 
75 void CheckClTuningParameter(const int& tuningLevel,
76  const std::string& tuningPath,
77  const std::vector<armnn::BackendId> computeDevices)
78 {
79  if (!tuningPath.empty())
80  {
81  if (tuningLevel == 0)
82  {
83  ARMNN_LOG(info) << "Using cl tuning file: " << tuningPath << "\n";
84  if (!ValidatePath(tuningPath, true))
85  {
86  throw armnn::InvalidArgumentException("The tuning path is not valid");
87  }
88  }
89  else if ((1 <= tuningLevel) && (tuningLevel <= 3))
90  {
91  ARMNN_LOG(info) << "Starting execution to generate a cl tuning file: " << tuningPath << "\n"
92  << "Tuning level in use: " << tuningLevel << "\n";
93  }
94  else if ((0 < tuningLevel) || (tuningLevel > 3))
95  {
96  throw armnn::InvalidArgumentException(fmt::format("The tuning level {} is not valid.",
97  tuningLevel));
98  }
99 
100  // Ensure that a GpuAcc is enabled. Otherwise no tuning data are used or genereted
101  // Only warn if it's not enabled
102  auto it = std::find(computeDevices.begin(), computeDevices.end(), "GpuAcc");
103  if (it == computeDevices.end())
104  {
105  ARMNN_LOG(warning) << "To use Cl Tuning the compute device GpuAcc needs to be active.";
106  }
107  }
108 
109 }
110 
112 {
113  if (m_DynamicBackendsPath == "")
114  {
115  // Check compute devices are valid unless they are dynamically loaded at runtime
116  std::string invalidBackends;
117  if (!CheckRequestedBackendsAreValid(m_ComputeDevices, armnn::Optional<std::string&>(invalidBackends)))
118  {
119  ARMNN_LOG(fatal) << "The list of preferred devices contains invalid backend IDs: "
120  << invalidBackends;
121  }
122  }
123 
125 
127  {
128  throw armnn::InvalidArgumentException("BFloat16 and Float16 turbo mode cannot be "
129  "enabled at the same time.");
130  }
131 
133 
135 
136  // Check input tensor shapes
137  if ((m_InputTensorShapes.size() != 0) &&
138  (m_InputTensorShapes.size() != m_InputNames.size()))
139  {
140  throw armnn::InvalidArgumentException("input-name and input-tensor-shape must have "
141  "the same amount of elements. ");
142  }
143 
144  if (m_InputTensorDataFilePaths.size() != 0)
145  {
147  {
148  throw armnn::InvalidArgumentException("One or more input data file paths are not valid.");
149  }
150 
151  if (m_InputTensorDataFilePaths.size() < m_InputNames.size())
152  {
154  fmt::format("According to the number of input names the user provided the network has {} "
155  "inputs. But only {} input-tensor-data file paths were provided. Each input of the "
156  "model is expected to be stored in it's own file.",
157  m_InputNames.size(),
159  }
160  else if (m_InputTensorDataFilePaths.size() % m_InputNames.size() != 0)
161  {
163  fmt::format("According to the number of input names the user provided the network has {} "
164  "inputs. The user specified {} input-tensor-data file paths which is not "
165  "divisible by the number of inputs.",
166  m_InputNames.size(),
168  }
169  }
170 
171  if (m_InputTypes.size() == 0)
172  {
173  //Defaults the value of all inputs to "float"
174  m_InputTypes.assign(m_InputNames.size(), "float");
175  }
176  else if ((m_InputTypes.size() != 0) &&
177  (m_InputTypes.size() != m_InputNames.size()))
178  {
179  throw armnn::InvalidArgumentException("input-name and input-type must have the same amount of elements.");
180  }
181 
182  // Make sure that the number of input files given is divisible by the number of inputs of the model
183  if (!(m_InputTensorDataFilePaths.size() % m_InputNames.size() == 0))
184  {
186  fmt::format("The number of input-tensor-data files ({0}) is not divisible by the "
187  "number of inputs ({1} according to the number of input names).",
189  m_InputNames.size()));
190  }
191 
192  if (m_OutputTypes.size() == 0)
193  {
194  //Defaults the value of all outputs to "float"
195  m_OutputTypes.assign(m_OutputNames.size(), "float");
196  }
197  else if ((m_OutputTypes.size() != 0) &&
198  (m_OutputTypes.size() != m_OutputNames.size()))
199  {
200  throw armnn::InvalidArgumentException("output-name and output-type must have the same amount of elements.");
201  }
202 
203  // Make sure that the number of output files given is equal to the number of outputs of the model
204  // or equal to the number of outputs of the model multiplied with the number of iterations
205  if (!m_OutputTensorFiles.empty())
206  {
207  if ((m_OutputTensorFiles.size() != m_OutputNames.size()) &&
208  (m_OutputTensorFiles.size() != m_OutputNames.size() * m_Iterations))
209  {
210  std::stringstream errmsg;
211  auto numOutputs = m_OutputNames.size();
213  fmt::format("The user provided {0} output-tensor files. The only allowed number of output-tensor "
214  "files is the number of outputs of the network ({1} according to the number of "
215  "output names) or the number of outputs multiplied with the number of times the "
216  "network should be executed (NumOutputs * NumIterations = {1} * {2} = {3}).",
217  m_OutputTensorFiles.size(),
218  numOutputs,
219  m_Iterations,
220  numOutputs*m_Iterations));
221  }
222  }
223 
224  // Check that threshold time is not less than zero
225  if (m_ThresholdTime < 0)
226  {
227  throw armnn::InvalidArgumentException("Threshold time supplied as a command line argument is less than zero.");
228  }
229 
230  // Warn if ExecuteNetwork will generate dummy input data
232  {
233  ARMNN_LOG(warning) << "No input files provided, input tensors will be filled with 0s.";
234  }
235 }
236 
237 #if defined(ARMNN_TFLITE_DELEGATE)
238 /**
239  * A utility method that populates a DelegateOptions object from this ExecuteNetworkParams.
240  *
241  * @return a populated armnnDelegate::DelegateOptions object.
242  */
243 armnnDelegate::DelegateOptions ExecuteNetworkParams::ToDelegateOptions() const
244 {
247  delegateOptions.SetGpuProfilingState(m_EnableProfiling);
248 
249  armnn::OptimizerOptions options;
252  options.m_Debug = m_PrintIntermediate;
256  if (m_InferOutputShape)
257  {
259  }
260 
261  armnn::BackendOptions gpuAcc("GpuAcc",
262  {
263  { "FastMathEnabled", m_EnableFastMath },
264  { "SaveCachedNetwork", m_SaveCachedNetwork },
265  { "CachedNetworkFilePath", m_CachedNetworkFilePath },
266  { "TuningLevel", m_TuningLevel},
267  { "TuningFile", m_TuningPath.c_str()},
268  { "KernelProfilingEnabled", m_EnableProfiling},
269  { "MLGOTuningFilePath", m_MLGOTuningFilePath}
270  });
271 
272  armnn::BackendOptions cpuAcc("CpuAcc",
273  {
274  { "FastMathEnabled", m_EnableFastMath },
275  { "NumberOfThreads", m_NumberOfThreads }
276  });
277  options.m_ModelOptions.push_back(gpuAcc);
278  options.m_ModelOptions.push_back(cpuAcc);
279 
280  delegateOptions.SetOptimizerOptions(options);
281 
282  // If v,visualize-optimized-model is enabled then construct a file name for the dot file.
284  {
285  fs::path filename = m_ModelPath;
286  filename.replace_extension("dot");
287  delegateOptions.SetSerializeToDot(filename);
288  }
289 
290  return delegateOptions;
291 }
292 #endif
std::vector< std::string > m_InputTypes
ModelOptions m_ModelOptions
Definition: INetwork.hpp:189
ShapeInferenceMethod m_shapeInferenceMethod
Definition: INetwork.hpp:183
std::vector< TensorShapePtr > m_InputTensorShapes
void SetSerializeToDot(const std::string &serializeToDotFile)
#define ARMNN_LOG(severity)
Definition: Logging.hpp:202
bool m_ReduceFp32ToBf16
Reduces all Fp32 operators in the model to Bf16 for faster processing.
Definition: INetwork.hpp:180
std::vector< std::string > m_OutputNames
std::vector< std::string > m_OutputTensorFiles
void CheckClTuningParameter(const int &tuningLevel, const std::string &tuningPath, const std::vector< armnn::BackendId > computeDevices)
std::vector< armnn::BackendId > m_ComputeDevices
bool m_ReduceFp32ToFp16
Reduces all Fp32 operators in the model to Fp16 for faster processing.
Definition: INetwork.hpp:170
std::vector< std::string > m_OutputTypes
std::vector< std::string > m_InputNames
Validate all output shapes.
void CheckModelFormat(const std::string &modelFormat)
bool ValidatePaths(const std::vector< std::string > &fileVec, const bool expectFile)
Verifies if a given vector of strings are valid paths.
ArmNN performs an optimization on each model/network before it gets loaded for execution.
Definition: INetwork.hpp:120
std::vector< std::string > m_InputTensorDataFilePaths
bool IsModelBinary(const std::string &modelFormat)
Struct for the users to pass backend specific options.
void SetDynamicBackendsPath(const std::string &dynamicBackendsPath)
Infer missing output shapes and validate all output shapes.
void SetOptimizerOptions(const armnn::OptimizerOptions &optimizerOptions)
void SetGpuProfilingState(bool gpuProfilingState)
bool ValidatePath(const std::string &file, const bool expectFile)
Verifies if the given string is a valid path.
void SetInternalProfilingParams(bool internalProfilingState, const armnn::ProfilingDetailsMethod &internalProfilingDetail)