Compare commits

...

2 Commits

Author SHA1 Message Date
Alexey Suhov
45d159094b Fix license header in Movidius sources 2021-06-04 19:59:17 +03:00
Artemy Skrebkov
6f860ddcf2 Restore precision setting for benchmark (#4859)
* Add -ip,-op,-iop parameters to benchamrk_app

* Revert not related changes

* Revert extension usage
2021-03-19 10:20:18 +03:00
8 changed files with 292 additions and 243 deletions

View File

@@ -10,3 +10,4 @@ ie_add_sample(NAME benchmark_app
HEADERS ${HDR}
DEPENDENCIES format_reader
OPENCV_DEPENDENCIES imgcodecs)

View File

@@ -105,6 +105,9 @@ Options:
-nthreads "<integer>" Optional. Number of threads to use for inference on the CPU (including HETERO and MULTI cases).
-enforcebf16 Optional. Enforcing of floating point operations execution in bfloat16 precision on platforms with native bfloat16 support. By default, this key sets "true" on platforms with native bfloat16 support and "false" for other platforms. Use "-enforcebf16=false" to disable this feature.
-pin "YES"/"NO"/"NUMA" Optional. Enable threads->cores ("YES", default), threads->(NUMA)nodes ("NUMA") or completely disable ("NO") CPU threads pinning for CPU-involved inference.
-ip "U8"/"FP16"/"FP32" Optional. Specifies precision for all input layers of the network.
-op "U8"/"FP16"/"FP32" Optional. Specifies precision for all output layers of the network.
-iop Optional. Specifies precision for input and output layers by name. Example: -iop "input:FP16, output:FP16". Notice that quotes are required. Overwrites precision from ip and op options for specified layers.
Statistics dumping options:

View File

@@ -108,6 +108,19 @@ static const char layout_message[] = "Optional. Prompts how network layouts shou
// @brief message for quantization bits
static const char gna_qb_message[] = "Optional. Weight bits for quantization: 8 or 16 (default)";
// TODO: duplicate options from compile_tool
static constexpr char inputs_precision_message[] =
"Optional. Specifies precision for all input layers of the network.";
static constexpr char outputs_precision_message[] =
"Optional. Specifies precision for all output layers of the network.";
static constexpr char iop_message[] =
"Optional. Specifies precision for input and output layers by name.\n"
" Example: -iop \"input:FP16, output:FP16\".\n"
" Notice that quotes are required.\n"
" Overwrites precision from ip and op options for specified layers.";
/// @brief Define flag for showing help message <br>
DEFINE_bool(h, false, help_message);
@@ -198,6 +211,18 @@ DEFINE_string(layout, "", layout_message);
/// @brief Define flag for quantization bits (default 16)
DEFINE_int32(qb, 16, gna_qb_message);
/// @brief Specify precision for all input layers of the network
DEFINE_string(ip, "", inputs_precision_message);
/// @brief Specify precision for all ouput layers of the network
DEFINE_string(op, "", outputs_precision_message);
/// @brief Specify precision for input and output layers by name.\n"
/// Example: -iop \"input:FP16, output:FP16\".\n"
/// Notice that quotes are required.\n"
/// Overwrites layout from ip and op options for specified layers.";
DEFINE_string(iop, "", iop_message);
/**
* @brief This function show a help message
*/
@@ -237,4 +262,7 @@ static void showUsage() {
std::cout << " -load_config " << load_config_message << std::endl;
#endif
std::cout << " -qb " << gna_qb_message << std::endl;
std::cout << " -ip <value> " << inputs_precision_message << std::endl;
std::cout << " -op <value> " << outputs_precision_message << std::endl;
std::cout << " -iop \"<value>\" " << iop_message << std::endl;
}

View File

@@ -67,6 +67,14 @@ bool ParseAndCheckCommandLine(int argc, char *argv[]) {
throw std::logic_error("only " + std::string(detailedCntReport) + " report type is supported for MULTI device");
}
bool isNetworkCompiled = fileExt(FLAGS_m) == "blob";
bool isPrecisionSet = !(FLAGS_ip.empty() && FLAGS_op.empty() && FLAGS_iop.empty());
if (isNetworkCompiled && isPrecisionSet) {
std::string err = std::string("Cannot set precision for a compiled network. ") +
std::string("Please re-compile your network with required precision using compile_tool");
throw std::logic_error(err);
}
return true;
}
@@ -380,6 +388,10 @@ int main(int argc, char *argv[]) {
item.second->setPrecision(app_inputs_info.at(item.first).precision);
}
}
processPrecision(cnnNetwork, FLAGS_ip, FLAGS_op, FLAGS_iop);
printInputAndOutputsInfo(cnnNetwork);
// ----------------- 7. Loading the model to the device --------------------------------------------------------
next_step();
startTime = Time::now();

View File

@@ -85,3 +85,240 @@ void parseInputFilesArguments(std::vector<std::string> &files) {
readInputFilesArguments(files, args.at(i));
}
}
namespace {
void splitStringList(const std::string& str, std::vector<std::string>& out, char delim) {
out.clear();
if (str.empty())
return;
std::istringstream istr(str);
std::string elem;
while (std::getline(istr, elem, delim)) {
if (elem.empty()) {
continue;
}
out.emplace_back(std::move(elem));
}
}
std::map<std::string, std::string> parseArgMap(std::string argMap) {
argMap.erase(std::remove_if(argMap.begin(), argMap.end(), ::isspace), argMap.end());
std::vector<std::string> pairs;
splitStringList(argMap, pairs, ',');
std::map<std::string, std::string> parsedMap;
for (auto&& pair : pairs) {
std::vector<std::string> keyValue;
splitStringList(pair, keyValue, ':');
if (keyValue.size() != 2) {
throw std::invalid_argument("Invalid key/value pair " + pair + ". Expected <layer_name>:<value>");
}
parsedMap[keyValue[0]] = keyValue[1];
}
return parsedMap;
}
using supported_precisions_t = std::unordered_map<std::string, InferenceEngine::Precision>;
InferenceEngine::Precision getPrecision(std::string value,
const supported_precisions_t& supported_precisions) {
std::transform(value.begin(), value.end(), value.begin(), ::toupper);
const auto precision = supported_precisions.find(value);
if (precision == supported_precisions.end()) {
throw std::logic_error("\"" + value + "\"" + " is not a valid precision");
}
return precision->second;
}
InferenceEngine::Precision getPrecision(const std::string& value) {
static const supported_precisions_t supported_precisions = {
{ "FP32", InferenceEngine::Precision::FP32 },
{ "FP16", InferenceEngine::Precision::FP16 },
{ "BF16", InferenceEngine::Precision::BF16 },
{ "U64", InferenceEngine::Precision::U64 },
{ "I64", InferenceEngine::Precision::I64 },
{ "U32", InferenceEngine::Precision::U32 },
{ "I32", InferenceEngine::Precision::I32 },
{ "U16", InferenceEngine::Precision::U16 },
{ "I16", InferenceEngine::Precision::I16 },
{ "U8", InferenceEngine::Precision::U8 },
{ "I8", InferenceEngine::Precision::I8 },
{ "BOOL", InferenceEngine::Precision::BOOL },
};
return getPrecision(value, supported_precisions);
}
void setPrecisions(const InferenceEngine::CNNNetwork& network, const std::string &iop) {
const auto user_precisions_map = parseArgMap(iop);
auto inputs = network.getInputsInfo();
auto outputs = network.getOutputsInfo();
for (auto&& item : user_precisions_map) {
const auto& layer_name = item.first;
const auto& user_precision = item.second;
const auto input = inputs.find(layer_name);
const auto output = outputs.find(layer_name);
if (input != inputs.end()) {
input->second->setPrecision(getPrecision(user_precision));
} else if (output != outputs.end()) {
output->second->setPrecision(getPrecision(user_precision));
} else {
throw std::logic_error(layer_name + " is not an input neither output");
}
}
}
} // namespace
void processPrecision(InferenceEngine::CNNNetwork& network, const std::string &ip, const std::string &op,
const std::string &iop) {
if (!ip.empty()) {
const auto user_precision = getPrecision(ip);
for (auto&& layer : network.getInputsInfo()) {
layer.second->setPrecision(user_precision);
}
}
if (!op.empty()) {
auto user_precision = getPrecision(op);
for (auto&& layer : network.getOutputsInfo()) {
layer.second->setPrecision(user_precision);
}
}
if (!iop.empty()) {
setPrecisions(network, iop);
}
}
namespace {
using supported_layouts_t = std::unordered_map<std::string, InferenceEngine::Layout>;
using matchLayoutToDims_t = std::unordered_map<size_t, size_t>;
InferenceEngine::Layout getLayout(std::string value,
const supported_layouts_t& supported_layouts) {
std::transform(value.begin(), value.end(), value.begin(), ::toupper);
const auto layout = supported_layouts.find(value);
if (layout == supported_layouts.end()) {
throw std::logic_error("\"" + value + "\"" + " is not a valid layout");
}
return layout->second;
}
InferenceEngine::Layout getLayout(const std::string& value) {
static const supported_layouts_t supported_layouts = {
{ "NCDHW", InferenceEngine::Layout::NCDHW },
{ "NDHWC", InferenceEngine::Layout::NDHWC },
{ "NCHW", InferenceEngine::Layout::NCHW },
{ "NHWC", InferenceEngine::Layout::NHWC },
{ "CHW", InferenceEngine::Layout::CHW },
{ "NC", InferenceEngine::Layout::NC },
{ "C", InferenceEngine::Layout::C },
};
return getLayout(value, supported_layouts);
}
bool isMatchLayoutToDims(InferenceEngine::Layout layout, size_t dimension) {
static const matchLayoutToDims_t matchLayoutToDims = {
{static_cast<size_t>(InferenceEngine::Layout::NCDHW), 5 },
{static_cast<size_t>(InferenceEngine::Layout::NDHWC), 5 },
{static_cast<size_t>(InferenceEngine::Layout::NCHW), 4 },
{static_cast<size_t>(InferenceEngine::Layout::NHWC), 4 },
{static_cast<size_t>(InferenceEngine::Layout::CHW), 3 },
{static_cast<size_t>(InferenceEngine::Layout::NC), 2 },
{static_cast<size_t>(InferenceEngine::Layout::C), 1 }
};
const auto dims = matchLayoutToDims.find(static_cast<size_t>(layout));
if (dims == matchLayoutToDims.end()) {
throw std::logic_error("Layout is not valid.");
}
return dimension == dims->second;
}
void setLayouts(const InferenceEngine::CNNNetwork& network, const std::string iol) {
const auto user_layouts_map = parseArgMap(iol);
auto inputs = network.getInputsInfo();
auto outputs = network.getOutputsInfo();
for (auto&& item : user_layouts_map) {
const auto& layer_name = item.first;
const auto& user_layout = getLayout(item.second);
const auto input = inputs.find(layer_name);
const auto output = outputs.find(layer_name);
if (input != inputs.end()) {
if (!isMatchLayoutToDims(user_layout, input->second->getTensorDesc().getDims().size())) {
throw std::logic_error(item.second + " layout is not applicable to " + layer_name);
}
input->second->setLayout(user_layout);
} else if (output != outputs.end()) {
if (!isMatchLayoutToDims(user_layout, output->second->getTensorDesc().getDims().size())) {
throw std::logic_error(item.second + " layout is not applicable to " + layer_name);
}
output->second->setLayout(user_layout);
} else {
throw std::logic_error(layer_name + " is not an input neither output");
}
}
}
} // namespace
void processLayout(InferenceEngine::CNNNetwork& network, const std::string& il, const std::string& ol, const std::string& iol) {
if (!il.empty()) {
const auto layout = getLayout(il);
for (auto&& layer : network.getInputsInfo()) {
if (isMatchLayoutToDims(layout, layer.second->getTensorDesc().getDims().size())) {
layer.second->setLayout(layout);
}
}
}
if (!ol.empty()) {
const auto layout = getLayout(ol);
for (auto&& layer : network.getOutputsInfo()) {
if (isMatchLayoutToDims(layout, layer.second->getTensorDesc().getDims().size())) {
layer.second->setLayout(layout);
}
}
}
if (!iol.empty()) {
setLayouts(network, iol);
}
}
void printInputAndOutputsInfo(const InferenceEngine::CNNNetwork& network) {
std::cout << "Network inputs:" << std::endl;
for (auto&& layer : network.getInputsInfo()) {
std::cout << " " << layer.first << " : " << layer.second->getPrecision() << " / " << layer.second->getLayout() << std::endl;
}
std::cout << "Network outputs:" << std::endl;
for (auto&& layer : network.getOutputsInfo()) {
std::cout << " " << layer.first << " : " << layer.second->getPrecision() << " / " << layer.second->getLayout() << std::endl;
}
}

View File

@@ -1,20 +1,6 @@
/*
* Copyright 2017-2019 Intel Corporation.
* The source code, information and material ("Material") contained herein is
* owned by Intel Corporation or its suppliers or licensors, and title to such
* Material remains with Intel Corporation or its suppliers or licensors.
* The Material contains proprietary information of Intel or its suppliers and
* licensors. The Material is protected by worldwide copyright laws and treaty
* provisions.
* No part of the Material may be used, copied, reproduced, modified, published,
* uploaded, posted, transmitted, distributed or disclosed in any way without
* Intel's prior express written permission. No license under any patent,
* copyright or other intellectual property rights in the Material is granted to
* or conferred upon you, either expressly, by implication, inducement, estoppel
* or otherwise.
* Any license under such intellectual property rights must be express and
* approved by Intel in writing.
*/
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "XLinkStringUtils.h"

View File

@@ -1,20 +1,6 @@
/*
* Copyright 2017-2019 Intel Corporation.
* The source code, information and material ("Material") contained herein is
* owned by Intel Corporation or its suppliers or licensors, and title to such
* Material remains with Intel Corporation or its suppliers or licensors.
* The Material contains proprietary information of Intel or its suppliers and
* licensors. The Material is protected by worldwide copyright laws and treaty
* provisions.
* No part of the Material may be used, copied, reproduced, modified, published,
* uploaded, posted, transmitted, distributed or disclosed in any way without
* Intel's prior express written permission. No license under any patent,
* copyright or other intellectual property rights in the Material is granted to
* or conferred upon you, either expressly, by implication, inducement, estoppel
* or otherwise.
* Any license under such intellectual property rights must be express and
* approved by Intel in writing.
*/
// Copyright (C) 2018-2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "mvnc_data.h"
#include "mvnc_tool.h"

View File

@@ -18,7 +18,9 @@
#include <vpu/vpu_plugin_config.hpp>
#include <vpu/private_plugin_config.hpp>
#include <vpu/utils/string.hpp>
#include "samples/common.hpp"
#include "samples/args_helper.hpp"
static constexpr char help_message[] =
"Optional. Print the usage message.";
@@ -208,106 +210,6 @@ IE_SUPPRESS_DEPRECATED_END
return config;
}
static std::map<std::string, std::string> parseArgMap(std::string argMap) {
argMap.erase(std::remove_if(argMap.begin(), argMap.end(), ::isspace), argMap.end());
std::vector<std::string> pairs;
vpu::splitStringList(argMap, pairs, ',');
std::map<std::string, std::string> parsedMap;
for (auto&& pair : pairs) {
std::vector<std::string> keyValue;
vpu::splitStringList(pair, keyValue, ':');
if (keyValue.size() != 2) {
throw std::invalid_argument("Invalid key/value pair " + pair + ". Expected <layer_name>:<value>");
}
parsedMap[keyValue[0]] = keyValue[1];
}
return parsedMap;
}
using supported_precisions_t = std::unordered_map<std::string, InferenceEngine::Precision>;
using supported_layouts_t = std::unordered_map<std::string, InferenceEngine::Layout>;
using matchLayoutToDims_t = std::unordered_map<size_t, size_t>;
static InferenceEngine::Layout getLayout(std::string value,
const supported_layouts_t& supported_layouts) {
std::transform(value.begin(), value.end(), value.begin(), ::toupper);
const auto layout = supported_layouts.find(value);
if (layout == supported_layouts.end()) {
throw std::logic_error("\"" + value + "\"" + " is not a valid layout");
}
return layout->second;
}
static InferenceEngine::Layout getLayout(const std::string& value) {
static const supported_layouts_t supported_layouts = {
{ "NCDHW", InferenceEngine::Layout::NCDHW },
{ "NDHWC", InferenceEngine::Layout::NDHWC },
{ "NCHW", InferenceEngine::Layout::NCHW },
{ "NHWC", InferenceEngine::Layout::NHWC },
{ "CHW", InferenceEngine::Layout::CHW },
{ "NC", InferenceEngine::Layout::NC },
{ "C", InferenceEngine::Layout::C },
};
return getLayout(value, supported_layouts);
}
static bool isMatchLayoutToDims(InferenceEngine::Layout layout, size_t dimension) {
static const matchLayoutToDims_t matchLayoutToDims = {
{static_cast<size_t>(InferenceEngine::Layout::NCDHW), 5 },
{static_cast<size_t>(InferenceEngine::Layout::NDHWC), 5 },
{static_cast<size_t>(InferenceEngine::Layout::NCHW), 4 },
{static_cast<size_t>(InferenceEngine::Layout::NHWC), 4 },
{static_cast<size_t>(InferenceEngine::Layout::CHW), 3 },
{static_cast<size_t>(InferenceEngine::Layout::NC), 2 },
{static_cast<size_t>(InferenceEngine::Layout::C), 1 }
};
const auto dims = matchLayoutToDims.find(static_cast<size_t>(layout));
if (dims == matchLayoutToDims.end()) {
throw std::logic_error("Layout is not valid.");
}
return dimension == dims->second;
}
static InferenceEngine::Precision getPrecision(std::string value,
const supported_precisions_t& supported_precisions) {
std::transform(value.begin(), value.end(), value.begin(), ::toupper);
const auto precision = supported_precisions.find(value);
if (precision == supported_precisions.end()) {
throw std::logic_error("\"" + value + "\"" + " is not a valid precision");
}
return precision->second;
}
static InferenceEngine::Precision getPrecision(const std::string& value) {
static const supported_precisions_t supported_precisions = {
{ "FP32", InferenceEngine::Precision::FP32 },
{ "FP16", InferenceEngine::Precision::FP16 },
{ "BF16", InferenceEngine::Precision::BF16 },
{ "U64", InferenceEngine::Precision::U64 },
{ "I64", InferenceEngine::Precision::I64 },
{ "U32", InferenceEngine::Precision::U32 },
{ "I32", InferenceEngine::Precision::I32 },
{ "U16", InferenceEngine::Precision::U16 },
{ "I16", InferenceEngine::Precision::I16 },
{ "U8", InferenceEngine::Precision::U8 },
{ "I8", InferenceEngine::Precision::I8 },
{ "BOOL", InferenceEngine::Precision::BOOL },
};
return getPrecision(value, supported_precisions);
}
bool isFP16(InferenceEngine::Precision precision) {
return precision == InferenceEngine::Precision::FP16;
}
@@ -320,29 +222,6 @@ bool isFloat(InferenceEngine::Precision precision) {
return isFP16(precision) || isFP32(precision);
}
static void setPrecisions(const InferenceEngine::CNNNetwork& network) {
const auto user_precisions_map = parseArgMap(FLAGS_iop);
auto inputs = network.getInputsInfo();
auto outputs = network.getOutputsInfo();
for (auto&& item : user_precisions_map) {
const auto& layer_name = item.first;
const auto& user_precision = item.second;
const auto input = inputs.find(layer_name);
const auto output = outputs.find(layer_name);
if (input != inputs.end()) {
input->second->setPrecision(getPrecision(user_precision));
} else if (output != outputs.end()) {
output->second->setPrecision(getPrecision(user_precision));
} else {
throw std::logic_error(layer_name + " is not an input neither output");
}
}
}
static void setDefaultIO(InferenceEngine::CNNNetwork& network) {
const bool isMYRIAD = FLAGS_d.find("MYRIAD") != std::string::npos;
const bool isVPUX = FLAGS_d.find("VPUX") != std::string::npos;
@@ -377,81 +256,6 @@ static void setDefaultIO(InferenceEngine::CNNNetwork& network) {
}
}
static void processPrecisions(InferenceEngine::CNNNetwork& network) {
if (!FLAGS_ip.empty()) {
const auto user_precision = getPrecision(FLAGS_ip);
for (auto&& layer : network.getInputsInfo()) {
layer.second->setPrecision(user_precision);
}
}
if (!FLAGS_op.empty()) {
auto user_precision = getPrecision(FLAGS_op);
for (auto&& layer : network.getOutputsInfo()) {
layer.second->setPrecision(user_precision);
}
}
if (!FLAGS_iop.empty()) {
setPrecisions(network);
}
}
static void setLayouts(const InferenceEngine::CNNNetwork& network) {
const auto user_layouts_map = parseArgMap(FLAGS_iol);
auto inputs = network.getInputsInfo();
auto outputs = network.getOutputsInfo();
for (auto&& item : user_layouts_map) {
const auto& layer_name = item.first;
const auto& user_layout = getLayout(item.second);
const auto input = inputs.find(layer_name);
const auto output = outputs.find(layer_name);
if (input != inputs.end()) {
if (!isMatchLayoutToDims(user_layout, input->second->getTensorDesc().getDims().size())) {
throw std::logic_error(item.second + " layout is not applicable to " + layer_name);
}
input->second->setLayout(user_layout);
} else if (output != outputs.end()) {
if (!isMatchLayoutToDims(user_layout, output->second->getTensorDesc().getDims().size())) {
throw std::logic_error(item.second + " layout is not applicable to " + layer_name);
}
output->second->setLayout(user_layout);
} else {
throw std::logic_error(layer_name + " is not an input neither output");
}
}
}
static void processLayout(InferenceEngine::CNNNetwork& network) {
if (!FLAGS_il.empty()) {
const auto layout = getLayout(FLAGS_il);
for (auto&& layer : network.getInputsInfo()) {
if (isMatchLayoutToDims(layout, layer.second->getTensorDesc().getDims().size())) {
layer.second->setLayout(layout);
}
}
}
if (!FLAGS_ol.empty()) {
const auto layout = getLayout(FLAGS_ol);
for (auto&& layer : network.getOutputsInfo()) {
if (isMatchLayoutToDims(layout, layer.second->getTensorDesc().getDims().size())) {
layer.second->setLayout(layout);
}
}
}
if (!FLAGS_iol.empty()) {
setLayouts(network);
}
}
std::string getFileNameFromPath(const std::string& path,
#if defined(_WIN32)
const std::string& sep = "\\") {
@@ -487,18 +291,10 @@ int main(int argc, char* argv[]) {
auto network = ie.ReadNetwork(FLAGS_m);
setDefaultIO(network);
processPrecisions(network);
processLayout(network);
processPrecision(network, FLAGS_ip, FLAGS_op, FLAGS_iop);
processLayout(network, FLAGS_il, FLAGS_ol, FLAGS_iol);
std::cout << "Network inputs:" << std::endl;
for (auto&& layer : network.getInputsInfo()) {
std::cout << " " << layer.first << " : " << layer.second->getPrecision() << " / " << layer.second->getLayout() << std::endl;
}
std::cout << "Network outputs:" << std::endl;
for (auto&& layer : network.getOutputsInfo()) {
std::cout << " " << layer.first << " : " << layer.second->getPrecision() << " / " << layer.second->getLayout() << std::endl;
}
std::cout << std::endl;
printInputAndOutputsInfo(network);
auto timeBeforeLoadNetwork = std::chrono::steady_clock::now();
auto executableNetwork = ie.LoadNetwork(network, FLAGS_d, configure());