9 #include <armnnTestUtils/TensorHelpers.hpp>
14 #include <doctest/doctest.h>
15 #include <fmt/format.h>
23 template<
typename TParser>
37 const std::string& inputName,
38 const std::string& outputName);
41 const std::string& inputName,
42 const std::string& outputName);
43 void Setup(
const std::map<std::string, armnn::TensorShape>& inputShapes,
44 const std::vector<std::string>& requestedOutputs);
45 void Setup(
const std::map<std::string, armnn::TensorShape>& inputShapes);
48 const std::map<std::string,armnn::TensorShape>& inputShapes,
49 const std::vector<std::string>& requestedOutputs);
54 template <std::
size_t NumOutputDimensions>
55 void RunTest(
const std::vector<float>& inputData,
const std::vector<float>& expectedOutputData);
59 template <std::
size_t NumOutputDimensions>
60 void RunComparisonTest(
const std::map<std::string, std::vector<float>>& inputData,
61 const std::map<std::string, std::vector<uint8_t>>& expectedOutputData);
65 template <std::
size_t NumOutputDimensions,
typename T =
float>
66 void RunTest(
const std::map<std::string, std::vector<float>>& inputData,
67 const std::map<std::string, std::vector<T>>& expectedOutputData);
70 std::unique_ptr<TParser, void(*)(TParser* parser)>
m_Parser;
86 template<
typename TParser>
88 const std::string& outputName)
91 m_SingleInputName = inputName;
92 m_SingleOutputName = outputName;
93 Setup({ }, { outputName });
96 template<
typename TParser>
98 const std::string& inputName,
99 const std::string& outputName)
102 m_SingleInputName = inputName;
103 m_SingleOutputName = outputName;
104 Setup({ { inputName, inputTensorShape } }, { outputName });
107 template<
typename TParser>
110 const std::string& inputName,
111 const std::string& outputName)
115 m_SingleInputName = inputName;
116 m_SingleOutputName = outputName;
117 m_SingleOutputShape = outputTensorShape;
118 Setup({ { inputName, inputTensorShape } }, { outputName });
121 template<
typename TParser>
123 const std::vector<std::string>& requestedOutputs)
125 std::string errorMessage;
128 m_Parser->CreateNetworkFromString(m_Prototext.c_str(), inputShapes, requestedOutputs);
130 armnn::Status ret = m_Runtime->LoadNetwork(m_NetworkIdentifier, std::move(optimized), errorMessage);
133 throw armnn::Exception(fmt::format(
"LoadNetwork failed with error: '{0}' {1}",
139 template<
typename TParser>
142 std::string errorMessage;
145 m_Parser->CreateNetworkFromString(m_Prototext.c_str(), inputShapes);
147 armnn::Status ret = m_Runtime->LoadNetwork(m_NetworkIdentifier, std::move(optimized), errorMessage);
150 throw armnn::Exception(fmt::format(
"LoadNetwork failed with error: '{0}' {1}",
156 template<
typename TParser>
159 std::string errorMessage;
162 m_Parser->CreateNetworkFromString(m_Prototext.c_str());
164 armnn::Status ret = m_Runtime->LoadNetwork(m_NetworkIdentifier, std::move(optimized), errorMessage);
167 throw armnn::Exception(fmt::format(
"LoadNetwork failed with error: '{0}' {1}",
173 template<
typename TParser>
175 const std::map<std::string,armnn::TensorShape>& inputShapes,
176 const std::vector<std::string>& requestedOutputs)
179 m_Parser->CreateNetworkFromString(m_Prototext.c_str(), inputShapes, requestedOutputs);
184 template<
typename TParser>
185 template <std::
size_t NumOutputDimensions>
187 const std::vector<float>& expectedOutputData)
189 RunTest<NumOutputDimensions>({ { m_SingleInputName, inputData } }, { { m_SingleOutputName, expectedOutputData } });
192 template<
typename TParser>
193 template <std::
size_t NumOutputDimensions>
195 const std::map<std::string, std::vector<uint8_t>>&
198 RunTest<NumOutputDimensions, uint8_t>(inputData, expectedOutputData);
201 template<
typename TParser>
202 template <std::
size_t NumOutputDimensions,
typename T>
204 const std::map<std::string, std::vector<T>>& expectedOutputData)
208 for (
auto&& it : inputData)
211 bindingInfo.second.SetConstant(
true);
212 inputTensors.push_back({ bindingInfo.first,
armnn::ConstTensor(bindingInfo.second, it.second.data()) });
213 if (bindingInfo.second.GetNumElements() != it.second.size())
215 throw armnn::Exception(fmt::format(
"Input tensor {0} is expected to have {1} elements. "
216 "{2} elements supplied. {3}",
218 bindingInfo.second.GetNumElements(),
225 std::map<std::string, std::vector<T>> outputStorage;
227 for (
auto&& it : expectedOutputData)
230 outputStorage.emplace(it.first, std::vector<T>(bindingInfo.second.GetNumElements()));
231 outputTensors.push_back(
232 { bindingInfo.first,
armnn::Tensor(bindingInfo.second, outputStorage.at(it.first).data()) });
235 m_Runtime->EnqueueWorkload(m_NetworkIdentifier, inputTensors, outputTensors);
238 for (
auto&& it : expectedOutputData)
241 if (bindingInfo.second.GetNumElements() != it.second.size())
243 throw armnn::Exception(fmt::format(
"Output tensor {0} is expected to have {1} elements. "
244 "{2} elements supplied. {3}",
246 bindingInfo.second.GetNumElements(),
252 if (m_SingleOutputShape.GetNumDimensions() != 0)
255 if (bindingInfo.second.GetShape().GetNumDimensions() == NumOutputDimensions &&
256 bindingInfo.second.GetShape().GetNumDimensions() == m_SingleOutputShape.GetNumDimensions())
258 for (
unsigned int i = 0; i < m_SingleOutputShape.GetNumDimensions(); ++i)
260 if (m_SingleOutputShape[i] != bindingInfo.second.GetShape()[i])
264 std::stringstream message;
265 message <<
"Output tensor " << it.first <<
" is expected to have "
266 << bindingInfo.second.GetShape() <<
"shape. "
267 << m_SingleOutputShape <<
" shape supplied. "
275 throw armnn::Exception(fmt::format(
"Output tensor {0} is expected to have {1} dimensions. "
276 "{2} dimensions supplied. {3}",
278 bindingInfo.second.GetShape().GetNumDimensions(),
284 auto outputExpected = it.second;
285 auto shape = bindingInfo.second.GetShape();
286 if (std::is_same<T, uint8_t>::value)
288 auto result = CompareTensors(outputExpected, outputStorage[it.first], shape, shape,
true);
289 CHECK_MESSAGE(result.m_Result, result.m_Message.str());
293 auto result = CompareTensors(outputExpected, outputStorage[it.first], shape, shape);
294 CHECK_MESSAGE(result.m_Result, result.m_Message.str());