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

547 lines
24 KiB
C++
Raw Normal View History

2019-04-12 18:25:53 +03:00
// Copyright (C) 2019 Intel Corporation
2018-11-23 16:19:43 +03:00
// SPDX-License-Identifier: Apache-2.0
//
#include <algorithm>
#include <chrono>
#include <memory>
#include <map>
#include <string>
#include <vector>
#include <utility>
#include <inference_engine.hpp>
#include <ext_list.hpp>
2019-04-12 18:25:53 +03:00
#include <vpu/vpu_plugin_config.hpp>
2019-08-09 19:02:42 +03:00
#include <cldnn/cldnn_config.hpp>
2018-11-23 16:19:43 +03:00
#include <samples/common.hpp>
#include <samples/slog.hpp>
#include <samples/args_helper.hpp>
2019-04-12 18:25:53 +03:00
#include "benchmark_app.hpp"
#include "infer_request_wrap.hpp"
#include "progress_bar.hpp"
#include "statistics_report.hpp"
2019-08-09 19:02:42 +03:00
#include "inputs_filling.hpp"
#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
2019-04-12 18:25:53 +03:00
bool ParseAndCheckCommandLine(int argc, char *argv[]) {
2019-08-09 19:02:42 +03:00
// ---------------------------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()) {
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
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
}
2018-11-23 16:19:43 +03:00
2019-04-12 18:25:53 +03:00
if (!FLAGS_report_type.empty() &&
2019-08-09 19:02:42 +03:00
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) +
2019-04-12 18:25:53 +03:00
" report types are supported (invalid -report_type option value)";
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");
}
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, "Reading the Intermediate Representation network" },
{ 4, "Resizing network to match image sizes and given batch" },
{ 5, "Configuring input of the model" },
{ 6, "Setting device configuration" },
{ 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" }
};
step_id++;
if (step_names.count(step_id) == 0)
THROW_IE_EXCEPTION << "Step ID " << step_id << " is out of total steps number " << step_names.size();
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::vector<T> sortedVec(vec);
std::sort(sortedVec.begin(), sortedVec.end());
return (sortedVec.size() % 2 != 0) ?
sortedVec[sortedVec.size() / 2ULL] :
(sortedVec[sortedVec.size() / 2ULL] + sortedVec[sortedVec.size() / 2ULL - 1ULL]) / static_cast<T>(2.0);
}
2019-04-12 18:25:53 +03:00
/**
2019-08-09 19:02:42 +03:00
* @brief The entry point of the benchmark application
2019-04-12 18:25:53 +03:00
*/
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 {
2019-08-09 19:02:42 +03:00
// ----------------- 1. Parsing and validating input arguments -------------------------------------------------
next_step();
2019-04-12 18:25:53 +03:00
if (!ParseAndCheckCommandLine(argc, argv)) {
return 0;
2018-11-23 16:19:43 +03:00
}
2019-10-04 19:26:43 +03:00
if (!FLAGS_report_type.empty()) {
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 });
}
}
statistics = std::make_shared<StatisticsReport>(StatisticsReport::Config{FLAGS_report_type, FLAGS_report_folder});
statistics->addParameters(StatisticsReport::Category::COMMAND_LINE_PARAMETERS, command_line_arguments);
}
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
2019-10-04 19:26:43 +03:00
if (FLAGS_nstreams.empty()) {
slog::warn << "-nstreams default value is determined automatically for a 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<< slog::endl;
}
2019-08-09 19:02:42 +03:00
// ----------------- 2. Loading the Inference Engine -----------------------------------------------------------
next_step();
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
// Get optimal runtime parameters for device
std::string device_name = FLAGS_d;
2019-04-12 18:25:53 +03:00
2019-08-09 19:02:42 +03:00
Core ie;
2018-11-23 16:19:43 +03:00
if (FLAGS_d.find("CPU") != std::string::npos) {
2019-08-09 19:02:42 +03:00
// Loading default CPU extensions
ie.AddExtension(std::make_shared<Extensions::Cpu::CpuExtensions>(), "CPU");
if (!FLAGS_l.empty()) {
// CPU (MKLDNN) extensions is loaded as a shared library and passed as a pointer to base extension
const auto extension_ptr = InferenceEngine::make_so_pointer<InferenceEngine::IExtension>(FLAGS_l);
2019-08-09 19:02:42 +03:00
ie.AddExtension(extension_ptr, "CPU");
slog::info << "CPU (MKLDNN) extensions is loaded " << FLAGS_l << slog::endl;
}
}
if ((FLAGS_d.find("GPU") != std::string::npos) && !FLAGS_c.empty()) {
2018-11-23 16:19:43 +03:00
// Load clDNN Extensions
2019-08-09 19:02:42 +03:00
ie.SetConfig({ {CONFIG_KEY(CONFIG_FILE), FLAGS_c} });
2018-11-23 16:19:43 +03:00
slog::info << "GPU extensions is loaded " << FLAGS_c << slog::endl;
}
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
2019-08-09 19:02:42 +03:00
// ----------------- 3. Reading the Intermediate Representation network ----------------------------------------
next_step();
2019-04-12 18:25:53 +03:00
2018-11-23 16:19:43 +03:00
slog::info << "Loading network files" << slog::endl;
2019-08-09 19:02:42 +03:00
CNNNetReader netBuilder;
2019-10-04 19:26:43 +03:00
auto startTime = Time::now();
2018-11-23 16:19:43 +03:00
netBuilder.ReadNetwork(FLAGS_m);
const std::string binFileName = fileNameNoExt(FLAGS_m) + ".bin";
netBuilder.ReadWeights(binFileName);
2019-10-04 19:26:43 +03:00
auto float_to_string = [] (const float number) {
std::stringstream ss;
ss << std::fixed << std::setprecision(2) << number;
return ss.str();
};
auto get_total_ms_time = [ &startTime ] () {
return std::chrono::duration_cast<ns>(Time::now() - startTime).count() * 0.000001;
};
auto duration_ms = float_to_string(get_total_ms_time());
slog::info << "Read network took " << duration_ms << " ms" << slog::endl;
if (statistics)
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{
{"read network time (ms)", duration_ms}
});
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
CNNNetwork cnnNetwork = netBuilder.getNetwork();
const InputsDataMap inputInfo(cnnNetwork.getInputsInfo());
2018-11-23 16:19:43 +03:00
if (inputInfo.empty()) {
throw std::logic_error("no inputs info is provided");
}
2019-08-09 19:02:42 +03:00
// ----------------- 4. Resizing network to match image sizes and given batch ----------------------------------
next_step();
2019-04-12 18:25:53 +03:00
2018-11-23 16:19:43 +03:00
if (FLAGS_b != 0) {
ICNNNetwork::InputShapes shapes = cnnNetwork.getInputShapes();
2019-08-09 19:02:42 +03:00
bool reshape = false;
for (const InputsDataMap::value_type& item : inputInfo) {
auto layout = item.second->getTensorDesc().getLayout();
int batchIndex = -1;
if ((layout == Layout::NCHW) || (layout == Layout::NCDHW) ||
(layout == Layout::NHWC) || (layout == Layout::NDHWC) ||
(layout == Layout::NC)) {
batchIndex = 0;
} else if (layout == CN) {
batchIndex = 1;
}
if ((batchIndex != -1) && (shapes[item.first][batchIndex] != FLAGS_b)) {
shapes[item.first][batchIndex] = FLAGS_b;
reshape = true;
}
}
if (reshape) {
slog::info << "Resizing network to batch = " << FLAGS_b << slog::endl;
cnnNetwork.reshape(shapes);
2018-11-23 16:19:43 +03:00
}
}
const size_t batchSize = cnnNetwork.getBatchSize();
2019-10-04 19:26:43 +03:00
const Precision precision = cnnNetwork.getPrecision();
2018-11-23 16:19:43 +03:00
slog::info << (FLAGS_b != 0 ? "Network batch size was changed to: " : "Network batch size: ") << batchSize <<
2019-10-04 19:26:43 +03:00
", precision: " << precision << slog::endl;
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
// ----------------- 5. Configuring input ----------------------------------------------------------------------
next_step();
2019-04-12 18:25:53 +03:00
2018-11-23 16:19:43 +03:00
for (auto& item : inputInfo) {
2019-08-09 19:02:42 +03:00
if (isImage(item.second)) {
/** Set the precision of input data provided by the user, should be called before load of the network to the device **/
item.second->setPrecision(Precision::U8);
}
2018-11-23 16:19:43 +03:00
}
2019-08-09 19:02:42 +03:00
// ----------------- 6. Setting device configuration -----------------------------------------------------------
next_step();
bool perf_counts = (FLAGS_report_type == detailedCntReport ||
FLAGS_report_type == averageCntReport ||
2019-10-04 19:26:43 +03:00
FLAGS_pc ||
!FLAGS_exec_graph_path.empty());
2019-08-09 19:02:42 +03:00
auto devices = parseDevices(device_name);
std::map<std::string, uint32_t> device_nstreams = parseValuePerDevice(devices, FLAGS_nstreams);
for (auto& device : devices) {
if (device == "CPU") { // CPU supports few special performance-oriented keys
// limit threading for CPU portion of inference
if (FLAGS_nthreads != 0)
ie.SetConfig({{ CONFIG_KEY(CPU_THREADS_NUM), std::to_string(FLAGS_nthreads) }}, device);
2019-10-04 19:26:43 +03:00
if ((device_name.find("MULTI") != std::string::npos) &&
(device_name.find("GPU") != std::string::npos)) {
ie.SetConfig({{ CONFIG_KEY(CPU_BIND_THREAD), CONFIG_VALUE(NO) }}, device);
} else {
// pin threads for CPU portion of inference
ie.SetConfig({{ CONFIG_KEY(CPU_BIND_THREAD), FLAGS_pin }}, device);
}
2019-08-09 19:02:42 +03:00
// for CPU execution, more throughput-oriented execution via streams
if (FLAGS_api == "async")
ie.SetConfig({{ CONFIG_KEY(CPU_THROUGHPUT_STREAMS),
(device_nstreams.count(device) > 0 ? std::to_string(device_nstreams.at(device)) :
"CPU_THROUGHPUT_AUTO") }}, device);
device_nstreams[device] = std::stoi(ie.GetConfig(device, CONFIG_KEY(CPU_THROUGHPUT_STREAMS)).as<std::string>());
} else if (device == ("GPU")) {
if (FLAGS_api == "async")
ie.SetConfig({{ CONFIG_KEY(GPU_THROUGHPUT_STREAMS),
(device_nstreams.count(device) > 0 ? std::to_string(device_nstreams.at(device)) :
"GPU_THROUGHPUT_AUTO") }}, device);
device_nstreams[device] = std::stoi(ie.GetConfig(device, CONFIG_KEY(GPU_THROUGHPUT_STREAMS)).as<std::string>());
2019-10-04 19:26:43 +03:00
if ((device_name.find("MULTI") != std::string::npos) &&
(device_name.find("CPU") != std::string::npos)) {
// multi-device execution with the CPU + GPU performs best with GPU trottling hint,
// which releases another CPU thread (that is otherwise used by the GPU driver for active polling)
ie.SetConfig({{ CLDNN_CONFIG_KEY(PLUGIN_THROTTLE), "1" }}, "GPU");
}
2019-08-09 19:02:42 +03:00
} else if (device == "MYRIAD") {
ie.SetConfig({{ CONFIG_KEY(LOG_LEVEL), CONFIG_VALUE(LOG_NONE) },
{ VPU_CONFIG_KEY(LOG_LEVEL), CONFIG_VALUE(LOG_WARNING) }}, device);
}
2018-11-23 16:19:43 +03:00
}
2019-08-09 19:02:42 +03:00
// ----------------- 7. Loading the model to the device --------------------------------------------------------
next_step();
std::map<std::string, std::string> config = {{ CONFIG_KEY(PERF_COUNT), perf_counts ? CONFIG_VALUE(YES) :
CONFIG_VALUE(NO) }};
2019-10-04 19:26:43 +03:00
startTime = Time::now();
2019-08-09 19:02:42 +03:00
ExecutableNetwork exeNetwork = ie.LoadNetwork(cnnNetwork, device_name, config);
2019-10-04 19:26:43 +03:00
duration_ms = float_to_string(get_total_ms_time());
slog::info << "Load network took " << duration_ms << " ms" << slog::endl;
if (statistics)
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{
{"load network time (ms)", duration_ms}
});
2019-08-09 19:02:42 +03:00
// ----------------- 8. Setting optimal runtime parameters -----------------------------------------------------
next_step();
// Number of requests
uint32_t nireq = FLAGS_nireq;
if (nireq == 0) {
std::string key = METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS);
try {
nireq = exeNetwork.GetMetric(key).as<unsigned int>();
} catch (const details::InferenceEngineException& ex) {
THROW_IE_EXCEPTION
<< "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();
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;
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-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", cnnNetwork.getName()},
{"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))},
});
for (auto& nstreams : device_nstreams) {
std::stringstream ss;
ss << "number of " << nstreams.first << " streams";
statistics->addParameters(StatisticsReport::Category::RUNTIME_CONFIG,
{
{ss.str(), std::to_string(nstreams.second)},
});
}
}
2019-08-09 19:02:42 +03:00
// ----------------- 9. Creating infer requests and filling input blobs ----------------------------------------
next_step();
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
InferRequestsQueue inferRequestsQueue(exeNetwork, nireq);
2018-11-23 16:19:43 +03:00
2019-08-09 19:02:42 +03:00
fillBlobs(inputFiles, batchSize, inputInfo, inferRequestsQueue.requests);
2019-04-12 18:25:53 +03:00
2019-08-09 19:02:42 +03:00
// ----------------- 10. Measuring performance ------------------------------------------------------------------
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 << "ronously";
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) {
THROW_IE_EXCEPTION << "No idle Infer Requests!";
}
2018-11-23 16:19:43 +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();
inferRequestsQueue.resetTimes();
2019-10-04 19:26:43 +03:00
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 **/
ProgressBar progressBar(progressBarTotalCount, FLAGS_stream_output, FLAGS_progress);
while ((niter != 0LL && iteration < niter) ||
(duration_nanoseconds != 0LL && (uint64_t)execTime < duration_nanoseconds) ||
(FLAGS_api == "async" && iteration % nireq != 0)) {
inferRequest = inferRequestsQueue.getIdleRequest();
if (!inferRequest) {
THROW_IE_EXCEPTION << "No idle Infer Requests!";
}
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 {
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.
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();
2019-10-04 19:26:43 +03:00
double latency = getMedianValue<double>(inferRequestsQueue.getLatencies());
double totalDuration = inferRequestsQueue.getDurationInMilliseconds();
double fps = (FLAGS_api == "sync") ? batchSize * 1000.0 / latency :
batchSize * 1000.0 * iteration / totalDuration;
if (statistics) {
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{
{"total execution time (ms)", float_to_string(totalDuration)},
{"total number of iterations", std::to_string(iteration)},
});
if (device_name.find("MULTI") == std::string::npos) {
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{
{"latency (ms)", float_to_string(latency)},
});
2018-11-23 16:19:43 +03:00
}
2019-10-04 19:26:43 +03:00
statistics->addParameters(StatisticsReport::Category::EXECUTION_RESULTS,
{
{"throughput", float_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 -------------------------------------------------------------
next_step();
2018-11-23 16:19:43 +03:00
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) {
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) {
slog::info << "Pefrormance counts for " << ireq << "-th infer request:" << slog::endl;
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;
2019-10-04 19:26:43 +03:00
std::cout << "Duration: " << float_to_string(totalDuration) << " ms" << std::endl;
if (device_name.find("MULTI") == std::string::npos)
std::cout << "Latency: " << float_to_string(latency) << " ms" << std::endl;
std::cout << "Throughput: " << float_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()},
});
statistics->dump();
}
2018-11-23 16:19:43 +03:00
return 3;
}
return 0;
}