ArmNN
 20.02
MultipleNetworksCifar10.cpp File Reference
#include <iostream>
#include <chrono>
#include <vector>
#include <array>
#include "armnn/ArmNN.hpp"
#include "armnn/Utils.hpp"
#include "armnn/INetwork.hpp"
#include "armnnCaffeParser/ICaffeParser.hpp"
#include "../Cifar10Database.hpp"
#include "../InferenceTest.hpp"
#include "../InferenceModel.hpp"

Go to the source code of this file.

Functions

int main (int argc, char *argv[])
 

Function Documentation

◆ main()

int main ( int  argc,
char *  argv[] 
)

Definition at line 22 of file MultipleNetworksCifar10.cpp.

References ARMNN_LOG, armnn::BackendRegistryInstance(), armnn::ConfigureLogging(), armnn::CpuAcc, armnn::CpuRef, ICaffeParser::Create(), IRuntime::Create(), armnn::Debug, defaultBackends, armnn::Failure, BackendRegistry::GetBackendIdsAsString(), Cifar10Database::GetTestCaseData(), armnn::Info, armnnUtils::MakeInputTensors(), armnnUtils::MakeOutputTensors(), armnn::Optimize(), options, armnn::test::ValidateDirectory(), and Exception::what().

23 {
24 #ifdef NDEBUG
26 #else
28 #endif
29 
30  try
31  {
32  // Configures logging for both the ARMNN library and this test program.
33  armnn::ConfigureLogging(true, true, level);
34  namespace po = boost::program_options;
35 
36  std::vector<armnn::BackendId> computeDevice;
37  std::vector<armnn::BackendId> defaultBackends = {armnn::Compute::CpuAcc, armnn::Compute::CpuRef};
38  std::string modelDir;
39  std::string dataDir;
40 
41  const std::string backendsMessage = "Which device to run layers on by default. Possible choices: "
43 
44  po::options_description desc("Options");
45  try
46  {
47  // Adds generic options needed for all inference tests.
48  desc.add_options()
49  ("help", "Display help messages")
50  ("model-dir,m", po::value<std::string>(&modelDir)->required(),
51  "Path to directory containing the Cifar10 model file")
52  ("compute,c", po::value<std::vector<armnn::BackendId>>(&computeDevice)->default_value(defaultBackends),
53  backendsMessage.c_str())
54  ("data-dir,d", po::value<std::string>(&dataDir)->required(),
55  "Path to directory containing the Cifar10 test data");
56  }
57  catch (const std::exception& e)
58  {
59  // Coverity points out that default_value(...) can throw a bad_lexical_cast,
60  // and that desc.add_options() can throw boost::io::too_few_args.
61  // They really won't in any of these cases.
62  BOOST_ASSERT_MSG(false, "Caught unexpected exception");
63  std::cerr << "Fatal internal error: " << e.what() << std::endl;
64  return 1;
65  }
66 
67  po::variables_map vm;
68 
69  try
70  {
71  po::store(po::parse_command_line(argc, argv, desc), vm);
72 
73  if (vm.count("help"))
74  {
75  std::cout << desc << std::endl;
76  return 1;
77  }
78 
79  po::notify(vm);
80  }
81  catch (po::error& e)
82  {
83  std::cerr << e.what() << std::endl << std::endl;
84  std::cerr << desc << std::endl;
85  return 1;
86  }
87 
88  if (!ValidateDirectory(modelDir))
89  {
90  return 1;
91  }
92  string modelPath = modelDir + "cifar10_full_iter_60000.caffemodel";
93 
94  // Create runtime
95  // This will also load dynamic backend in case that the dynamic backend path is specified
98 
99  // Check if the requested backend are all valid
100  std::string invalidBackends;
101  if (!CheckRequestedBackendsAreValid(computeDevice, armnn::Optional<std::string&>(invalidBackends)))
102  {
103  ARMNN_LOG(fatal) << "The list of preferred devices contains invalid backend IDs: "
104  << invalidBackends;
105  return EXIT_FAILURE;
106  }
107 
108  // Loads networks.
109  armnn::Status status;
110  struct Net
111  {
112  Net(armnn::NetworkId netId,
113  const std::pair<armnn::LayerBindingId, armnn::TensorInfo>& in,
114  const std::pair<armnn::LayerBindingId, armnn::TensorInfo>& out)
115  : m_Network(netId)
116  , m_InputBindingInfo(in)
117  , m_OutputBindingInfo(out)
118  {}
119 
120  armnn::NetworkId m_Network;
121  std::pair<armnn::LayerBindingId, armnn::TensorInfo> m_InputBindingInfo;
122  std::pair<armnn::LayerBindingId, armnn::TensorInfo> m_OutputBindingInfo;
123  };
124  std::vector<Net> networks;
125 
127 
128  const int networksCount = 4;
129  for (int i = 0; i < networksCount; ++i)
130  {
131  // Creates a network from a file on the disk.
132  armnn::INetworkPtr network = parser->CreateNetworkFromBinaryFile(modelPath.c_str(), {}, { "prob" });
133 
134  // Optimizes the network.
135  armnn::IOptimizedNetworkPtr optimizedNet(nullptr, nullptr);
136  try
137  {
138  optimizedNet = armnn::Optimize(*network, computeDevice, runtime->GetDeviceSpec());
139  }
140  catch (armnn::Exception& e)
141  {
142  std::stringstream message;
143  message << "armnn::Exception ("<<e.what()<<") caught from optimize.";
144  ARMNN_LOG(fatal) << message.str();
145  return 1;
146  }
147 
148  // Loads the network into the runtime.
149  armnn::NetworkId networkId;
150  status = runtime->LoadNetwork(networkId, std::move(optimizedNet));
151  if (status == armnn::Status::Failure)
152  {
153  ARMNN_LOG(fatal) << "armnn::IRuntime: Failed to load network";
154  return 1;
155  }
156 
157  networks.emplace_back(networkId,
158  parser->GetNetworkInputBindingInfo("data"),
159  parser->GetNetworkOutputBindingInfo("prob"));
160  }
161 
162  // Loads a test case and tests inference.
163  if (!ValidateDirectory(dataDir))
164  {
165  return 1;
166  }
167  Cifar10Database cifar10(dataDir);
168 
169  for (unsigned int i = 0; i < 3; ++i)
170  {
171  // Loads test case data (including image data).
172  std::unique_ptr<Cifar10Database::TTestCaseData> testCaseData = cifar10.GetTestCaseData(i);
173 
174  // Tests inference.
175  std::vector<TContainer> outputs;
176  outputs.reserve(networksCount);
177 
178  for (unsigned int j = 0; j < networksCount; ++j)
179  {
180  outputs.push_back(std::vector<float>(10));
181  }
182 
183  for (unsigned int k = 0; k < networksCount; ++k)
184  {
185  std::vector<armnn::BindingPointInfo> inputBindings = { networks[k].m_InputBindingInfo };
186  std::vector<armnn::BindingPointInfo> outputBindings = { networks[k].m_OutputBindingInfo };
187 
188  std::vector<TContainer> inputDataContainers = { testCaseData->m_InputImage };
189  std::vector<TContainer> outputDataContainers = { outputs[k] };
190 
191  status = runtime->EnqueueWorkload(networks[k].m_Network,
192  armnnUtils::MakeInputTensors(inputBindings, inputDataContainers),
193  armnnUtils::MakeOutputTensors(outputBindings, outputDataContainers));
194  if (status == armnn::Status::Failure)
195  {
196  ARMNN_LOG(fatal) << "armnn::IRuntime: Failed to enqueue workload";
197  return 1;
198  }
199  }
200 
201  // Compares outputs.
202  std::vector<float> output0 = boost::get<std::vector<float>>(outputs[0]);
203 
204  for (unsigned int k = 1; k < networksCount; ++k)
205  {
206  std::vector<float> outputK = boost::get<std::vector<float>>(outputs[k]);
207 
208  if (!std::equal(output0.begin(), output0.end(), outputK.begin(), outputK.end()))
209  {
210  ARMNN_LOG(error) << "Multiple networks inference failed!";
211  return 1;
212  }
213  }
214  }
215 
216  ARMNN_LOG(info) << "Multiple networks inference ran successfully!";
217  return 0;
218  }
219  catch (armnn::Exception const& e)
220  {
221  // Coverity fix: BOOST_LOG_TRIVIAL (typically used to report errors) may throw an
222  // exception of type std::length_error.
223  // Using stderr instead in this context as there is no point in nesting try-catch blocks here.
224  std::cerr << "Armnn Error: " << e.what() << std::endl;
225  return 1;
226  }
227  catch (const std::exception& e)
228  {
229  // Coverity fix: various boost exceptions can be thrown by methods called by this test.
230  std::cerr << "WARNING: MultipleNetworksCifar10: An error has occurred when running the "
231  "multiple networks inference tests: " << e.what() << std::endl;
232  return 1;
233  }
234 }
static IRuntimePtr Create(const CreationOptions &options)
Definition: Runtime.cpp:32
CPU Execution: Reference C++ kernels.
void ConfigureLogging(bool printToStandardOutput, bool printToDebugOutput, LogSeverity severity)
Configures the logging behaviour of the ARMNN library.
Definition: Utils.cpp:10
std::unique_ptr< IRuntime, void(*)(IRuntime *runtime)> IRuntimePtr
Definition: IRuntime.hpp:24
virtual const char * what() const noexcept override
Definition: Exceptions.cpp:32
#define ARMNN_LOG(severity)
Definition: Logging.hpp:163
BackendRegistry & BackendRegistryInstance()
int NetworkId
Definition: IRuntime.hpp:19
std::string GetBackendIdsAsString() const
armnn::InputTensors MakeInputTensors(const std::vector< armnn::BindingPointInfo > &inputBindings, const std::vector< TContainer > &inputDataContainers)
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Create an optimized version of the network.
Definition: Network.cpp:890
static ICaffeParserPtr Create()
Status
enumeration
Definition: Types.hpp:26
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
Definition: INetwork.hpp:566
std::unique_ptr< ICaffeParser, void(*)(ICaffeParser *parser)> ICaffeParserPtr
armnn::OutputTensors MakeOutputTensors(const std::vector< armnn::BindingPointInfo > &outputBindings, std::vector< TContainer > &outputDataContainers)
std::vector< armnn::BackendId > defaultBackends
Base class for all ArmNN exceptions so that users can filter to just those.
Definition: Exceptions.hpp:46
CPU Execution: NEON: ArmCompute.
bool ValidateDirectory(std::string &dir)
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
Definition: INetwork.hpp:101
armnn::Runtime::CreationOptions::ExternalProfilingOptions options
LogSeverity
Definition: Utils.hpp:12