diff options
-rw-r--r-- | tests/CxxoptsUtils.hpp | 27 | ||||
-rw-r--r-- | tests/DeepSpeechV1InferenceTest.hpp | 45 | ||||
-rw-r--r-- | tests/InferenceModel.hpp | 58 | ||||
-rw-r--r-- | tests/InferenceTest.cpp | 66 | ||||
-rw-r--r-- | tests/InferenceTest.hpp | 13 | ||||
-rw-r--r-- | tests/InferenceTest.inl | 29 | ||||
-rw-r--r-- | tests/MobileNetSsdInferenceTest.hpp | 15 | ||||
-rw-r--r-- | tests/YoloInferenceTest.hpp | 21 |
8 files changed, 153 insertions, 121 deletions
diff --git a/tests/CxxoptsUtils.hpp b/tests/CxxoptsUtils.hpp new file mode 100644 index 0000000000..518fc1be67 --- /dev/null +++ b/tests/CxxoptsUtils.hpp @@ -0,0 +1,27 @@ +// +// Copyright © 2020 Arm Ltd. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include <cxxopts/cxxopts.hpp> + +/** + * Ensure all mandatory command-line parameters have been passed to cxxopts. + * @param result returned from the cxxopts parse(argc, argv) call + * @param required vector of strings listing the mandatory parameters to be input from the command-line + * @return boolean value - true if all required parameters satisfied, false otherwise + * */ +inline bool CheckRequiredOptions(const cxxopts::ParseResult& result, const std::vector<std::string>& required) +{ + for(const std::string& str : required) + { + if(result.count(str) == 0) + { + std::cerr << "--" << str << " parameter is mandatory" << std::endl; + return false; + } + } + return true; +} diff --git a/tests/DeepSpeechV1InferenceTest.hpp b/tests/DeepSpeechV1InferenceTest.hpp index d859ba7505..ac799cb45a 100644 --- a/tests/DeepSpeechV1InferenceTest.hpp +++ b/tests/DeepSpeechV1InferenceTest.hpp @@ -99,31 +99,28 @@ public: : m_ConstructModel(constructModel) {} - virtual void AddCommandLineOptions(boost::program_options::options_description& options) override + virtual void AddCommandLineOptions(cxxopts::Options& options, std::vector<std::string>& required) override { - namespace po = boost::program_options; - - options.add_options() - ("input-seq-dir,s", po::value<std::string>(&m_InputSeqDir)->required(), - "Path to directory containing test data for m_InputSeq"); - options.add_options() - ("prev-state-h-dir,h", po::value<std::string>(&m_PrevStateHDir)->required(), - "Path to directory containing test data for m_PrevStateH"); - options.add_options() - ("prev-state-c-dir,c", po::value<std::string>(&m_PrevStateCDir)->required(), - "Path to directory containing test data for m_PrevStateC"); - options.add_options() - ("logits-dir,l", po::value<std::string>(&m_LogitsDir)->required(), - "Path to directory containing test data for m_Logits"); - options.add_options() - ("new-state-h-dir,H", po::value<std::string>(&m_NewStateHDir)->required(), - "Path to directory containing test data for m_NewStateH"); - options.add_options() - ("new-state-c-dir,C", po::value<std::string>(&m_NewStateCDir)->required(), - "Path to directory containing test data for m_NewStateC"); - - - Model::AddCommandLineOptions(options, m_ModelCommandLineOptions); + options + .allow_unrecognised_options() + .add_options() + ("s,input-seq-dir", "Path to directory containing test data for m_InputSeq", + cxxopts::value<std::string>(m_InputSeqDir)) + ("h,prev-state-h-dir", "Path to directory containing test data for m_PrevStateH", + cxxopts::value<std::string>(m_PrevStateHDir)) + ("c,prev-state-c-dir", "Path to directory containing test data for m_PrevStateC", + cxxopts::value<std::string>(m_PrevStateCDir)) + ("l,logits-dir", "Path to directory containing test data for m_Logits", + cxxopts::value<std::string>(m_LogitsDir)) + ("H,new-state-h-dir", "Path to directory containing test data for m_NewStateH", + cxxopts::value<std::string>(m_NewStateHDir)) + ("C,new-state-c-dir", "Path to directory containing test data for m_NewStateC", + cxxopts::value<std::string>(m_NewStateCDir)); + + required.insert(required.end(), {"input-seq-dir", "prev-state-h-dir", "prev-state-c-dir", "logits-dir", + "new-state-h-dir", "new-state-c-dir"}); + + Model::AddCommandLineOptions(options, m_ModelCommandLineOptions, required); } virtual bool ProcessCommandLineOptions(const InferenceTestOptions &commonOptions) override diff --git a/tests/InferenceModel.hpp b/tests/InferenceModel.hpp index fd8dedeb29..dbc0419191 100644 --- a/tests/InferenceModel.hpp +++ b/tests/InferenceModel.hpp @@ -29,7 +29,8 @@ #include "armnn/utility/StringUtils.hpp" #include <boost/exception/exception.hpp> #include <boost/exception/diagnostic_information.hpp> -#include <boost/program_options.hpp> +#include <cxxopts/cxxopts.hpp> +#include "CxxoptsUtils.hpp" #include <fmt/format.h> #include <mapbox/variant.hpp> @@ -347,37 +348,42 @@ public: } }; - static void AddCommandLineOptions(boost::program_options::options_description& desc, CommandLineOptions& options) + static void AddCommandLineOptions(cxxopts::Options& options, + CommandLineOptions& cLineOptions, std::vector<std::string>& required) { - namespace po = boost::program_options; - const std::vector<std::string> defaultComputes = { "CpuAcc", "CpuRef" }; const std::string backendsMessage = "Which device to run layers on by default. Possible choices: " + armnn::BackendRegistryInstance().GetBackendIdsAsString(); - desc.add_options() - ("model-dir,m", po::value<std::string>(&options.m_ModelDir)->required(), - "Path to directory containing model files (.caffemodel/.prototxt/.tflite)") - ("compute,c", po::value<std::vector<std::string>>(&options.m_ComputeDevices)-> - default_value(defaultComputes, armnn::stringUtils::StringConcat(defaultComputes, ", "))-> - multitoken(), backendsMessage.c_str()) - ("dynamic-backends-path,b", po::value(&options.m_DynamicBackendsPath), - "Path where to load any available dynamic backend from. " - "If left empty (the default), dynamic backends will not be used.") - ("labels,l", po::value<std::string>(&options.m_Labels), - "Text file containing one image filename - correct label pair per line, " - "used to test the accuracy of the network.") - ("visualize-optimized-model,v", - po::value<bool>(&options.m_VisualizePostOptimizationModel)->default_value(false), - "Produce a dot file useful for visualizing the graph post optimization." - "The file will have the same name as the model with the .dot extention.") - ("fp16-turbo-mode", po::value<bool>(&options.m_EnableFp16TurboMode)->default_value(false), - "If this option is enabled FP32 layers, weights and biases will be converted " - "to FP16 where the backend supports it.") - ("bf16-turbo-mode", po::value<bool>(&options.m_EnableBf16TurboMode)->default_value(false), - "If this option is enabled FP32 layers, weights and biases will be converted " - "to BF16 where the backend supports it."); + options + .allow_unrecognised_options() + .add_options() + ("m,model-dir", "Path to directory containing model files (.caffemodel/.prototxt/.tflite)", + cxxopts::value<std::string>(cLineOptions.m_ModelDir)) + ("c,compute", backendsMessage.c_str(), + cxxopts::value<std::vector<std::string>>(cLineOptions.m_ComputeDevices)->default_value("CpuRef")) + ("b,dynamic-backends-path", + "Path where to load any available dynamic backend from. " + "If left empty (the default), dynamic backends will not be used.", + cxxopts::value(cLineOptions.m_DynamicBackendsPath)) + ("l,labels", + "Text file containing one image filename - correct label pair per line, " + "used to test the accuracy of the network.", cxxopts::value<std::string>(cLineOptions.m_Labels)) + ("v,visualize-optimized-model", + "Produce a dot file useful for visualizing the graph post optimization." + "The file will have the same name as the model with the .dot extention.", + cxxopts::value<bool>(cLineOptions.m_VisualizePostOptimizationModel)->default_value("false")) + ("fp16-turbo-mode", + "If this option is enabled FP32 layers, weights and biases will be converted " + "to FP16 where the backend supports it.", + cxxopts::value<bool>(cLineOptions.m_EnableFp16TurboMode)->default_value("false")) + ("bf16-turbo-mode", + "If this option is enabled FP32 layers, weights and biases will be converted " + "to BF16 where the backend supports it.", + cxxopts::value<bool>(cLineOptions.m_EnableBf16TurboMode)->default_value("false")); + + required.emplace_back("model-dir"); } InferenceModel(const Params& params, diff --git a/tests/InferenceTest.cpp b/tests/InferenceTest.cpp index b3b38d1386..3392f6ea51 100644 --- a/tests/InferenceTest.cpp +++ b/tests/InferenceTest.cpp @@ -8,7 +8,7 @@ #include <Filesystem.hpp> #include "../src/armnn/Profiling.hpp" -#include <boost/program_options.hpp> +#include <cxxopts/cxxopts.hpp> #include <fstream> #include <iostream> @@ -28,53 +28,51 @@ namespace test bool ParseCommandLine(int argc, char** argv, IInferenceTestCaseProvider& testCaseProvider, InferenceTestOptions& outParams) { - namespace po = boost::program_options; - - po::options_description desc("Options"); + cxxopts::Options options("InferenceTest", "Inference iteration parameters"); try { // Adds generic options needed for all inference tests. - desc.add_options() - ("help", "Display help messages") - ("iterations,i", po::value<unsigned int>(&outParams.m_IterationCount)->default_value(0), - "Sets the number number of inferences to perform. If unset, a default number will be ran.") - ("inference-times-file", po::value<std::string>(&outParams.m_InferenceTimesFile)->default_value(""), - "If non-empty, each individual inference time will be recorded and output to this file") - ("event-based-profiling,e", po::value<bool>(&outParams.m_EnableProfiling)->default_value(0), - "Enables built in profiler. If unset, defaults to off."); + options + .allow_unrecognised_options() + .add_options() + ("h,help", "Display help messages") + ("i,iterations", "Sets the number of inferences to perform. If unset, will only be run once.", + cxxopts::value<unsigned int>(outParams.m_IterationCount)->default_value("0")) + ("inference-times-file", + "If non-empty, each individual inference time will be recorded and output to this file", + cxxopts::value<std::string>(outParams.m_InferenceTimesFile)->default_value("")) + ("e,event-based-profiling", "Enables built in profiler. If unset, defaults to off.", + cxxopts::value<bool>(outParams.m_EnableProfiling)->default_value("0")); + + std::vector<std::string> required; //to be passed as reference to derived inference tests // Adds options specific to the ITestCaseProvider. - testCaseProvider.AddCommandLineOptions(desc); - } - catch (const std::exception& e) - { - // Coverity points out that default_value(...) can throw a bad_lexical_cast, - // and that desc.add_options() can throw boost::io::too_few_args. - // They really won't in any of these cases. - ARMNN_ASSERT_MSG(false, "Caught unexpected exception"); - std::cerr << "Fatal internal error: " << e.what() << std::endl; - return false; - } - - po::variables_map vm; + testCaseProvider.AddCommandLineOptions(options, required); - try - { - po::store(po::parse_command_line(argc, argv, desc), vm); + auto result = options.parse(argc, argv); - if (vm.count("help")) + if (result.count("help")) { - std::cout << desc << std::endl; + std::cout << options.help() << std::endl; return false; } - po::notify(vm); + CheckRequiredOptions(result, required); + + } + catch (const cxxopts::OptionException& e) + { + std::cerr << e.what() << std::endl << options.help() << std::endl; + return false; } - catch (po::error& e) + catch (const std::exception& e) { - std::cerr << e.what() << std::endl << std::endl; - std::cerr << desc << std::endl; + // Coverity points out that default_value(...) can throw a bad_lexical_cast, + // and that desc.add_options() can throw boost::io::too_few_args. + // They really won't in any of these cases. + ARMNN_ASSERT_MSG(false, "Caught unexpected exception"); + std::cerr << "Fatal internal error: " << e.what() << std::endl; return false; } diff --git a/tests/InferenceTest.hpp b/tests/InferenceTest.hpp index 1dafd01c01..5ec744ca7e 100644 --- a/tests/InferenceTest.hpp +++ b/tests/InferenceTest.hpp @@ -11,7 +11,8 @@ #include <armnn/TypesUtils.hpp> #include <armnn/utility/IgnoreUnused.hpp> -#include <boost/program_options.hpp> +#include <cxxopts/cxxopts.hpp> +#include <fmt/format.h> namespace armnn @@ -25,7 +26,7 @@ inline std::istream& operator>>(std::istream& in, armnn::Compute& compute) if (compute == armnn::Compute::Undefined) { in.setstate(std::ios_base::failbit); - throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value); + throw cxxopts::OptionException(fmt::format("Unrecognised compute device: {}", token)); } return in; } @@ -38,7 +39,7 @@ inline std::istream& operator>>(std::istream& in, armnn::BackendId& backend) if (compute == armnn::Compute::Undefined) { in.setstate(std::ios_base::failbit); - throw boost::program_options::validation_error(boost::program_options::validation_error::invalid_option_value); + throw cxxopts::OptionException(fmt::format("Unrecognised compute device: {}", token)); } backend = compute; return in; @@ -92,9 +93,9 @@ class IInferenceTestCaseProvider public: virtual ~IInferenceTestCaseProvider() {} - virtual void AddCommandLineOptions(boost::program_options::options_description& options) + virtual void AddCommandLineOptions(cxxopts::Options& options, std::vector<std::string>& required) { - IgnoreUnused(options); + IgnoreUnused(options, required); }; virtual bool ProcessCommandLineOptions(const InferenceTestOptions &commonOptions) { @@ -180,7 +181,7 @@ public: template <typename TConstructDatabaseCallable, typename TConstructModelCallable> ClassifierTestCaseProvider(TConstructDatabaseCallable constructDatabase, TConstructModelCallable constructModel); - virtual void AddCommandLineOptions(boost::program_options::options_description& options) override; + virtual void AddCommandLineOptions(cxxopts::Options& options, std::vector<std::string>& required) override; virtual bool ProcessCommandLineOptions(const InferenceTestOptions &commonOptions) override; virtual std::unique_ptr<IInferenceTestCase> GetTestCase(unsigned int testCaseId) override; virtual bool OnInferenceTestFinished() override; diff --git a/tests/InferenceTest.inl b/tests/InferenceTest.inl index e8401f6bc3..3d6dae335a 100644 --- a/tests/InferenceTest.inl +++ b/tests/InferenceTest.inl @@ -6,8 +6,9 @@ #include <armnn/utility/Assert.hpp> #include <armnn/utility/NumericCast.hpp> +#include "CxxoptsUtils.hpp" -#include <boost/program_options.hpp> +#include <cxxopts/cxxopts.hpp> #include <fmt/format.h> #include <fstream> @@ -181,19 +182,21 @@ ClassifierTestCaseProvider<TDatabase, InferenceModel>::ClassifierTestCaseProvide template <typename TDatabase, typename InferenceModel> void ClassifierTestCaseProvider<TDatabase, InferenceModel>::AddCommandLineOptions( - boost::program_options::options_description& options) + cxxopts::Options& options, std::vector<std::string>& required) { - namespace po = boost::program_options; - - options.add_options() - ("validation-file-in", po::value<std::string>(&m_ValidationFileIn)->default_value(""), - "Reads expected predictions from the given file and confirms they match the actual predictions.") - ("validation-file-out", po::value<std::string>(&m_ValidationFileOut)->default_value(""), - "Predictions are saved to the given file for later use via --validation-file-in.") - ("data-dir,d", po::value<std::string>(&m_DataDir)->required(), - "Path to directory containing test data"); - - InferenceModel::AddCommandLineOptions(options, m_ModelCommandLineOptions); + options + .allow_unrecognised_options() + .add_options() + ("validation-file-in", + "Reads expected predictions from the given file and confirms they match the actual predictions.", + cxxopts::value<std::string>(m_ValidationFileIn)->default_value("")) + ("validation-file-out", "Predictions are saved to the given file for later use via --validation-file-in.", + cxxopts::value<std::string>(m_ValidationFileOut)->default_value("")) + ("d,data-dir", "Path to directory containing test data", cxxopts::value<std::string>(m_DataDir)); + + required.emplace_back("data-dir"); //add to required arguments to check + + InferenceModel::AddCommandLineOptions(options, m_ModelCommandLineOptions, required); } template <typename TDatabase, typename InferenceModel> diff --git a/tests/MobileNetSsdInferenceTest.hpp b/tests/MobileNetSsdInferenceTest.hpp index 2a5d47d634..7377640629 100644 --- a/tests/MobileNetSsdInferenceTest.hpp +++ b/tests/MobileNetSsdInferenceTest.hpp @@ -152,18 +152,19 @@ public: : m_ConstructModel(constructModel) {} - virtual void AddCommandLineOptions(boost::program_options::options_description& options) override + virtual void AddCommandLineOptions(cxxopts::Options& options, std::vector<std::string>& required) override { - namespace po = boost::program_options; + options + .allow_unrecognised_options() + .add_options() + ("d,data-dir", "Path to directory containing test data", cxxopts::value<std::string>(m_DataDir)); - options.add_options() - ("data-dir,d", po::value<std::string>(&m_DataDir)->required(), - "Path to directory containing test data"); + required.emplace_back("data-dir"); - Model::AddCommandLineOptions(options, m_ModelCommandLineOptions); + Model::AddCommandLineOptions(options, m_ModelCommandLineOptions, required); } - virtual bool ProcessCommandLineOptions(const InferenceTestOptions &commonOptions) override + virtual bool ProcessCommandLineOptions(const InferenceTestOptions& commonOptions) override { if (!ValidateDirectory(m_DataDir)) { diff --git a/tests/YoloInferenceTest.hpp b/tests/YoloInferenceTest.hpp index 81ba0f5127..4f391a84a5 100644 --- a/tests/YoloInferenceTest.hpp +++ b/tests/YoloInferenceTest.hpp @@ -10,13 +10,13 @@ #include <armnn/utility/Assert.hpp> #include <armnn/utility/IgnoreUnused.hpp> +#include <boost/multi_array.hpp> +#include <boost/test/tools/floating_point_comparison.hpp> + #include <algorithm> #include <array> #include <utility> -#include <boost/multi_array.hpp> -#include <boost/test/tools/floating_point_comparison.hpp> - constexpr size_t YoloOutputSize = 1470; template <typename Model> @@ -187,18 +187,17 @@ public: { } - virtual void AddCommandLineOptions(boost::program_options::options_description& options) override + virtual void AddCommandLineOptions(cxxopts::Options& options, std::vector<std::string>& required) override { - namespace po = boost::program_options; - - options.add_options() - ("data-dir,d", po::value<std::string>(&m_DataDir)->required(), - "Path to directory containing test data"); + options + .allow_unrecognised_options() + .add_options() + ("d,data-dir", "Path to directory containing test data", cxxopts::value<std::string>(m_DataDir)); - Model::AddCommandLineOptions(options, m_ModelCommandLineOptions); + Model::AddCommandLineOptions(options, m_ModelCommandLineOptions, required); } - virtual bool ProcessCommandLineOptions(const InferenceTestOptions &commonOptions) override + virtual bool ProcessCommandLineOptions(const InferenceTestOptions& commonOptions) override { if (!ValidateDirectory(m_DataDir)) { |