2021-03-25 02:40:09 +03:00
|
|
|
// Copyright (C) 2018-2021 Intel Corporation
|
2019-04-12 18:25:53 +03:00
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
//
|
|
|
|
|
|
2021-12-13 11:30:58 +03:00
|
|
|
// clang-format off
|
2021-04-22 14:02:54 +03:00
|
|
|
#include <algorithm>
|
|
|
|
|
#include <map>
|
2019-04-12 18:25:53 +03:00
|
|
|
#include <string>
|
|
|
|
|
#include <utility>
|
2021-04-22 14:02:54 +03:00
|
|
|
#include <vector>
|
2019-04-12 18:25:53 +03:00
|
|
|
|
2021-12-13 11:30:58 +03:00
|
|
|
#include "statistics_report.hpp"
|
|
|
|
|
// clang-format on
|
|
|
|
|
|
2021-04-22 14:02:54 +03:00
|
|
|
void StatisticsReport::addParameters(const Category& category, const Parameters& parameters) {
|
2019-10-04 19:26:43 +03:00
|
|
|
if (_parameters.count(category) == 0)
|
|
|
|
|
_parameters[category] = parameters;
|
|
|
|
|
else
|
|
|
|
|
_parameters[category].insert(_parameters[category].end(), parameters.begin(), parameters.end());
|
2019-04-12 18:25:53 +03:00
|
|
|
}
|
|
|
|
|
|
2019-10-04 19:26:43 +03:00
|
|
|
void StatisticsReport::dump() {
|
|
|
|
|
CsvDumper dumper(true, _config.report_folder + _separator + "benchmark_report.csv");
|
2019-08-09 19:02:42 +03:00
|
|
|
|
2021-04-22 14:02:54 +03:00
|
|
|
auto dump_parameters = [&dumper](const Parameters& parameters) {
|
2019-10-04 19:26:43 +03:00
|
|
|
for (auto& parameter : parameters) {
|
|
|
|
|
dumper << parameter.first << parameter.second;
|
|
|
|
|
dumper.endLine();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if (_parameters.count(Category::COMMAND_LINE_PARAMETERS)) {
|
|
|
|
|
dumper << "Command line parameters";
|
|
|
|
|
dumper.endLine();
|
2019-04-12 18:25:53 +03:00
|
|
|
|
2019-10-04 19:26:43 +03:00
|
|
|
dump_parameters(_parameters.at(Category::COMMAND_LINE_PARAMETERS));
|
|
|
|
|
dumper.endLine();
|
2019-04-12 18:25:53 +03:00
|
|
|
}
|
|
|
|
|
|
2019-10-04 19:26:43 +03:00
|
|
|
if (_parameters.count(Category::RUNTIME_CONFIG)) {
|
|
|
|
|
dumper << "Configuration setup";
|
2019-04-12 18:25:53 +03:00
|
|
|
dumper.endLine();
|
|
|
|
|
|
2019-10-04 19:26:43 +03:00
|
|
|
dump_parameters(_parameters.at(Category::RUNTIME_CONFIG));
|
2019-04-12 18:25:53 +03:00
|
|
|
dumper.endLine();
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-04 19:26:43 +03:00
|
|
|
if (_parameters.count(Category::EXECUTION_RESULTS)) {
|
|
|
|
|
dumper << "Execution results";
|
|
|
|
|
dumper.endLine();
|
2019-04-12 18:25:53 +03:00
|
|
|
|
2019-10-04 19:26:43 +03:00
|
|
|
dump_parameters(_parameters.at(Category::EXECUTION_RESULTS));
|
2019-04-12 18:25:53 +03:00
|
|
|
dumper.endLine();
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-04 19:26:43 +03:00
|
|
|
slog::info << "Statistics report is stored to " << dumper.getFilename() << slog::endl;
|
2019-04-12 18:25:53 +03:00
|
|
|
}
|
|
|
|
|
|
2021-04-22 14:02:54 +03:00
|
|
|
void StatisticsReport::dumpPerformanceCountersRequest(CsvDumper& dumper, const PerformaceCounters& perfCounts) {
|
2019-10-04 19:26:43 +03:00
|
|
|
auto performanceMapSorted = perfCountersSorted(perfCounts);
|
2019-04-12 18:25:53 +03:00
|
|
|
|
2019-10-04 19:26:43 +03:00
|
|
|
long long total = 0L;
|
|
|
|
|
long long total_cpu = 0L;
|
|
|
|
|
|
2021-04-22 14:02:54 +03:00
|
|
|
dumper << "layerName"
|
|
|
|
|
<< "execStatus"
|
|
|
|
|
<< "layerType"
|
|
|
|
|
<< "execType";
|
|
|
|
|
dumper << "realTime (ms)"
|
|
|
|
|
<< "cpuTime (ms)";
|
2019-10-04 19:26:43 +03:00
|
|
|
dumper.endLine();
|
2019-04-12 18:25:53 +03:00
|
|
|
|
2021-04-22 14:02:54 +03:00
|
|
|
for (const auto& layer : performanceMapSorted) {
|
2019-10-04 19:26:43 +03:00
|
|
|
dumper << layer.first; // layer name
|
|
|
|
|
|
|
|
|
|
switch (layer.second.status) {
|
2021-04-22 14:02:54 +03:00
|
|
|
case InferenceEngine::InferenceEngineProfileInfo::EXECUTED:
|
|
|
|
|
dumper << "EXECUTED";
|
|
|
|
|
break;
|
|
|
|
|
case InferenceEngine::InferenceEngineProfileInfo::NOT_RUN:
|
|
|
|
|
dumper << "NOT_RUN";
|
|
|
|
|
break;
|
|
|
|
|
case InferenceEngine::InferenceEngineProfileInfo::OPTIMIZED_OUT:
|
|
|
|
|
dumper << "OPTIMIZED_OUT";
|
|
|
|
|
break;
|
2019-04-12 18:25:53 +03:00
|
|
|
}
|
2019-10-04 19:26:43 +03:00
|
|
|
dumper << layer.second.layer_type << layer.second.exec_type;
|
2021-04-22 14:02:54 +03:00
|
|
|
dumper << std::to_string(layer.second.realTime_uSec / 1000.0) << std::to_string(layer.second.cpu_uSec / 1000.0);
|
2019-10-04 19:26:43 +03:00
|
|
|
total += layer.second.realTime_uSec;
|
|
|
|
|
total_cpu += layer.second.cpu_uSec;
|
|
|
|
|
dumper.endLine();
|
2019-04-12 18:25:53 +03:00
|
|
|
}
|
2021-04-22 14:02:54 +03:00
|
|
|
dumper << "Total"
|
|
|
|
|
<< ""
|
|
|
|
|
<< ""
|
|
|
|
|
<< "";
|
|
|
|
|
dumper << total / 1000.0 << total_cpu / 1000.0;
|
2019-10-04 19:26:43 +03:00
|
|
|
dumper.endLine();
|
|
|
|
|
dumper.endLine();
|
2019-04-12 18:25:53 +03:00
|
|
|
}
|
|
|
|
|
|
2021-04-22 14:02:54 +03:00
|
|
|
void StatisticsReport::dumpPerformanceCounters(const std::vector<PerformaceCounters>& perfCounts) {
|
2019-10-04 19:26:43 +03:00
|
|
|
if ((_config.report_type.empty()) || (_config.report_type == noCntReport)) {
|
2021-04-22 14:02:54 +03:00
|
|
|
slog::info << "Statistics collecting for performance counters was not "
|
|
|
|
|
"requested. No reports are dumped."
|
|
|
|
|
<< slog::endl;
|
2019-10-04 19:26:43 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (perfCounts.empty()) {
|
2020-11-11 15:35:39 +03:00
|
|
|
slog::info << "Performance counters are empty. No reports are dumped." << slog::endl;
|
2019-10-04 19:26:43 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
CsvDumper dumper(true, _config.report_folder + _separator + "benchmark_" + _config.report_type + "_report.csv");
|
|
|
|
|
if (_config.report_type == detailedCntReport) {
|
|
|
|
|
for (auto& pc : perfCounts) {
|
|
|
|
|
dumpPerformanceCountersRequest(dumper, pc);
|
|
|
|
|
}
|
|
|
|
|
} else if (_config.report_type == averageCntReport) {
|
2021-04-22 14:02:54 +03:00
|
|
|
auto getAveragePerformanceCounters = [&perfCounts]() {
|
2019-10-04 19:26:43 +03:00
|
|
|
std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> performanceCountersAvg;
|
|
|
|
|
// iterate over each processed infer request and handle its PM data
|
|
|
|
|
for (size_t i = 0; i < perfCounts.size(); i++) {
|
2020-02-11 22:48:49 +03:00
|
|
|
auto performanceMapSorted = perfCountersSorted(perfCounts[i]);
|
2021-04-22 14:02:54 +03:00
|
|
|
// iterate over each layer from sorted vector and add required PM data
|
|
|
|
|
// to the per-layer maps
|
2019-10-04 19:26:43 +03:00
|
|
|
for (const auto& pm : performanceMapSorted) {
|
|
|
|
|
if (performanceCountersAvg.count(pm.first) == 0) {
|
|
|
|
|
performanceCountersAvg[pm.first] = perfCounts.at(i).at(pm.first);
|
|
|
|
|
} else {
|
|
|
|
|
performanceCountersAvg[pm.first].realTime_uSec += perfCounts.at(i).at(pm.first).realTime_uSec;
|
|
|
|
|
performanceCountersAvg[pm.first].cpu_uSec += perfCounts.at(i).at(pm.first).cpu_uSec;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (auto& pm : performanceCountersAvg) {
|
|
|
|
|
pm.second.realTime_uSec /= perfCounts.size();
|
|
|
|
|
pm.second.cpu_uSec /= perfCounts.size();
|
|
|
|
|
}
|
|
|
|
|
return performanceCountersAvg;
|
|
|
|
|
};
|
|
|
|
|
dumpPerformanceCountersRequest(dumper, getAveragePerformanceCounters());
|
|
|
|
|
} else {
|
|
|
|
|
throw std::logic_error("PM data can only be collected for average or detailed report types");
|
|
|
|
|
}
|
2021-02-16 13:08:54 +09:00
|
|
|
slog::info << "Performance counters report is stored to " << dumper.getFilename() << slog::endl;
|
2019-04-12 18:25:53 +03:00
|
|
|
}
|