1 //
2 // Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "ExecuteNetworkParams.hpp"
7
8 #include "NetworkExecutionUtils/NetworkExecutionUtils.hpp"
9 #include <armnn/Logging.hpp>
10
11 #include <fmt/format.h>
12 #include <armnnUtils/Filesystem.hpp>
13
CheckClTuningParameter(const int & tuningLevel,const std::string & tuningPath,const std::vector<armnn::BackendId> computeDevices)14 void CheckClTuningParameter(const int& tuningLevel,
15 const std::string& tuningPath,
16 const std::vector<armnn::BackendId> computeDevices)
17 {
18 if (!tuningPath.empty())
19 {
20 if (tuningLevel == 0)
21 {
22 ARMNN_LOG(info) << "Using cl tuning file: " << tuningPath << "\n";
23 if (!ValidatePath(tuningPath, true))
24 {
25 throw armnn::InvalidArgumentException("The tuning path is not valid");
26 }
27 }
28 else if ((1 <= tuningLevel) && (tuningLevel <= 3))
29 {
30 ARMNN_LOG(info) << "Starting execution to generate a cl tuning file: " << tuningPath << "\n"
31 << "Tuning level in use: " << tuningLevel << "\n";
32 }
33 else if ((0 < tuningLevel) || (tuningLevel > 3))
34 {
35 throw armnn::InvalidArgumentException(fmt::format("The tuning level {} is not valid.",
36 tuningLevel));
37 }
38
39 // Ensure that a GpuAcc is enabled. Otherwise no tuning data are used or genereted
40 // Only warn if it's not enabled
41 auto it = std::find(computeDevices.begin(), computeDevices.end(), "GpuAcc");
42 if (it == computeDevices.end())
43 {
44 ARMNN_LOG(warning) << "To use Cl Tuning the compute device GpuAcc needs to be active.";
45 }
46 }
47 }
48
ValidateParams()49 void ExecuteNetworkParams::ValidateParams()
50 {
51 if (m_DynamicBackendsPath == "")
52 {
53 // Check compute devices are valid unless they are dynamically loaded at runtime
54 std::string invalidBackends;
55 if (!CheckRequestedBackendsAreValid(m_ComputeDevices, armnn::Optional<std::string&>(invalidBackends)))
56 {
57 ARMNN_LOG(fatal) << "The list of preferred devices contains invalid backend IDs: "
58 << invalidBackends;
59 }
60 }
61 CheckClTuningParameter(m_TuningLevel, m_TuningPath, m_ComputeDevices);
62
63 if (m_EnableBf16TurboMode && !m_EnableFastMath)
64 {
65 throw armnn::InvalidArgumentException("To use BF16 please use --enable-fast-math. ");
66 }
67
68 // Check input tensor shapes
69 if ((m_InputTensorShapes.size() != 0) &&
70 (m_InputTensorShapes.size() != m_InputNames.size()))
71 {
72 throw armnn::InvalidArgumentException("input-name and input-tensor-shape must have "
73 "the same amount of elements. ");
74 }
75
76 if (m_InputTensorDataFilePaths.size() != 0)
77 {
78 if (!ValidatePaths(m_InputTensorDataFilePaths, true))
79 {
80 throw armnn::InvalidArgumentException("One or more input data file paths are not valid.");
81 }
82
83 if (m_InputTensorDataFilePaths.size() < m_InputNames.size())
84 {
85 throw armnn::InvalidArgumentException(
86 fmt::format("According to the number of input names the user provided the network has {} "
87 "inputs. But only {} input-tensor-data file paths were provided. Each input of the "
88 "model is expected to be stored in it's own file.",
89 m_InputNames.size(),
90 m_InputTensorDataFilePaths.size()));
91 }
92 }
93
94 // Check that threshold time is not less than zero
95 if (m_ThresholdTime < 0)
96 {
97 throw armnn::InvalidArgumentException("Threshold time supplied as a command line argument is less than zero.");
98 }
99
100 // Warn if ExecuteNetwork will generate dummy input data
101 if (m_GenerateTensorData)
102 {
103 ARMNN_LOG(warning) << "No input files provided, input tensors will be filled with 0s.";
104 }
105
106 if (m_AllowExpandedDims && m_InferOutputShape)
107 {
108 throw armnn::InvalidArgumentException("infer-output-shape and allow-expanded-dims cannot be used together.");
109 }
110 }
111
112 #if defined(ARMNN_TFLITE_DELEGATE)
113 /**
114 * A utility method that populates a DelegateOptions object from this ExecuteNetworkParams.
115 *
116 * @return a populated armnnDelegate::DelegateOptions object.
117 */
ToDelegateOptions() const118 armnnDelegate::DelegateOptions ExecuteNetworkParams::ToDelegateOptions() const
119 {
120 armnnDelegate::DelegateOptions delegateOptions(m_ComputeDevices);
121 delegateOptions.SetDynamicBackendsPath(m_DynamicBackendsPath);
122 delegateOptions.SetGpuProfilingState(m_EnableProfiling);
123 delegateOptions.SetInternalProfilingParams(m_EnableProfiling, armnn::ProfilingDetailsMethod::DetailsWithEvents);
124
125 // GPU Backend options first.
126 {
127 armnn::BackendOptions gpuOption("GpuAcc", {{"TuningLevel", m_TuningLevel}});
128 delegateOptions.AddBackendOption(gpuOption);
129 }
130 {
131 armnn::BackendOptions gpuOption("GpuAcc", {{"TuningFile", m_TuningPath.c_str()}});
132 delegateOptions.AddBackendOption(gpuOption);
133 }
134 {
135 armnn::BackendOptions gpuOption("GpuAcc", {{"KernelProfilingEnabled", m_EnableProfiling}});
136 delegateOptions.AddBackendOption(gpuOption);
137 }
138
139 // Optimizer options next.
140 armnn::OptimizerOptionsOpaque optimizerOptions;
141 optimizerOptions.SetReduceFp32ToFp16(m_EnableFp16TurboMode);
142 optimizerOptions.SetDebugEnabled(m_PrintIntermediate);
143 optimizerOptions.SetDebugToFileEnabled(m_PrintIntermediateOutputsToFile);
144 optimizerOptions.SetProfilingEnabled(m_EnableProfiling);
145 optimizerOptions.SetShapeInferenceMethod(armnn::ShapeInferenceMethod::ValidateOnly);
146 if (m_InferOutputShape)
147 {
148 optimizerOptions.SetShapeInferenceMethod(armnn::ShapeInferenceMethod::InferAndValidate);
149 armnn::BackendOptions networkOption("ShapeInferenceMethod",
150 {
151 {"InferAndValidate", true}
152 });
153 optimizerOptions.AddModelOption(networkOption);
154 }
155
156 {
157 armnn::BackendOptions option("GpuAcc", {{"FastMathEnabled", m_EnableFastMath}});
158 optimizerOptions.AddModelOption(option);
159 }
160 {
161 armnn::BackendOptions option("GpuAcc", {{"CachedNetworkFilePath", m_CachedNetworkFilePath}});
162 optimizerOptions.AddModelOption(option);
163 }
164 {
165 armnn::BackendOptions option("GpuAcc", {{"MLGOTuningFilePath", m_MLGOTuningFilePath}});
166 optimizerOptions.AddModelOption(option);
167 }
168
169 armnn::BackendOptions cpuAcc("CpuAcc",
170 {
171 { "FastMathEnabled", m_EnableFastMath },
172 { "NumberOfThreads", m_NumberOfThreads }
173 });
174 optimizerOptions.AddModelOption(cpuAcc);
175 if (m_AllowExpandedDims)
176 {
177 armnn::BackendOptions networkOption("AllowExpandedDims",
178 {
179 {"AllowExpandedDims", true}
180 });
181 optimizerOptions.AddModelOption(networkOption);
182 }
183 delegateOptions.SetOptimizerOptions(optimizerOptions);
184 return delegateOptions;
185 }
186
187 #endif
188