Files
openvino/inference-engine/samples/benchmark_app/main.cpp

831 lines
39 KiB
C++
Raw Normal View History

// Copyright (C) 2018-2021 Intel Corporation
2018-11-23 16:19:43 +03:00
// SPDX-License-Identifier: Apache-2.0
//
#include <algorithm>
#include <chrono>
#include <gna/gna_config.hpp>
#include <gpu/gpu_config.hpp>
#include <inference_engine.hpp>
#include <map>
#include <memory>
#include <samples/args_helper.hpp>
2018-11-23 16:19:43 +03:00
#include <samples/common.hpp>
#include <samples/slog.hpp>
#include <string>
#include <utility>
#include <vector>
#include <vpu/vpu_plugin_config.hpp>
2018-11-23 16:19:43 +03:00
2019-04-12 18:25:53 +03:00
#include "benchmark_app.hpp"
#include "infer_request_wrap.hpp"
#include "inputs_filling.hpp"
2019-04-12 18:25:53 +03:00
#include "progress_bar.hpp"
#include "remote_blobs_filling.hpp"
2019-04-12 18:25:53 +03:00
#include "statistics_report.hpp"
2019-08-09 19:02:42 +03:00
#include "utils.hpp"
2018-11-23 16:19:43 +03:00
using namespace InferenceEngine;
2019-08-09 19:02:42 +03:00
static const size_t progressBarDefaultTotalCount = 1000;
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
uint64_t getDurationInMilliseconds(uint32_t duration) {
return duration * 1000LL;
}
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
uint64_t getDurationInNanoseconds(uint32_t duration) {
return duration * 1000000000LL;
}
2018-11-23 16:19:43 +03:00
bool ParseAndCheckCommandLine(int argc, char* argv[]) {
// ---------------------------Parsing and validating input
// arguments--------------------------------------
2019-04-12 18:25:53 +03:00
slog::info << "Parsing input parameters" << slog::endl;
gflags::ParseCommandLineNonHelpFlags(&argc, &argv, true);
2019-08-09 19:02:42 +03:00
if (FLAGS_help || FLAGS_h) {
2019-04-12 18:25:53 +03:00
showUsage();
2019-08-09 19:02:42 +03:00
showAvailableDevices();
2019-04-12 18:25:53 +03:00
return false;
}
2018-11-23 16:19:43 +03:00
2019-04-12 18:25:53 +03:00
if (FLAGS_m.empty()) {
showUsage();
2019-08-09 19:02:42 +03:00
throw std::logic_error("Model is required but not set. Please set -m option.");
2019-04-12 18:25:53 +03:00
}
2018-11-23 16:19:43 +03:00
if (FLAGS_latency_percentile > 100 || FLAGS_latency_percentile < 1) {
showUsage();
throw std::logic_error("The percentile value is incorrect. The applicable values range is [1, 100].");
}
2019-04-12 18:25:53 +03:00
if (FLAGS_api != "async" && FLAGS_api != "sync") {
2019-08-09 19:02:42 +03:00
throw std::logic_error("Incorrect API. Please set -api option to `sync` or `async` value.");
2019-04-12 18:25:53 +03:00
}
OV Performance Hints (CPU and GPU logic for selecting the actual configs), while AUTO/MULTI are passing them thru) (#6993) * rebasing the perf-modes-2021.3 to the 2021.4 Caveats: the (explicit) setting #streams is not disabled (as it was before for experiments with DLBenchmark), and the logic slighlty differ (streamsSet) (cherry picked from commit 1ae1edc0ed70fdea40f528fdaf8d00a9904d2a5c) * overriding streams (to force the TPUT mode to the DLBenchnark) (cherry picked from commit 7f506cda31abf35ac293d0dce32f602a0188c619) * disabling reducing #streams to fully mimic baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments) (cherry picked from commit 85073dd1dd2c7d43a89c37c8f646313f6ddfc650) * clang/identation (cherry picked from commit 050a4155a923cee294c8689d685b39247b7a172a) * splitting the Transformation to general and CPU specific. Now hopefully,this fully mimics the baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments), as the streams reduce num (as well as early exit on GRU/LSTM/TensorIterator) is deisabled (cherry picked from commit e98b2c1a67f2542a686543594b75b575ef515196) * disabling GRU/LSTM/TI + reducing of streams + 5D considered compute-limited only for int8 (cherry picked from commit 32b8d80dee18685ebf3d069bb4cd2172af7363b7) * refactored to avoid compute_limited_ratio, reverted the reducing #streams, removed LSTM from limitations (cherry picked from commit f2b972171b29cf599aae2407ceec2e6adb67e4e9) * isa-based threshold logic (cherry picked from commit b218457e1a93fcb3374eb9da948fdad2175ec33a) * mode->hint (cherry picked from commit ec20aa8ecaf3222f2a6fdfe9153cf6c9dfdd6a54) * optional PERFORMANCE_HINT_NUM_REQUESTS (cherry picked from commit 5a3883e3f36e7928c6391094ae10711c8e4c3b5c) * moving the perfHints to the common OV config class + initial tests (CPU only, as the actual AUTO/MULTI should be accommodated on the master) (cherry picked from commit (then fixed)45bafe7d527f466507dea0693aeed51be4ebf776) * AUTO support for PerfHints * MULTI support for PerfHints * Enabling Perf hints for the GPU plugin * brushing settings output a bit * disabling "throughput" perf hint being default (until OV 2.0) * uncommenting the logic which was disabled to force the DLBenchmark to use the throughput mode by default * removing dead and experimental code, and debug printfs * clang/code-style * code-review remarks * Moved the output of the actual params that the hint produced to the right place * aligning MULTI's GetConfig beh to HETERO's as captured in the preso (CVS-59960) ratified with the ArchForum * clang * benchmark_app brushing * Update inference-engine/samples/benchmark_app/README.md * propagating the perf hints thru one more scenario in the merged AUTO-MULTI * fixed mispint * Python benchmark_app update for perf hints * addresssing reviewers comments on the python benchmark_app * simplifying/brushing logic a bit * refactor the heuristic to the separate file (to be shared with iGPU soon) * refactor conversion of modes to the specific GPU config per feedback from Vladimir
2021-09-13 15:40:36 +03:00
if (!FLAGS_hint.empty() && FLAGS_hint != "throughput" && FLAGS_hint != "tput" && FLAGS_hint != "latency") {
throw std::logic_error("Incorrect performance hint. Please set -hint option to"
"either `throughput`(tput) or `latency' value.");
}
if (!FLAGS_report_type.empty() && FLAGS_report_type != noCntReport && FLAGS_report_type != averageCntReport &&
FLAGS_report_type != detailedCntReport) {
std::string err = "only " + std::string(noCntReport) + "/" + std::string(averageCntReport) + "/" +
std::string(detailedCntReport) +
" report types are supported (invalid -report_type option value)";
2019-04-12 18:25:53 +03:00
throw std::logic_error(err);
}
2019-10-04 19:26:43 +03:00
if ((FLAGS_report_type == averageCntReport) && ((FLAGS_d.find("MULTI") != std::string::npos))) {
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);
}
2019-04-12 18:25:53 +03:00
return true;
}
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
static void next_step(const std::string additional_info = "") {
static size_t step_id = 0;
static const std::map<size_t, std::string> step_names = {
{1, "Parsing and validating input arguments"},
{2, "Loading Inference Engine"},
{3, "Setting device configuration"},
{4, "Reading network files"},
{5, "Resizing network to match image sizes and given batch"},
{6, "Configuring input of the model"},
{7, "Loading the model to the device"},
{8, "Setting optimal runtime parameters"},
{9, "Creating infer requests and filling input blobs with images"},
{10, "Measuring performance"},
{11, "Dumping statistics report"}};
2019-08-09 19:02:42 +03:00
step_id++;
if (step_names.count(step_id) == 0)
IE_THROW() << "Step ID " << step_id << " is out of total steps number " << step_names.size();
2019-08-09 19:02:42 +03:00
std::cout << "[Step " << step_id << "/" << step_names.size() << "] " << step_names.at(step_id)
<< (additional_info.empty() ? "" : " (" + additional_info + ")") << std::endl;
}
2019-10-04 19:26:43 +03:00
template <typename T>
T getMedianValue(const std::vector<T>& vec, std::size_t percentile) {
2019-10-04 19:26:43 +03:00
std::vector<T> sortedVec(vec);
std::sort(sortedVec.begin(), sortedVec.end());
return sortedVec[(sortedVec.size() / 100) * percentile];
2019-10-04 19:26:43 +03:00
}
2019-04-12 18:25:53 +03:00
/**
* @brief The entry point of the benchmark application
*/
int main(int argc, char* argv[]) {
2019-10-04 19:26:43 +03:00
std::shared_ptr<StatisticsReport> statistics;
2019-04-12 18:25:53 +03:00
try {
2020-02-11 22:48:49 +03:00
ExecutableNetwork exeNetwork;
// ----------------- 1. Parsing and validating input arguments
// -------------------------------------------------
2019-08-09 19:02:42 +03:00
next_step();
2019-04-12 18:25:53 +03:00
if (!ParseAndCheckCommandLine(argc, argv)) {
return 0;
2018-11-23 16:19:43 +03:00
}
2020-02-11 22:48:49 +03:00
bool isNetworkCompiled = fileExt(FLAGS_m) == "blob";
if (isNetworkCompiled) {
slog::info << "Network is compiled" << slog::endl;
}
std::vector<gflags::CommandLineFlagInfo> flags;
StatisticsReport::Parameters command_line_arguments;
gflags::GetAllFlags(&flags);
for (auto& flag : flags) {
if (!flag.is_default) {
command_line_arguments.push_back({flag.name, flag.current_value});
2019-10-04 19:26:43 +03:00
}
}
if (!FLAGS_report_type.empty()) {
statistics =
std::make_shared<StatisticsReport>(StatisticsReport::Config{FLAGS_report_type, FLAGS_report_folder});
2019-10-04 19:26:43 +03:00
statistics->addParameters(StatisticsReport::Category::COMMAND_LINE_PARAMETERS, command_line_arguments);
}
auto isFlagSetInCommandLine = [&command_line_arguments](const std::string& name) {
return (std::find_if(command_line_arguments.begin(),
command_line_arguments.end(),
[name](const std::pair<std::string, std::string>& p) {
return p.first == name;
}) != command_line_arguments.end());
};
std::string device_name = FLAGS_d;
// Parse devices
auto devices = parseDevices(device_name);
2019-10-04 19:26:43 +03:00
// Parse nstreams per device
std::map<std::string, std::string> device_nstreams = parseNStreamsValuePerDevice(devices, FLAGS_nstreams);
// Load device config file if specified
std::map<std::string, std::map<std::string, std::string>> config;
#ifdef USE_OPENCV
if (!FLAGS_load_config.empty()) {
load_config(FLAGS_load_config, config);
}
#endif
2019-04-12 18:25:53 +03:00
/** This vector stores paths to the processed images **/
2019-08-09 19:02:42 +03:00
std::vector<std::string> inputFiles;
parseInputFilesArguments(inputFiles);
2018-11-23 16:19:43 +03:00
// ----------------- 2. Loading the Inference Engine
// -----------------------------------------------------------
2019-08-09 19:02:42 +03:00
next_step();
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
Core ie;
2020-02-11 22:48:49 +03:00
if (FLAGS_d.find("CPU") != std::string::npos && !FLAGS_l.empty()) {
// CPU (MKLDNN) extensions is loaded as a shared library and passed as a
// pointer to base extension
2021-03-05 12:08:01 +03:00
const auto extension_ptr = std::make_shared<InferenceEngine::Extension>(FLAGS_l);
ie.AddExtension(extension_ptr);
2020-02-11 22:48:49 +03:00
slog::info << "CPU (MKLDNN) extensions is loaded " << FLAGS_l << slog::endl;
}
// Load clDNN Extensions
if ((FLAGS_d.find("GPU") != std::string::npos) && !FLAGS_c.empty()) {
// Override config if command line parameter is specified
if (!config.count("GPU"))
config["GPU"] = {};
config["GPU"][CONFIG_KEY(CONFIG_FILE)] = FLAGS_c;
}
if (config.count("GPU") && config.at("GPU").count(CONFIG_KEY(CONFIG_FILE))) {
auto ext = config.at("GPU").at(CONFIG_KEY(CONFIG_FILE));
ie.SetConfig({{CONFIG_KEY(CONFIG_FILE), ext}}, "GPU");
slog::info << "GPU extensions is loaded " << ext << slog::endl;
2018-11-23 16:19:43 +03:00
}
2019-08-09 19:02:42 +03:00
slog::info << "InferenceEngine: " << GetInferenceEngineVersion() << slog::endl;
slog::info << "Device info: " << slog::endl;
std::cout << ie.GetVersions(device_name) << std::endl;
2018-11-23 16:19:43 +03:00
// ----------------- 3. Setting device configuration
// -----------------------------------------------------------
2019-08-09 19:02:42 +03:00
next_step();
OV Performance Hints (CPU and GPU logic for selecting the actual configs), while AUTO/MULTI are passing them thru) (#6993) * rebasing the perf-modes-2021.3 to the 2021.4 Caveats: the (explicit) setting #streams is not disabled (as it was before for experiments with DLBenchmark), and the logic slighlty differ (streamsSet) (cherry picked from commit 1ae1edc0ed70fdea40f528fdaf8d00a9904d2a5c) * overriding streams (to force the TPUT mode to the DLBenchnark) (cherry picked from commit 7f506cda31abf35ac293d0dce32f602a0188c619) * disabling reducing #streams to fully mimic baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments) (cherry picked from commit 85073dd1dd2c7d43a89c37c8f646313f6ddfc650) * clang/identation (cherry picked from commit 050a4155a923cee294c8689d685b39247b7a172a) * splitting the Transformation to general and CPU specific. Now hopefully,this fully mimics the baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments), as the streams reduce num (as well as early exit on GRU/LSTM/TensorIterator) is deisabled (cherry picked from commit e98b2c1a67f2542a686543594b75b575ef515196) * disabling GRU/LSTM/TI + reducing of streams + 5D considered compute-limited only for int8 (cherry picked from commit 32b8d80dee18685ebf3d069bb4cd2172af7363b7) * refactored to avoid compute_limited_ratio, reverted the reducing #streams, removed LSTM from limitations (cherry picked from commit f2b972171b29cf599aae2407ceec2e6adb67e4e9) * isa-based threshold logic (cherry picked from commit b218457e1a93fcb3374eb9da948fdad2175ec33a) * mode->hint (cherry picked from commit ec20aa8ecaf3222f2a6fdfe9153cf6c9dfdd6a54) * optional PERFORMANCE_HINT_NUM_REQUESTS (cherry picked from commit 5a3883e3f36e7928c6391094ae10711c8e4c3b5c) * moving the perfHints to the common OV config class + initial tests (CPU only, as the actual AUTO/MULTI should be accommodated on the master) (cherry picked from commit (then fixed)45bafe7d527f466507dea0693aeed51be4ebf776) * AUTO support for PerfHints * MULTI support for PerfHints * Enabling Perf hints for the GPU plugin * brushing settings output a bit * disabling "throughput" perf hint being default (until OV 2.0) * uncommenting the logic which was disabled to force the DLBenchmark to use the throughput mode by default * removing dead and experimental code, and debug printfs * clang/code-style * code-review remarks * Moved the output of the actual params that the hint produced to the right place * aligning MULTI's GetConfig beh to HETERO's as captured in the preso (CVS-59960) ratified with the ArchForum * clang * benchmark_app brushing * Update inference-engine/samples/benchmark_app/README.md * propagating the perf hints thru one more scenario in the merged AUTO-MULTI * fixed mispint * Python benchmark_app update for perf hints * addresssing reviewers comments on the python benchmark_app * simplifying/brushing logic a bit * refactor the heuristic to the separate file (to be shared with iGPU soon) * refactor conversion of modes to the specific GPU config per feedback from Vladimir
2021-09-13 15:40:36 +03:00
std::string ov_perf_hint;
if (FLAGS_hint == "throughput" || FLAGS_hint == "tput")
ov_perf_hint = CONFIG_VALUE(THROUGHPUT);
else if (FLAGS_hint == "latency")
ov_perf_hint = CONFIG_VALUE(LATENCY);
2019-08-09 19:02:42 +03:00
auto getDeviceTypeFromName = [](std::string device) -> std::string {
return device.substr(0, device.find_first_of(".("));
};
// Set default values from dumped config
std::set<std::string> default_devices;
for (auto& device : devices) {
auto default_config = config.find(getDeviceTypeFromName(device));
if (default_config != config.end()) {
if (!config.count(device)) {
config[device] = default_config->second;
default_devices.emplace(default_config->first);
}
}
}
for (auto& device : default_devices) {
config.erase(device);
}
bool perf_counts = false;
// Update config per device according to command line parameters
for (auto& device : devices) {
if (!config.count(device))
config[device] = {};
std::map<std::string, std::string>& device_config = config.at(device);
OV Performance Hints (CPU and GPU logic for selecting the actual configs), while AUTO/MULTI are passing them thru) (#6993) * rebasing the perf-modes-2021.3 to the 2021.4 Caveats: the (explicit) setting #streams is not disabled (as it was before for experiments with DLBenchmark), and the logic slighlty differ (streamsSet) (cherry picked from commit 1ae1edc0ed70fdea40f528fdaf8d00a9904d2a5c) * overriding streams (to force the TPUT mode to the DLBenchnark) (cherry picked from commit 7f506cda31abf35ac293d0dce32f602a0188c619) * disabling reducing #streams to fully mimic baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments) (cherry picked from commit 85073dd1dd2c7d43a89c37c8f646313f6ddfc650) * clang/identation (cherry picked from commit 050a4155a923cee294c8689d685b39247b7a172a) * splitting the Transformation to general and CPU specific. Now hopefully,this fully mimics the baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments), as the streams reduce num (as well as early exit on GRU/LSTM/TensorIterator) is deisabled (cherry picked from commit e98b2c1a67f2542a686543594b75b575ef515196) * disabling GRU/LSTM/TI + reducing of streams + 5D considered compute-limited only for int8 (cherry picked from commit 32b8d80dee18685ebf3d069bb4cd2172af7363b7) * refactored to avoid compute_limited_ratio, reverted the reducing #streams, removed LSTM from limitations (cherry picked from commit f2b972171b29cf599aae2407ceec2e6adb67e4e9) * isa-based threshold logic (cherry picked from commit b218457e1a93fcb3374eb9da948fdad2175ec33a) * mode->hint (cherry picked from commit ec20aa8ecaf3222f2a6fdfe9153cf6c9dfdd6a54) * optional PERFORMANCE_HINT_NUM_REQUESTS (cherry picked from commit 5a3883e3f36e7928c6391094ae10711c8e4c3b5c) * moving the perfHints to the common OV config class + initial tests (CPU only, as the actual AUTO/MULTI should be accommodated on the master) (cherry picked from commit (then fixed)45bafe7d527f466507dea0693aeed51be4ebf776) * AUTO support for PerfHints * MULTI support for PerfHints * Enabling Perf hints for the GPU plugin * brushing settings output a bit * disabling "throughput" perf hint being default (until OV 2.0) * uncommenting the logic which was disabled to force the DLBenchmark to use the throughput mode by default * removing dead and experimental code, and debug printfs * clang/code-style * code-review remarks * Moved the output of the actual params that the hint produced to the right place * aligning MULTI's GetConfig beh to HETERO's as captured in the preso (CVS-59960) ratified with the ArchForum * clang * benchmark_app brushing * Update inference-engine/samples/benchmark_app/README.md * propagating the perf hints thru one more scenario in the merged AUTO-MULTI * fixed mispint * Python benchmark_app update for perf hints * addresssing reviewers comments on the python benchmark_app * simplifying/brushing logic a bit * refactor the heuristic to the separate file (to be shared with iGPU soon) * refactor conversion of modes to the specific GPU config per feedback from Vladimir
2021-09-13 15:40:36 +03:00
// high-level performance modes
if (!ov_perf_hint.empty()) {
device_config[CONFIG_KEY(PERFORMANCE_HINT)] = ov_perf_hint;
if (FLAGS_nireq != 0)
device_config[CONFIG_KEY(PERFORMANCE_HINT_NUM_REQUESTS)] = std::to_string(FLAGS_nireq);
}
// Set performance counter
if (isFlagSetInCommandLine("pc")) {
// set to user defined value
device_config[CONFIG_KEY(PERF_COUNT)] = FLAGS_pc ? CONFIG_VALUE(YES) : CONFIG_VALUE(NO);
} else if (device_config.count(CONFIG_KEY(PERF_COUNT)) &&
(device_config.at(CONFIG_KEY(PERF_COUNT)) == "YES")) {
slog::warn << "Performance counters for " << device
<< " device is turned on. To print results use -pc option." << slog::endl;
} else if (FLAGS_report_type == detailedCntReport || FLAGS_report_type == averageCntReport) {
slog::warn << "Turn on performance counters for " << device << " device since report type is "
<< FLAGS_report_type << "." << slog::endl;
device_config[CONFIG_KEY(PERF_COUNT)] = CONFIG_VALUE(YES);
} else if (!FLAGS_exec_graph_path.empty()) {
slog::warn << "Turn on performance counters for " << device << " device due to execution graph dumping."
<< slog::endl;
device_config[CONFIG_KEY(PERF_COUNT)] = CONFIG_VALUE(YES);
} else {
// set to default value
device_config[CONFIG_KEY(PERF_COUNT)] = FLAGS_pc ? CONFIG_VALUE(YES) : CONFIG_VALUE(NO);
2020-04-13 21:17:23 +03:00
}
perf_counts = (device_config.at(CONFIG_KEY(PERF_COUNT)) == CONFIG_VALUE(YES)) ? true : perf_counts;
OV Performance Hints (CPU and GPU logic for selecting the actual configs), while AUTO/MULTI are passing them thru) (#6993) * rebasing the perf-modes-2021.3 to the 2021.4 Caveats: the (explicit) setting #streams is not disabled (as it was before for experiments with DLBenchmark), and the logic slighlty differ (streamsSet) (cherry picked from commit 1ae1edc0ed70fdea40f528fdaf8d00a9904d2a5c) * overriding streams (to force the TPUT mode to the DLBenchnark) (cherry picked from commit 7f506cda31abf35ac293d0dce32f602a0188c619) * disabling reducing #streams to fully mimic baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments) (cherry picked from commit 85073dd1dd2c7d43a89c37c8f646313f6ddfc650) * clang/identation (cherry picked from commit 050a4155a923cee294c8689d685b39247b7a172a) * splitting the Transformation to general and CPU specific. Now hopefully,this fully mimics the baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments), as the streams reduce num (as well as early exit on GRU/LSTM/TensorIterator) is deisabled (cherry picked from commit e98b2c1a67f2542a686543594b75b575ef515196) * disabling GRU/LSTM/TI + reducing of streams + 5D considered compute-limited only for int8 (cherry picked from commit 32b8d80dee18685ebf3d069bb4cd2172af7363b7) * refactored to avoid compute_limited_ratio, reverted the reducing #streams, removed LSTM from limitations (cherry picked from commit f2b972171b29cf599aae2407ceec2e6adb67e4e9) * isa-based threshold logic (cherry picked from commit b218457e1a93fcb3374eb9da948fdad2175ec33a) * mode->hint (cherry picked from commit ec20aa8ecaf3222f2a6fdfe9153cf6c9dfdd6a54) * optional PERFORMANCE_HINT_NUM_REQUESTS (cherry picked from commit 5a3883e3f36e7928c6391094ae10711c8e4c3b5c) * moving the perfHints to the common OV config class + initial tests (CPU only, as the actual AUTO/MULTI should be accommodated on the master) (cherry picked from commit (then fixed)45bafe7d527f466507dea0693aeed51be4ebf776) * AUTO support for PerfHints * MULTI support for PerfHints * Enabling Perf hints for the GPU plugin * brushing settings output a bit * disabling "throughput" perf hint being default (until OV 2.0) * uncommenting the logic which was disabled to force the DLBenchmark to use the throughput mode by default * removing dead and experimental code, and debug printfs * clang/code-style * code-review remarks * Moved the output of the actual params that the hint produced to the right place * aligning MULTI's GetConfig beh to HETERO's as captured in the preso (CVS-59960) ratified with the ArchForum * clang * benchmark_app brushing * Update inference-engine/samples/benchmark_app/README.md * propagating the perf hints thru one more scenario in the merged AUTO-MULTI * fixed mispint * Python benchmark_app update for perf hints * addresssing reviewers comments on the python benchmark_app * simplifying/brushing logic a bit * refactor the heuristic to the separate file (to be shared with iGPU soon) * refactor conversion of modes to the specific GPU config per feedback from Vladimir
2021-09-13 15:40:36 +03:00
// the rest are individual per-device settings (overriding the values set with perf modes)
auto setThroughputStreams = [&]() {
const std::string key = getDeviceTypeFromName(device) + "_THROUGHPUT_STREAMS";
if (device_nstreams.count(device)) {
// set to user defined value
std::vector<std::string> supported_config_keys =
ie.GetMetric(device, METRIC_KEY(SUPPORTED_CONFIG_KEYS));
if (std::find(supported_config_keys.begin(), supported_config_keys.end(), key) ==
supported_config_keys.end()) {
throw std::logic_error("Device " + device + " doesn't support config key '" + key + "'! " +
"Please specify -nstreams for correct devices in format "
"<dev1>:<nstreams1>,<dev2>:<nstreams2>" +
" or via configuration file.");
}
device_config[key] = device_nstreams.at(device);
OV Performance Hints (CPU and GPU logic for selecting the actual configs), while AUTO/MULTI are passing them thru) (#6993) * rebasing the perf-modes-2021.3 to the 2021.4 Caveats: the (explicit) setting #streams is not disabled (as it was before for experiments with DLBenchmark), and the logic slighlty differ (streamsSet) (cherry picked from commit 1ae1edc0ed70fdea40f528fdaf8d00a9904d2a5c) * overriding streams (to force the TPUT mode to the DLBenchnark) (cherry picked from commit 7f506cda31abf35ac293d0dce32f602a0188c619) * disabling reducing #streams to fully mimic baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments) (cherry picked from commit 85073dd1dd2c7d43a89c37c8f646313f6ddfc650) * clang/identation (cherry picked from commit 050a4155a923cee294c8689d685b39247b7a172a) * splitting the Transformation to general and CPU specific. Now hopefully,this fully mimics the baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments), as the streams reduce num (as well as early exit on GRU/LSTM/TensorIterator) is deisabled (cherry picked from commit e98b2c1a67f2542a686543594b75b575ef515196) * disabling GRU/LSTM/TI + reducing of streams + 5D considered compute-limited only for int8 (cherry picked from commit 32b8d80dee18685ebf3d069bb4cd2172af7363b7) * refactored to avoid compute_limited_ratio, reverted the reducing #streams, removed LSTM from limitations (cherry picked from commit f2b972171b29cf599aae2407ceec2e6adb67e4e9) * isa-based threshold logic (cherry picked from commit b218457e1a93fcb3374eb9da948fdad2175ec33a) * mode->hint (cherry picked from commit ec20aa8ecaf3222f2a6fdfe9153cf6c9dfdd6a54) * optional PERFORMANCE_HINT_NUM_REQUESTS (cherry picked from commit 5a3883e3f36e7928c6391094ae10711c8e4c3b5c) * moving the perfHints to the common OV config class + initial tests (CPU only, as the actual AUTO/MULTI should be accommodated on the master) (cherry picked from commit (then fixed)45bafe7d527f466507dea0693aeed51be4ebf776) * AUTO support for PerfHints * MULTI support for PerfHints * Enabling Perf hints for the GPU plugin * brushing settings output a bit * disabling "throughput" perf hint being default (until OV 2.0) * uncommenting the logic which was disabled to force the DLBenchmark to use the throughput mode by default * removing dead and experimental code, and debug printfs * clang/code-style * code-review remarks * Moved the output of the actual params that the hint produced to the right place * aligning MULTI's GetConfig beh to HETERO's as captured in the preso (CVS-59960) ratified with the ArchForum * clang * benchmark_app brushing * Update inference-engine/samples/benchmark_app/README.md * propagating the perf hints thru one more scenario in the merged AUTO-MULTI * fixed mispint * Python benchmark_app update for perf hints * addresssing reviewers comments on the python benchmark_app * simplifying/brushing logic a bit * refactor the heuristic to the separate file (to be shared with iGPU soon) * refactor conversion of modes to the specific GPU config per feedback from Vladimir
2021-09-13 15:40:36 +03:00
} else if (ov_perf_hint.empty() && !device_config.count(key) && (FLAGS_api == "async")) {
slog::warn << "-nstreams default value is determined automatically for " << device
<< " device. "
"Although the automatic selection usually provides a "
"reasonable performance, "
"but it still may be non-optimal for some cases, for more "
"information look at README."
<< slog::endl;
if (std::string::npos == device.find("MYRIAD")) // MYRIAD sets the default number of
// streams implicitly (without _AUTO)
device_config[key] = std::string(getDeviceTypeFromName(device) + "_THROUGHPUT_AUTO");
}
if (device_config.count(key))
device_nstreams[device] = device_config.at(key);
};
2020-04-13 21:17:23 +03:00
if (device.find("CPU") != std::string::npos) { // CPU supports few special performance-oriented keys
2019-08-09 19:02:42 +03:00
// limit threading for CPU portion of inference
if (isFlagSetInCommandLine("nthreads"))
device_config[CONFIG_KEY(CPU_THREADS_NUM)] = std::to_string(FLAGS_nthreads);
if (isFlagSetInCommandLine("enforcebf16"))
device_config[CONFIG_KEY(ENFORCE_BF16)] = FLAGS_enforcebf16 ? CONFIG_VALUE(YES) : CONFIG_VALUE(NO);
if (isFlagSetInCommandLine("pin")) {
// set to user defined value
device_config[CONFIG_KEY(CPU_BIND_THREAD)] = FLAGS_pin;
} else if (!device_config.count(CONFIG_KEY(CPU_BIND_THREAD))) {
if ((device_name.find("MULTI") != std::string::npos) &&
(device_name.find("GPU") != std::string::npos)) {
slog::warn << "Turn off threads pinning for " << device
<< " device since multi-scenario with GPU device is used." << slog::endl;
device_config[CONFIG_KEY(CPU_BIND_THREAD)] = CONFIG_VALUE(NO);
}
2019-10-04 19:26:43 +03:00
}
2019-08-09 19:02:42 +03:00
// for CPU execution, more throughput-oriented execution via streams
setThroughputStreams();
} else if (device.find("GPU") != std::string::npos) {
// for GPU execution, more throughput-oriented execution via streams
setThroughputStreams();
2019-10-04 19:26:43 +03:00
if ((device_name.find("MULTI") != std::string::npos) &&
(device_name.find("CPU") != std::string::npos)) {
2021-06-14 22:47:59 +09:00
slog::warn << "Turn on GPU throttling. Multi-device execution with "
"the CPU + GPU performs best with GPU throttling hint, "
<< "which releases another CPU thread (that is otherwise "
"used by the GPU driver for active polling)"
<< slog::endl;
device_config[GPU_CONFIG_KEY(PLUGIN_THROTTLE)] = "1";
2019-10-04 19:26:43 +03:00
}
} else if (device.find("MYRIAD") != std::string::npos) {
device_config[CONFIG_KEY(LOG_LEVEL)] = CONFIG_VALUE(LOG_WARNING);
setThroughputStreams();
} else if (device.find("GNA") != std::string::npos) {
if (FLAGS_qb == 8)
device_config[GNA_CONFIG_KEY(PRECISION)] = "I8";
else
device_config[GNA_CONFIG_KEY(PRECISION)] = "I16";
if (isFlagSetInCommandLine("nthreads"))
device_config[GNA_CONFIG_KEY(LIB_N_THREADS)] = std::to_string(FLAGS_nthreads);
} else {
std::vector<std::string> supported_config_keys =
ie.GetMetric(device, METRIC_KEY(SUPPORTED_CONFIG_KEYS));
auto supported = [&](const std::string& key) {
return std::find(std::begin(supported_config_keys), std::end(supported_config_keys), key) !=
std::end(supported_config_keys);
};
if (supported(CONFIG_KEY(CPU_THREADS_NUM)) && isFlagSetInCommandLine("nthreads")) {
device_config[CONFIG_KEY(CPU_THREADS_NUM)] = std::to_string(FLAGS_nthreads);
}
if (supported(CONFIG_KEY(CPU_THROUGHPUT_STREAMS)) && isFlagSetInCommandLine("nstreams")) {
device_config[CONFIG_KEY(CPU_THROUGHPUT_STREAMS)] = FLAGS_nstreams;
}
if (supported(CONFIG_KEY(CPU_BIND_THREAD)) && isFlagSetInCommandLine("pin")) {
device_config[CONFIG_KEY(CPU_BIND_THREAD)] = FLAGS_pin;
}
2019-08-09 19:02:42 +03:00
}
2018-11-23 16:19:43 +03:00
}
for (auto&& item : config) {
ie.SetConfig(item.second, item.first);
}
auto double_to_string = [](const double number) {
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
return ss.str();
};
auto get_total_ms_time = [](Time::time_point& startTime) {
2020-02-11 22:48:49 +03:00
return std::chrono::duration_cast<ns>(Time::now() - startTime).count() * 0.000001;
};
2019-08-09 19:02:42 +03:00
2020-02-11 22:48:49 +03:00
size_t batchSize = FLAGS_b;
Precision precision = Precision::UNSPECIFIED;
std::string topology_name = "";
benchmark_app::InputsInfo app_inputs_info;
std::string output_name;
[Caching] Add caching options to benchmark app (#4909) * Python API for LoadNetwork by model file name * BenchmarkApp: Add caching and LoadNetworkFromFile support 2 new options are introduced - cache_dir <dir> - enables models caching - load_from_file - use new perform "LoadNetwork" by model file name Using both parameters will achieve maximum performance of read/load network on startup Tests: 1) Run "benchmark_app -h". Help will display 2 new options. After available devices there will be list of devices with cache support 2) ./benchmark_app -d CPU -i <model.xml> -load_from_file Verify that some test steps are skipped (related to ReadNetwork, re-shaping etc) 3) Pre-requisite: support of caching shall be enabled for Template plugin ./benchmark_app -d TEMPLATE -i <model.onnx> -load_from_file -cache_dir someDir Verify that "someDir" is created and generated blob is available Run again, verify that loading works as well (should be faster as it will not load onnx model) 4) Run same test as (3), but without -load_from_file option. Verify that cache is properly created For some devices loadNetwork time shall be improved when cache is available * Removed additional timing prints * Correction from old code * Revert "Removed additional timing prints" Additional change - when .blob is chosen instead of .xml, it takes priority over caching flags * Removed new time printings As discussed, these time measurements like 'total first inference time' will be available in 'timeTests' scripts * Fix clang-format issues
2021-05-17 13:41:15 +03:00
// Takes priority over config from file
if (!FLAGS_cache_dir.empty()) {
ie.SetConfig({{CONFIG_KEY(CACHE_DIR), FLAGS_cache_dir}});
}
if (FLAGS_load_from_file && !isNetworkCompiled) {
next_step();
slog::info << "Skipping the step for loading network from file" << slog::endl;
next_step();
slog::info << "Skipping the step for loading network from file" << slog::endl;
next_step();
slog::info << "Skipping the step for loading network from file" << slog::endl;
auto startTime = Time::now();
exeNetwork = ie.LoadNetwork(FLAGS_m, device_name);
auto duration_ms = double_to_string(get_total_ms_time(startTime));
slog::info << "Load network took " << duration_ms << " ms" << slog::endl;
if (statistics)
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{{"load network time (ms)", duration_ms}});
app_inputs_info = getInputsInfo<InputInfo::CPtr>(FLAGS_shape,
FLAGS_layout,
FLAGS_b,
FLAGS_iscale,
FLAGS_imean,
exeNetwork.GetInputsInfo());
[Caching] Add caching options to benchmark app (#4909) * Python API for LoadNetwork by model file name * BenchmarkApp: Add caching and LoadNetworkFromFile support 2 new options are introduced - cache_dir <dir> - enables models caching - load_from_file - use new perform "LoadNetwork" by model file name Using both parameters will achieve maximum performance of read/load network on startup Tests: 1) Run "benchmark_app -h". Help will display 2 new options. After available devices there will be list of devices with cache support 2) ./benchmark_app -d CPU -i <model.xml> -load_from_file Verify that some test steps are skipped (related to ReadNetwork, re-shaping etc) 3) Pre-requisite: support of caching shall be enabled for Template plugin ./benchmark_app -d TEMPLATE -i <model.onnx> -load_from_file -cache_dir someDir Verify that "someDir" is created and generated blob is available Run again, verify that loading works as well (should be faster as it will not load onnx model) 4) Run same test as (3), but without -load_from_file option. Verify that cache is properly created For some devices loadNetwork time shall be improved when cache is available * Removed additional timing prints * Correction from old code * Revert "Removed additional timing prints" Additional change - when .blob is chosen instead of .xml, it takes priority over caching flags * Removed new time printings As discussed, these time measurements like 'total first inference time' will be available in 'timeTests' scripts * Fix clang-format issues
2021-05-17 13:41:15 +03:00
if (batchSize == 0) {
batchSize = 1;
}
} else if (!isNetworkCompiled) {
// ----------------- 4. Reading the Intermediate Representation network
// ----------------------------------------
2020-02-11 22:48:49 +03:00
next_step();
slog::info << "Loading network files" << slog::endl;
auto startTime = Time::now();
CNNNetwork cnnNetwork = ie.ReadNetwork(FLAGS_m);
auto duration_ms = double_to_string(get_total_ms_time(startTime));
slog::info << "Read network took " << duration_ms << " ms" << slog::endl;
if (statistics)
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{{"read network time (ms)", duration_ms}});
2020-02-11 22:48:49 +03:00
const InputsDataMap inputInfo(cnnNetwork.getInputsInfo());
if (inputInfo.empty()) {
throw std::logic_error("no inputs info is provided");
}
// ----------------- 5. Resizing network to match image sizes and given
// batch ----------------------------------
2020-02-11 22:48:49 +03:00
next_step();
2020-04-13 21:17:23 +03:00
batchSize = cnnNetwork.getBatchSize();
// Parse input shapes if specified
bool reshape = false;
app_inputs_info = getInputsInfo<InputInfo::Ptr>(FLAGS_shape,
FLAGS_layout,
FLAGS_b,
FLAGS_iscale,
FLAGS_imean,
inputInfo,
reshape);
if (reshape) {
InferenceEngine::ICNNNetwork::InputShapes shapes = {};
for (auto& item : app_inputs_info)
shapes[item.first] = item.second.shape;
slog::info << "Reshaping network: " << getShapesString(shapes) << slog::endl;
startTime = Time::now();
cnnNetwork.reshape(shapes);
[Caching] Add caching options to benchmark app (#4909) * Python API for LoadNetwork by model file name * BenchmarkApp: Add caching and LoadNetworkFromFile support 2 new options are introduced - cache_dir <dir> - enables models caching - load_from_file - use new perform "LoadNetwork" by model file name Using both parameters will achieve maximum performance of read/load network on startup Tests: 1) Run "benchmark_app -h". Help will display 2 new options. After available devices there will be list of devices with cache support 2) ./benchmark_app -d CPU -i <model.xml> -load_from_file Verify that some test steps are skipped (related to ReadNetwork, re-shaping etc) 3) Pre-requisite: support of caching shall be enabled for Template plugin ./benchmark_app -d TEMPLATE -i <model.onnx> -load_from_file -cache_dir someDir Verify that "someDir" is created and generated blob is available Run again, verify that loading works as well (should be faster as it will not load onnx model) 4) Run same test as (3), but without -load_from_file option. Verify that cache is properly created For some devices loadNetwork time shall be improved when cache is available * Removed additional timing prints * Correction from old code * Revert "Removed additional timing prints" Additional change - when .blob is chosen instead of .xml, it takes priority over caching flags * Removed new time printings As discussed, these time measurements like 'total first inference time' will be available in 'timeTests' scripts * Fix clang-format issues
2021-05-17 13:41:15 +03:00
duration_ms = double_to_string(get_total_ms_time(startTime));
slog::info << "Reshape network took " << duration_ms << " ms" << slog::endl;
if (statistics)
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{{"reshape network time (ms)", duration_ms}});
2020-02-11 22:48:49 +03:00
}
// use batch size according to provided layout and shapes
batchSize = (!FLAGS_layout.empty()) ? getBatchSize(app_inputs_info) : cnnNetwork.getBatchSize();
2020-02-11 22:48:49 +03:00
topology_name = cnnNetwork.getName();
slog::info << (FLAGS_b != 0 ? "Network batch size was changed to: " : "Network batch size: ") << batchSize
<< slog::endl;
2020-02-11 22:48:49 +03:00
// ----------------- 6. Configuring inputs and outputs
// ----------------------------------------------------------------------
2020-02-11 22:48:49 +03:00
next_step();
processPrecision(cnnNetwork, FLAGS_ip, FLAGS_op, FLAGS_iop);
for (auto& item : cnnNetwork.getInputsInfo()) {
// if precision for input set by user, then set it to app_inputs
// if it an image, set U8
if (!FLAGS_ip.empty() || FLAGS_iop.find(item.first) != std::string::npos) {
app_inputs_info.at(item.first).precision = item.second->getPrecision();
} else if (app_inputs_info.at(item.first).isImage()) {
app_inputs_info.at(item.first).precision = Precision::U8;
item.second->setPrecision(app_inputs_info.at(item.first).precision);
2020-02-11 22:48:49 +03:00
}
}
printInputAndOutputsInfo(cnnNetwork);
// ----------------- 7. Loading the model to the device
// --------------------------------------------------------
2020-02-11 22:48:49 +03:00
next_step();
startTime = Time::now();
exeNetwork = ie.LoadNetwork(cnnNetwork, device_name);
2020-02-11 22:48:49 +03:00
duration_ms = double_to_string(get_total_ms_time(startTime));
slog::info << "Load network took " << duration_ms << " ms" << slog::endl;
if (statistics)
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{{"load network time (ms)", duration_ms}});
2020-02-11 22:48:49 +03:00
} else {
next_step();
slog::info << "Skipping the step for compiled network" << slog::endl;
next_step();
slog::info << "Skipping the step for compiled network" << slog::endl;
next_step();
slog::info << "Skipping the step for compiled network" << slog::endl;
// ----------------- 7. Loading the model to the device
// --------------------------------------------------------
2020-02-11 22:48:49 +03:00
next_step();
auto startTime = Time::now();
exeNetwork = ie.ImportNetwork(FLAGS_m, device_name, {});
auto duration_ms = double_to_string(get_total_ms_time(startTime));
slog::info << "Import network took " << duration_ms << " ms" << slog::endl;
if (statistics)
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{{"import network time (ms)", duration_ms}});
app_inputs_info = getInputsInfo<InputInfo::CPtr>(FLAGS_shape,
FLAGS_layout,
FLAGS_b,
FLAGS_iscale,
FLAGS_imean,
exeNetwork.GetInputsInfo());
2020-02-11 22:48:49 +03:00
if (batchSize == 0) {
batchSize = 1;
}
}
OV Performance Hints (CPU and GPU logic for selecting the actual configs), while AUTO/MULTI are passing them thru) (#6993) * rebasing the perf-modes-2021.3 to the 2021.4 Caveats: the (explicit) setting #streams is not disabled (as it was before for experiments with DLBenchmark), and the logic slighlty differ (streamsSet) (cherry picked from commit 1ae1edc0ed70fdea40f528fdaf8d00a9904d2a5c) * overriding streams (to force the TPUT mode to the DLBenchnark) (cherry picked from commit 7f506cda31abf35ac293d0dce32f602a0188c619) * disabling reducing #streams to fully mimic baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments) (cherry picked from commit 85073dd1dd2c7d43a89c37c8f646313f6ddfc650) * clang/identation (cherry picked from commit 050a4155a923cee294c8689d685b39247b7a172a) * splitting the Transformation to general and CPU specific. Now hopefully,this fully mimics the baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments), as the streams reduce num (as well as early exit on GRU/LSTM/TensorIterator) is deisabled (cherry picked from commit e98b2c1a67f2542a686543594b75b575ef515196) * disabling GRU/LSTM/TI + reducing of streams + 5D considered compute-limited only for int8 (cherry picked from commit 32b8d80dee18685ebf3d069bb4cd2172af7363b7) * refactored to avoid compute_limited_ratio, reverted the reducing #streams, removed LSTM from limitations (cherry picked from commit f2b972171b29cf599aae2407ceec2e6adb67e4e9) * isa-based threshold logic (cherry picked from commit b218457e1a93fcb3374eb9da948fdad2175ec33a) * mode->hint (cherry picked from commit ec20aa8ecaf3222f2a6fdfe9153cf6c9dfdd6a54) * optional PERFORMANCE_HINT_NUM_REQUESTS (cherry picked from commit 5a3883e3f36e7928c6391094ae10711c8e4c3b5c) * moving the perfHints to the common OV config class + initial tests (CPU only, as the actual AUTO/MULTI should be accommodated on the master) (cherry picked from commit (then fixed)45bafe7d527f466507dea0693aeed51be4ebf776) * AUTO support for PerfHints * MULTI support for PerfHints * Enabling Perf hints for the GPU plugin * brushing settings output a bit * disabling "throughput" perf hint being default (until OV 2.0) * uncommenting the logic which was disabled to force the DLBenchmark to use the throughput mode by default * removing dead and experimental code, and debug printfs * clang/code-style * code-review remarks * Moved the output of the actual params that the hint produced to the right place * aligning MULTI's GetConfig beh to HETERO's as captured in the preso (CVS-59960) ratified with the ArchForum * clang * benchmark_app brushing * Update inference-engine/samples/benchmark_app/README.md * propagating the perf hints thru one more scenario in the merged AUTO-MULTI * fixed mispint * Python benchmark_app update for perf hints * addresssing reviewers comments on the python benchmark_app * simplifying/brushing logic a bit * refactor the heuristic to the separate file (to be shared with iGPU soon) * refactor conversion of modes to the specific GPU config per feedback from Vladimir
2021-09-13 15:40:36 +03:00
// ----------------- 8. Querying optimal runtime parameters
// -----------------------------------------------------
2019-08-09 19:02:42 +03:00
next_step();
OV Performance Hints (CPU and GPU logic for selecting the actual configs), while AUTO/MULTI are passing them thru) (#6993) * rebasing the perf-modes-2021.3 to the 2021.4 Caveats: the (explicit) setting #streams is not disabled (as it was before for experiments with DLBenchmark), and the logic slighlty differ (streamsSet) (cherry picked from commit 1ae1edc0ed70fdea40f528fdaf8d00a9904d2a5c) * overriding streams (to force the TPUT mode to the DLBenchnark) (cherry picked from commit 7f506cda31abf35ac293d0dce32f602a0188c619) * disabling reducing #streams to fully mimic baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments) (cherry picked from commit 85073dd1dd2c7d43a89c37c8f646313f6ddfc650) * clang/identation (cherry picked from commit 050a4155a923cee294c8689d685b39247b7a172a) * splitting the Transformation to general and CPU specific. Now hopefully,this fully mimics the baseline c4df94d42d90a2bc3cd91d3d6844ba42f29bca7f of the 2021.3 (before experiments), as the streams reduce num (as well as early exit on GRU/LSTM/TensorIterator) is deisabled (cherry picked from commit e98b2c1a67f2542a686543594b75b575ef515196) * disabling GRU/LSTM/TI + reducing of streams + 5D considered compute-limited only for int8 (cherry picked from commit 32b8d80dee18685ebf3d069bb4cd2172af7363b7) * refactored to avoid compute_limited_ratio, reverted the reducing #streams, removed LSTM from limitations (cherry picked from commit f2b972171b29cf599aae2407ceec2e6adb67e4e9) * isa-based threshold logic (cherry picked from commit b218457e1a93fcb3374eb9da948fdad2175ec33a) * mode->hint (cherry picked from commit ec20aa8ecaf3222f2a6fdfe9153cf6c9dfdd6a54) * optional PERFORMANCE_HINT_NUM_REQUESTS (cherry picked from commit 5a3883e3f36e7928c6391094ae10711c8e4c3b5c) * moving the perfHints to the common OV config class + initial tests (CPU only, as the actual AUTO/MULTI should be accommodated on the master) (cherry picked from commit (then fixed)45bafe7d527f466507dea0693aeed51be4ebf776) * AUTO support for PerfHints * MULTI support for PerfHints * Enabling Perf hints for the GPU plugin * brushing settings output a bit * disabling "throughput" perf hint being default (until OV 2.0) * uncommenting the logic which was disabled to force the DLBenchmark to use the throughput mode by default * removing dead and experimental code, and debug printfs * clang/code-style * code-review remarks * Moved the output of the actual params that the hint produced to the right place * aligning MULTI's GetConfig beh to HETERO's as captured in the preso (CVS-59960) ratified with the ArchForum * clang * benchmark_app brushing * Update inference-engine/samples/benchmark_app/README.md * propagating the perf hints thru one more scenario in the merged AUTO-MULTI * fixed mispint * Python benchmark_app update for perf hints * addresssing reviewers comments on the python benchmark_app * simplifying/brushing logic a bit * refactor the heuristic to the separate file (to be shared with iGPU soon) * refactor conversion of modes to the specific GPU config per feedback from Vladimir
2021-09-13 15:40:36 +03:00
// output of the actual settings that the device selected based on the hint
if (!ov_perf_hint.empty()) {
for (const auto& device : devices) {
std::vector<std::string> supported_config_keys =
ie.GetMetric(device, METRIC_KEY(SUPPORTED_CONFIG_KEYS));
slog::info << "Device: " << device << slog::endl;
for (const auto& cfg : supported_config_keys) {
try {
slog::info << " {" << cfg << " , " << exeNetwork.GetConfig(cfg).as<std::string>();
} catch (...) {
};
slog::info << " }" << slog::endl;
}
}
}
2019-08-09 19:02:42 +03:00
// Update number of streams
for (auto&& ds : device_nstreams) {
const std::string key = getDeviceTypeFromName(ds.first) + "_THROUGHPUT_STREAMS";
device_nstreams[ds.first] = ie.GetConfig(ds.first, key).as<std::string>();
}
2019-08-09 19:02:42 +03:00
// Number of requests
uint32_t nireq = FLAGS_nireq;
if (nireq == 0) {
2020-04-13 21:17:23 +03:00
if (FLAGS_api == "sync") {
nireq = 1;
} else {
std::string key = METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS);
try {
nireq = exeNetwork.GetMetric(key).as<unsigned int>();
} catch (const std::exception& ex) {
IE_THROW() << "Every device used with the benchmark_app should "
<< "support OPTIMAL_NUMBER_OF_INFER_REQUESTS "
"ExecutableNetwork metric. "
<< "Failed to query the metric for the " << device_name << " with error:" << ex.what();
2020-04-13 21:17:23 +03:00
}
2018-11-23 16:19:43 +03:00
}
}
2019-08-09 19:02:42 +03:00
// Iteration limit
uint32_t niter = FLAGS_niter;
if ((niter > 0) && (FLAGS_api == "async")) {
niter = ((niter + nireq - 1) / nireq) * nireq;
2019-08-09 19:02:42 +03:00
if (FLAGS_niter != niter) {
slog::warn << "Number of iterations was aligned by request number from " << FLAGS_niter << " to "
<< niter << " using number of requests " << nireq << slog::endl;
2019-08-09 19:02:42 +03:00
}
}
2019-04-12 18:25:53 +03:00
2019-08-09 19:02:42 +03:00
// Time limit
uint32_t duration_seconds = 0;
if (FLAGS_t != 0) {
// time limit
duration_seconds = FLAGS_t;
} else if (FLAGS_niter == 0) {
// default time limit
duration_seconds = deviceDefaultDeviceDurationInSeconds(device_name);
2019-04-12 18:25:53 +03:00
}
2019-08-09 19:02:42 +03:00
uint64_t duration_nanoseconds = getDurationInNanoseconds(duration_seconds);
2019-04-12 18:25:53 +03:00
2019-10-04 19:26:43 +03:00
if (statistics) {
statistics->addParameters(
StatisticsReport::Category::RUNTIME_CONFIG,
{
{"topology", topology_name},
{"target device", device_name},
{"API", FLAGS_api},
{"precision", std::string(precision.name())},
{"batch size", std::to_string(batchSize)},
{"number of iterations", std::to_string(niter)},
{"number of parallel infer requests", std::to_string(nireq)},
{"duration (ms)", std::to_string(getDurationInMilliseconds(duration_seconds))},
});
2019-10-04 19:26:43 +03:00
for (auto& nstreams : device_nstreams) {
std::stringstream ss;
ss << "number of " << nstreams.first << " streams";
statistics->addParameters(StatisticsReport::Category::RUNTIME_CONFIG,
{
{ss.str(), nstreams.second},
});
2019-10-04 19:26:43 +03:00
}
}
// ----------------- 9. Creating infer requests and filling input blobs
// ----------------------------------------
2019-08-09 19:02:42 +03:00
next_step();
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
InferRequestsQueue inferRequestsQueue(exeNetwork, nireq);
if (isFlagSetInCommandLine("use_device_mem")) {
if (device_name.find("GPU") == 0)
::gpu::fillRemoteBlobs(inputFiles, batchSize, app_inputs_info, inferRequestsQueue.requests, exeNetwork);
else if (device_name.find("CPU") == 0)
fillBlobs(inputFiles, batchSize, app_inputs_info, inferRequestsQueue.requests);
else
IE_THROW() << "Requested device doesn't support `use_device_mem` option.";
} else {
fillBlobs(inputFiles, batchSize, app_inputs_info, inferRequestsQueue.requests);
}
2019-04-12 18:25:53 +03:00
// ----------------- 10. Measuring performance
// ------------------------------------------------------------------
2019-08-09 19:02:42 +03:00
size_t progressCnt = 0;
size_t progressBarTotalCount = progressBarDefaultTotalCount;
size_t iteration = 0;
2019-04-12 18:25:53 +03:00
2019-08-09 19:02:42 +03:00
std::stringstream ss;
ss << "Start inference " << FLAGS_api << "hronously";
2019-08-09 19:02:42 +03:00
if (FLAGS_api == "async") {
if (!ss.str().empty()) {
ss << ", ";
}
ss << nireq << " inference requests";
std::stringstream device_ss;
for (auto& nstreams : device_nstreams) {
if (!device_ss.str().empty()) {
device_ss << ", ";
}
device_ss << nstreams.second << " streams for " << nstreams.first;
}
if (!device_ss.str().empty()) {
ss << " using " << device_ss.str();
2019-04-12 18:25:53 +03:00
}
}
2019-08-09 19:02:42 +03:00
ss << ", limits: ";
if (duration_seconds > 0) {
ss << getDurationInMilliseconds(duration_seconds) << " ms duration";
2018-11-23 16:19:43 +03:00
}
2019-08-09 19:02:42 +03:00
if (niter != 0) {
if (duration_seconds == 0) {
progressBarTotalCount = niter;
}
if (duration_seconds > 0) {
ss << ", ";
}
ss << niter << " iterations";
}
next_step(ss.str());
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
// warming up - out of scope
auto inferRequest = inferRequestsQueue.getIdleRequest();
if (!inferRequest) {
IE_THROW() << "No idle Infer Requests!";
2019-08-09 19:02:42 +03:00
}
2019-04-12 18:25:53 +03:00
if (FLAGS_api == "sync") {
inferRequest->infer();
2019-08-09 19:02:42 +03:00
} else {
inferRequest->startAsync();
}
inferRequestsQueue.waitAll();
auto duration_ms = double_to_string(inferRequestsQueue.getLatencies()[0]);
slog::info << "First inference took " << duration_ms << " ms" << slog::endl;
if (statistics)
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{{"first inference time (ms)", duration_ms}});
2019-08-09 19:02:42 +03:00
inferRequestsQueue.resetTimes();
2020-02-11 22:48:49 +03:00
auto startTime = Time::now();
2019-08-09 19:02:42 +03:00
auto execTime = std::chrono::duration_cast<ns>(Time::now() - startTime).count();
/** Start inference & calculate performance **/
/** to align number if iterations to guarantee that last infer requests are
* executed in the same conditions **/
2019-08-09 19:02:42 +03:00
ProgressBar progressBar(progressBarTotalCount, FLAGS_stream_output, FLAGS_progress);
while ((niter != 0LL && iteration < niter) ||
(duration_nanoseconds != 0LL && (uint64_t)execTime < duration_nanoseconds) ||
2019-08-09 19:02:42 +03:00
(FLAGS_api == "async" && iteration % nireq != 0)) {
inferRequest = inferRequestsQueue.getIdleRequest();
if (!inferRequest) {
IE_THROW() << "No idle Infer Requests!";
2019-08-09 19:02:42 +03:00
}
2019-08-09 19:02:42 +03:00
if (FLAGS_api == "sync") {
2019-04-12 18:25:53 +03:00
inferRequest->infer();
2018-11-23 16:19:43 +03:00
} else {
// As the inference request is currently idle, the wait() adds no
// additional overhead (and should return immediately). The primary
// reason for calling the method is exception checking/re-throwing.
// Callback, that governs the actual execution can handle errors as
// well, but as it uses just error codes it has no details like what()
// method of `std::exception` So, rechecking for any exceptions here.
2020-02-11 22:48:49 +03:00
inferRequest->wait();
2019-08-09 19:02:42 +03:00
inferRequest->startAsync();
2018-11-23 16:19:43 +03:00
}
2019-08-09 19:02:42 +03:00
iteration++;
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
execTime = std::chrono::duration_cast<ns>(Time::now() - startTime).count();
2019-04-12 18:25:53 +03:00
2019-08-09 19:02:42 +03:00
if (niter > 0) {
progressBar.addProgress(1);
} else {
// calculate how many progress intervals are covered by current
// iteration. depends on the current iteration time and time of each
// progress interval. Previously covered progress intervals must be
// skipped.
2019-08-09 19:02:42 +03:00
auto progressIntervalTime = duration_nanoseconds / progressBarTotalCount;
size_t newProgress = execTime / progressIntervalTime - progressCnt;
progressBar.addProgress(newProgress);
progressCnt += newProgress;
2018-11-23 16:19:43 +03:00
}
2019-08-09 19:02:42 +03:00
}
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
// wait the latest inference executions
inferRequestsQueue.waitAll();
double latency = getMedianValue<double>(inferRequestsQueue.getLatencies(), FLAGS_latency_percentile);
2019-10-04 19:26:43 +03:00
double totalDuration = inferRequestsQueue.getDurationInMilliseconds();
double fps =
(FLAGS_api == "sync") ? batchSize * 1000.0 / latency : batchSize * 1000.0 * iteration / totalDuration;
2019-10-04 19:26:43 +03:00
if (statistics) {
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{
{"total execution time (ms)", double_to_string(totalDuration)},
{"total number of iterations", std::to_string(iteration)},
});
2019-10-04 19:26:43 +03:00
if (device_name.find("MULTI") == std::string::npos) {
std::string latency_label;
if (FLAGS_latency_percentile == 50) {
latency_label = "latency (ms)";
} else {
latency_label = "latency (" + std::to_string(FLAGS_latency_percentile) + " percentile) (ms)";
}
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{
{latency_label, double_to_string(latency)},
});
2018-11-23 16:19:43 +03:00
}
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{{"throughput", double_to_string(fps)}});
2019-04-12 18:25:53 +03:00
}
2019-08-09 19:02:42 +03:00
progressBar.finish();
// ----------------- 11. Dumping statistics report
// -------------------------------------------------------------
2019-08-09 19:02:42 +03:00
next_step();
2018-11-23 16:19:43 +03:00
#ifdef USE_OPENCV
if (!FLAGS_dump_config.empty()) {
dump_config(FLAGS_dump_config, config);
slog::info << "Inference Engine configuration settings were dumped to " << FLAGS_dump_config << slog::endl;
}
#endif
2019-04-12 18:25:53 +03:00
if (!FLAGS_exec_graph_path.empty()) {
2019-08-09 19:02:42 +03:00
try {
CNNNetwork execGraphInfo = exeNetwork.GetExecGraphInfo();
execGraphInfo.serialize(FLAGS_exec_graph_path);
slog::info << "executable graph is stored to " << FLAGS_exec_graph_path << slog::endl;
} catch (const std::exception& ex) {
2019-08-09 19:02:42 +03:00
slog::err << "Can't get executable graph: " << ex.what() << slog::endl;
}
}
2019-10-04 19:26:43 +03:00
if (perf_counts) {
std::vector<std::map<std::string, InferenceEngine::InferenceEngineProfileInfo>> perfCounts;
2019-08-09 19:02:42 +03:00
for (size_t ireq = 0; ireq < nireq; ireq++) {
2019-10-04 19:26:43 +03:00
auto reqPerfCounts = inferRequestsQueue.requests[ireq]->getPerformanceCounts();
if (FLAGS_pc) {
2021-02-16 13:08:54 +09:00
slog::info << "Performance counts for " << ireq << "-th infer request:" << slog::endl;
2019-10-04 19:26:43 +03:00
printPerformanceCounts(reqPerfCounts, std::cout, getFullDeviceName(ie, FLAGS_d), false);
}
perfCounts.push_back(reqPerfCounts);
}
if (statistics) {
statistics->dumpPerformanceCounters(perfCounts);
2019-08-09 19:02:42 +03:00
}
2018-11-23 16:19:43 +03:00
}
2019-04-12 18:25:53 +03:00
2019-10-04 19:26:43 +03:00
if (statistics)
statistics->dump();
2019-08-09 19:02:42 +03:00
std::cout << "Count: " << iteration << " iterations" << std::endl;
2020-02-11 22:48:49 +03:00
std::cout << "Duration: " << double_to_string(totalDuration) << " ms" << std::endl;
if (device_name.find("MULTI") == std::string::npos) {
std::cout << "Latency";
if (FLAGS_latency_percentile == 50) {
std::cout << ": ";
} else {
std::cout << " (" << FLAGS_latency_percentile << " percentile): ";
}
std::cout << double_to_string(latency) << " ms" << std::endl;
}
2020-02-11 22:48:49 +03:00
std::cout << "Throughput: " << double_to_string(fps) << " FPS" << std::endl;
2018-11-23 16:19:43 +03:00
} catch (const std::exception& ex) {
slog::err << ex.what() << slog::endl;
2019-10-04 19:26:43 +03:00
if (statistics) {
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{
{"error", ex.what()},
});
2019-10-04 19:26:43 +03:00
statistics->dump();
}
2018-11-23 16:19:43 +03:00
return 3;
}
return 0;
}