ArmNN  NotReleased
ParserFlatbuffersSerializeFixture.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #pragma once
7 
8 #include "SchemaSerialize.hpp"
9 
10 #include <armnn/IRuntime.hpp>
12 
13 #include <boost/core/ignore_unused.hpp>
14 #include <boost/assert.hpp>
15 #include <boost/format.hpp>
16 
17 #include <ResolveType.hpp>
18 #include "test/TensorHelpers.hpp"
19 
20 #include "flatbuffers/idl.h"
21 #include "flatbuffers/util.h"
22 
23 #include <ArmnnSchema_generated.h>
24 
26 using TensorRawPtr = armnnSerializer::TensorInfo*;
27 
29 {
31  m_Parser(IDeserializer::Create()),
32  m_Runtime(armnn::IRuntime::Create(armnn::IRuntime::CreationOptions())),
34  {
35  }
36 
37  std::vector<uint8_t> m_GraphBinary;
38  std::string m_JsonString;
39  std::unique_ptr<IDeserializer, void (*)(IDeserializer* parser)> m_Parser;
42 
45  std::string m_SingleInputName;
46  std::string m_SingleOutputName;
47 
48  void Setup()
49  {
50  bool ok = ReadStringToBinary();
51  if (!ok)
52  {
53  throw armnn::Exception("LoadNetwork failed while reading binary input");
54  }
55 
56  armnn::INetworkPtr network =
57  m_Parser->CreateNetworkFromBinary(m_GraphBinary);
58 
59  if (!network)
60  {
61  throw armnn::Exception("The parser failed to create an ArmNN network");
62  }
63 
64  auto optimized = Optimize(*network, {armnn::Compute::CpuRef},
65  m_Runtime->GetDeviceSpec());
66 
67  std::string errorMessage;
68  armnn::Status ret = m_Runtime->LoadNetwork(m_NetworkIdentifier, move(optimized), errorMessage);
69 
70  if (ret != armnn::Status::Success)
71  {
72  throw armnn::Exception(
73  boost::str(
74  boost::format("The runtime failed to load the network. "
75  "Error was: %1%. in %2% [%3%:%4%]") %
76  errorMessage %
77  __func__ %
78  __FILE__ %
79  __LINE__));
80  }
81 
82  }
83 
84  void SetupSingleInputSingleOutput(const std::string& inputName, const std::string& outputName)
85  {
86  // Store the input and output name so they don't need to be passed to the single-input-single-output RunTest().
87  m_SingleInputName = inputName;
88  m_SingleOutputName = outputName;
89  Setup();
90  }
91 
93  {
94  std::string schemafile(&deserialize_schema_start, &deserialize_schema_end);
95 
96  // parse schema first, so we can use it to parse the data after
97  flatbuffers::Parser parser;
98 
99  bool ok = parser.Parse(schemafile.c_str());
100  BOOST_ASSERT_MSG(ok, "Failed to parse schema file");
101 
102  ok &= parser.Parse(m_JsonString.c_str());
103  BOOST_ASSERT_MSG(ok, "Failed to parse json input");
104 
105  if (!ok)
106  {
107  return false;
108  }
109 
110  {
111  const uint8_t* bufferPtr = parser.builder_.GetBufferPointer();
112  size_t size = static_cast<size_t>(parser.builder_.GetSize());
113  m_GraphBinary.assign(bufferPtr, bufferPtr+size);
114  }
115  return ok;
116  }
117 
120  template<std::size_t NumOutputDimensions,
121  armnn::DataType ArmnnType,
123  void RunTest(unsigned int layersId,
124  const std::vector<DataType>& inputData,
125  const std::vector<DataType>& expectedOutputData);
126 
127  template<std::size_t NumOutputDimensions,
128  armnn::DataType ArmnnInputType,
129  armnn::DataType ArmnnOutputType,
130  typename InputDataType = armnn::ResolveType<ArmnnInputType>,
131  typename OutputDataType = armnn::ResolveType<ArmnnOutputType>>
132  void RunTest(unsigned int layersId,
133  const std::vector<InputDataType>& inputData,
134  const std::vector<OutputDataType>& expectedOutputData);
135 
138  template<std::size_t NumOutputDimensions,
139  armnn::DataType ArmnnType,
140  typename DataType = armnn::ResolveType<ArmnnType>>
141  void RunTest(unsigned int layersId,
142  const std::map<std::string, std::vector<DataType>>& inputData,
143  const std::map<std::string, std::vector<DataType>>& expectedOutputData);
144 
145  template<std::size_t NumOutputDimensions,
146  armnn::DataType ArmnnInputType,
147  armnn::DataType ArmnnOutputType,
148  typename InputDataType = armnn::ResolveType<ArmnnInputType>,
149  typename OutputDataType = armnn::ResolveType<ArmnnOutputType>>
150  void RunTest(unsigned int layersId,
151  const std::map<std::string, std::vector<InputDataType>>& inputData,
152  const std::map<std::string, std::vector<OutputDataType>>& expectedOutputData);
153 
154  void CheckTensors(const TensorRawPtr& tensors, size_t shapeSize, const std::vector<int32_t>& shape,
155  armnnSerializer::TensorInfo tensorType, const std::string& name,
156  const float scale, const int64_t zeroPoint)
157  {
158  boost::ignore_unused(name);
159  BOOST_CHECK_EQUAL(shapeSize, tensors->dimensions()->size());
160  BOOST_CHECK_EQUAL_COLLECTIONS(shape.begin(), shape.end(),
161  tensors->dimensions()->begin(), tensors->dimensions()->end());
162  BOOST_CHECK_EQUAL(tensorType.dataType(), tensors->dataType());
163  BOOST_CHECK_EQUAL(scale, tensors->quantizationScale());
164  BOOST_CHECK_EQUAL(zeroPoint, tensors->quantizationOffset());
165  }
166 };
167 
168 template<std::size_t NumOutputDimensions, armnn::DataType ArmnnType, typename DataType>
170  const std::vector<DataType>& inputData,
171  const std::vector<DataType>& expectedOutputData)
172 {
173  RunTest<NumOutputDimensions, ArmnnType, ArmnnType, DataType, DataType>(layersId, inputData, expectedOutputData);
174 }
175 
176 template<std::size_t NumOutputDimensions,
177  armnn::DataType ArmnnInputType,
178  armnn::DataType ArmnnOutputType,
179  typename InputDataType,
180  typename OutputDataType>
182  const std::vector<InputDataType>& inputData,
183  const std::vector<OutputDataType>& expectedOutputData)
184 {
185  RunTest<NumOutputDimensions, ArmnnInputType, ArmnnOutputType>(layersId,
186  { { m_SingleInputName, inputData } },
187  { { m_SingleOutputName, expectedOutputData } });
188 }
189 
190 template<std::size_t NumOutputDimensions, armnn::DataType ArmnnType, typename DataType>
192  const std::map<std::string, std::vector<DataType>>& inputData,
193  const std::map<std::string, std::vector<DataType>>& expectedOutputData)
194 {
195  RunTest<NumOutputDimensions, ArmnnType, ArmnnType, DataType, DataType>(layersId, inputData, expectedOutputData);
196 }
197 
198 template<std::size_t NumOutputDimensions,
199  armnn::DataType ArmnnInputType,
200  armnn::DataType ArmnnOutputType,
201  typename InputDataType,
202  typename OutputDataType>
204  unsigned int layersId,
205  const std::map<std::string, std::vector<InputDataType>>& inputData,
206  const std::map<std::string, std::vector<OutputDataType>>& expectedOutputData)
207 {
208  auto ConvertBindingInfo = [](const armnnDeserializer::BindingPointInfo& bindingInfo)
209  {
210  return std::make_pair(bindingInfo.m_BindingId, bindingInfo.m_TensorInfo);
211  };
212 
213  // Setup the armnn input tensors from the given vectors.
214  armnn::InputTensors inputTensors;
215  for (auto&& it : inputData)
216  {
217  armnn::BindingPointInfo bindingInfo = ConvertBindingInfo(
218  m_Parser->GetNetworkInputBindingInfo(layersId, it.first));
219  armnn::VerifyTensorInfoDataType(bindingInfo.second, ArmnnInputType);
220  inputTensors.push_back({ bindingInfo.first, armnn::ConstTensor(bindingInfo.second, it.second.data()) });
221  }
222 
223  // Allocate storage for the output tensors to be written to and setup the armnn output tensors.
224  std::map<std::string, boost::multi_array<OutputDataType, NumOutputDimensions>> outputStorage;
225  armnn::OutputTensors outputTensors;
226  for (auto&& it : expectedOutputData)
227  {
228  armnn::BindingPointInfo bindingInfo = ConvertBindingInfo(
229  m_Parser->GetNetworkOutputBindingInfo(layersId, it.first));
230  armnn::VerifyTensorInfoDataType(bindingInfo.second, ArmnnOutputType);
231  outputStorage.emplace(it.first, MakeTensor<OutputDataType, NumOutputDimensions>(bindingInfo.second));
232  outputTensors.push_back(
233  { bindingInfo.first, armnn::Tensor(bindingInfo.second, outputStorage.at(it.first).data()) });
234  }
235 
236  m_Runtime->EnqueueWorkload(m_NetworkIdentifier, inputTensors, outputTensors);
237 
238  // Compare each output tensor to the expected values
239  for (auto&& it : expectedOutputData)
240  {
241  armnn::BindingPointInfo bindingInfo = ConvertBindingInfo(
242  m_Parser->GetNetworkOutputBindingInfo(layersId, it.first));
243  auto outputExpected = MakeTensor<OutputDataType, NumOutputDimensions>(bindingInfo.second, it.second);
244  BOOST_TEST(CompareTensors(outputExpected, outputStorage[it.first]));
245  }
246 }
Status
Definition: Types.hpp:26
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:199
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
Definition: Tensor.hpp:226
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Definition: Network.cpp:807
void VerifyTensorInfoDataType(const armnn::TensorInfo &info, armnn::DataType dataType)
Definition: TypesUtils.hpp:292
void CheckTensors(const TensorRawPtr &tensors, size_t shapeSize, const std::vector< int32_t > &shape, armnnSerializer::TensorInfo tensorType, const std::string &name, const float scale, const int64_t zeroPoint)
void SetupSingleInputSingleOutput(const std::string &inputName, const std::string &outputName)
std::pair< armnn::LayerBindingId, armnn::TensorInfo > BindingPointInfo
Definition: Tensor.hpp:146
typename ResolveTypeImpl< DT >::Type ResolveType
Definition: ResolveType.hpp:66
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
Definition: Tensor.hpp:191
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Definition: Tensor.hpp:225
std::unique_ptr< IDeserializer, void(*)(IDeserializer *parser)> m_Parser
armnnSerializer::TensorInfo * TensorRawPtr
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:85
CPU Execution: Reference C++ kernels.
const char deserialize_schema_end
DataType
Definition: Types.hpp:32
const char deserialize_schema_start
void RunTest(unsigned int layersId, const std::vector< DataType > &inputData, const std::vector< DataType > &expectedOutputData)
int NetworkId
Definition: IRuntime.hpp:19
std::unique_ptr< IRuntime, void(*)(IRuntime *runtime)> IRuntimePtr
Definition: IRuntime.hpp:24
boost::test_tools::predicate_result CompareTensors(const boost::multi_array< T, n > &a, const boost::multi_array< T, n > &b, bool compareBoolean=false)