[SAMPLES][GNA] Update C++ speech sample with new config API (#10357)
* [SAMPLES][GNA] Update speech sample with new cofig API * Review comments * Some additional checks
This commit is contained in:
1 parent
2e71fccd82
commit
fc5a416423
4 files changed
+138
-49
No files matched your search
@@ -19,7 +19,7 @@
|
||||
|
||||
// clang-format off
|
||||
#include <openvino/openvino.hpp>
|
||||
#include <gna/gna_config.hpp>
|
||||
#include <openvino/runtime/intel_gna/properties.hpp>
|
||||
|
||||
#include <samples/args_helper.hpp>
|
||||
#include <samples/slog.hpp>
|
||||
@@ -141,8 +141,15 @@ int main(int argc, char* argv[]) {
|
||||
if (useGna) {
|
||||
std::string gnaDevice =
|
||||
useHetero ? FLAGS_d.substr(FLAGS_d.find("GNA"), FLAGS_d.find(",") - FLAGS_d.find("GNA")) : FLAGS_d;
|
||||
gnaPluginConfig[InferenceEngine::GNAConfigParams::KEY_GNA_DEVICE_MODE] =
|
||||
gnaDevice.find("_") == std::string::npos ? "GNA_AUTO" : gnaDevice;
|
||||
auto parse_gna_device = [&](const std::string& device) -> ov::intel_gna::ExecutionMode {
|
||||
ov::intel_gna::ExecutionMode mode;
|
||||
std::stringstream ss(device);
|
||||
ss >> mode;
|
||||
return mode;
|
||||
};
|
||||
gnaPluginConfig[ov::intel_gna::execution_mode.name()] = gnaDevice.find("_") == std::string::npos
|
||||
? ov::intel_gna::ExecutionMode::AUTO
|
||||
: parse_gna_device(gnaDevice);
|
||||
}
|
||||
if (FLAGS_pc) {
|
||||
genericPluginConfig.emplace(ov::enable_profiling(true));
|
||||
@@ -151,23 +158,23 @@ int main(int argc, char* argv[]) {
|
||||
if (!FLAGS_rg.empty()) {
|
||||
slog::warn << "Custom scale factor will be used for imported gna model: " << FLAGS_rg << slog::endl;
|
||||
}
|
||||
auto scaleFactorInput = parse_scale_factors(FLAGS_sf);
|
||||
if (numInputFiles != scaleFactorInput.size()) {
|
||||
auto scale_factors_per_input = parse_scale_factors(model->inputs(), FLAGS_sf);
|
||||
if (numInputFiles != scale_factors_per_input.size()) {
|
||||
std::string errMessage(
|
||||
"Incorrect command line for multiple inputs: " + std::to_string(scaleFactorInput.size()) +
|
||||
"Incorrect command line for multiple inputs: " + std::to_string(scale_factors_per_input.size()) +
|
||||
" scale factors provided for " + std::to_string(numInputFiles) + " input files.");
|
||||
throw std::logic_error(errMessage);
|
||||
}
|
||||
for (size_t i = 0; i < scaleFactorInput.size(); ++i) {
|
||||
slog::info << "For input " << i << " using scale factor of " << scaleFactorInput[i] << slog::endl;
|
||||
std::string scaleFactorConfigKey = GNA_CONFIG_KEY(SCALE_FACTOR) + std::string("_") + std::to_string(i);
|
||||
gnaPluginConfig[scaleFactorConfigKey] = scaleFactorInput[i];
|
||||
for (auto&& sf : scale_factors_per_input) {
|
||||
slog::info << "For input " << sf.first << " using scale factor of " << sf.second << slog::endl;
|
||||
}
|
||||
gnaPluginConfig[ov::intel_gna::scale_factors_per_input.name()] = scale_factors_per_input;
|
||||
} else {
|
||||
// "static" quantization with calculated scale factor
|
||||
if (!FLAGS_rg.empty()) {
|
||||
slog::info << "Using scale factor from provided imported gna model: " << FLAGS_rg << slog::endl;
|
||||
} else {
|
||||
std::map<std::string, float> scale_factors_per_input;
|
||||
for (size_t i = 0; i < numInputFiles; i++) {
|
||||
auto inputFileName = inputFiles[i].c_str();
|
||||
std::string name;
|
||||
@@ -187,30 +194,26 @@ int main(int argc, char* argv[]) {
|
||||
numFrames * numFrameElements);
|
||||
slog::info << "Using scale factor of " << floatScaleFactor << " calculated from first utterance."
|
||||
<< slog::endl;
|
||||
std::string scaleFactorConfigKey =
|
||||
GNA_CONFIG_KEY(SCALE_FACTOR) + std::string("_") + std::to_string(i);
|
||||
gnaPluginConfig[scaleFactorConfigKey] = std::to_string(floatScaleFactor);
|
||||
scale_factors_per_input[model->input(i).get_any_name()] = floatScaleFactor;
|
||||
}
|
||||
gnaPluginConfig[ov::intel_gna::scale_factors_per_input.name()] = scale_factors_per_input;
|
||||
}
|
||||
}
|
||||
if (FLAGS_qb == 8) {
|
||||
gnaPluginConfig[InferenceEngine::GNAConfigParams::KEY_GNA_PRECISION] = "I8";
|
||||
} else {
|
||||
gnaPluginConfig[InferenceEngine::GNAConfigParams::KEY_GNA_PRECISION] = "I16";
|
||||
}
|
||||
gnaPluginConfig[InferenceEngine::GNAConfigParams::KEY_GNA_EXEC_TARGET] = FLAGS_exec_target;
|
||||
gnaPluginConfig[InferenceEngine::GNAConfigParams::KEY_GNA_COMPILE_TARGET] = FLAGS_compile_target;
|
||||
gnaPluginConfig[GNA_CONFIG_KEY(COMPACT_MODE)] = CONFIG_VALUE(NO);
|
||||
IE_SUPPRESS_DEPRECATED_START
|
||||
gnaPluginConfig[GNA_CONFIG_KEY(PWL_MAX_ERROR_PERCENT)] = std::to_string(FLAGS_pwl_me);
|
||||
IE_SUPPRESS_DEPRECATED_END
|
||||
gnaPluginConfig[ov::hint::inference_precision.name()] = (FLAGS_qb == 8) ? ov::element::i8 : ov::element::i16;
|
||||
auto parse_target = [&](const std::string& target) -> ov::intel_gna::HWGeneration {
|
||||
return (target == "GNA_TARGET_2_0") ? ov::intel_gna::HWGeneration::GNA_2_0
|
||||
: (target == "GNA_TARGET_3_0") ? ov::intel_gna::HWGeneration::GNA_3_0
|
||||
: ov::intel_gna::HWGeneration::UNDEFINED;
|
||||
};
|
||||
gnaPluginConfig[ov::intel_gna::execution_target.name()] = parse_target(FLAGS_exec_target);
|
||||
gnaPluginConfig[ov::intel_gna::compile_target.name()] = parse_target(FLAGS_compile_target);
|
||||
gnaPluginConfig[ov::intel_gna::memory_reuse.name()] = false;
|
||||
gnaPluginConfig[ov::intel_gna::pwl_max_error_percent.name()] = FLAGS_pwl_me;
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// --------------------------- Write model to file --------------------------------------------------
|
||||
// Embedded GNA model dumping (for Intel(R) Speech Enabling Developer Kit)
|
||||
if (!FLAGS_we.empty()) {
|
||||
IE_SUPPRESS_DEPRECATED_START
|
||||
gnaPluginConfig[InferenceEngine::GNAConfigParams::KEY_GNA_FIRMWARE_MODEL_IMAGE] = FLAGS_we;
|
||||
IE_SUPPRESS_DEPRECATED_END
|
||||
gnaPluginConfig[ov::intel_gna::firmware_model_image_path.name()] = FLAGS_we;
|
||||
}
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// --------------------------- Step 2. Loading model to the device ------------------------------------------
|
||||
|
||||
@@ -90,7 +90,8 @@ static const char quantization_bits_message[] = "Optional. Weight bits for quant
|
||||
static const char scale_factor_message[] =
|
||||
"Optional. User-specified input scale factor for quantization (use with -q user). "
|
||||
"If the network contains multiple inputs, provide scale factors by separating them with "
|
||||
"commas.";
|
||||
"commas. "
|
||||
"For example: <input_name1>:<sf1>,<input_name2>:<sf2> or just <sf> to be applied to all inputs";
|
||||
|
||||
/// @brief message for batch size argument
|
||||
static const char batch_size_message[] = "Optional. Batch size 1-8 (default 1)";
|
||||
|
||||
@@ -361,30 +361,113 @@ void sum_performance_counters(std::map<std::string, ov::ProfilingInfo> const& pe
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse scale factors
|
||||
* @param str reference to user-specified input scale factor for quantization, can be separated by comma
|
||||
* @return vector scale factors
|
||||
* @brief Split string by delimeter
|
||||
* @param s input string
|
||||
* @param delim delimeter
|
||||
* @return vector of chunks
|
||||
*/
|
||||
std::vector<std::string> parse_scale_factors(const std::string& str) {
|
||||
std::vector<std::string> scaleFactorInput;
|
||||
std::vector<std::string> split(const std::string& s, char delim) {
|
||||
std::vector<std::string> result;
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
|
||||
if (!str.empty()) {
|
||||
std::string outStr;
|
||||
std::istringstream stream(str);
|
||||
int i = 0;
|
||||
while (getline(stream, outStr, ',')) {
|
||||
auto floatScaleFactor = std::stof(outStr);
|
||||
if (floatScaleFactor <= 0.0f) {
|
||||
throw std::logic_error("Scale factor for input #" + std::to_string(i) +
|
||||
" (counting from zero) is out of range (must be positive).");
|
||||
}
|
||||
scaleFactorInput.push_back(outStr);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
throw std::logic_error("Scale factor need to be specified via -sf option if you are using -q user");
|
||||
while (getline(ss, item, delim)) {
|
||||
result.push_back(item);
|
||||
}
|
||||
return scaleFactorInput;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Concat strings using delimeter
|
||||
* @param chunks input chunks
|
||||
* @param delim delimeter
|
||||
* @return concatenated string
|
||||
*/
|
||||
std::string concat(const std::vector<std::string>& chunks, char delim) {
|
||||
std::stringstream ss;
|
||||
for (auto&& chunk : chunks) {
|
||||
if (!ss.str().empty()) {
|
||||
ss << delim;
|
||||
}
|
||||
ss << chunk;
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether name is present in node vector
|
||||
* @param nodes nodes
|
||||
* @param node_name name
|
||||
* @return false or true
|
||||
*/
|
||||
bool check_name(const ov::OutputVector& nodes, const std::string& node_name) {
|
||||
std::vector<std::string> any_names;
|
||||
bool count = false;
|
||||
for (auto& node : nodes) {
|
||||
any_names.push_back(node.get_any_name());
|
||||
auto names = node.get_names();
|
||||
count = std::count(names.begin(), names.end(), node_name);
|
||||
if (count)
|
||||
break;
|
||||
}
|
||||
if (!count) {
|
||||
std::stringstream ss;
|
||||
ss << "Incorrect node name '" + node_name << "'! ";
|
||||
ss << "Try one of the following names: [ ";
|
||||
for (auto&& name : any_names) {
|
||||
ss << name << " ";
|
||||
}
|
||||
ss << "]";
|
||||
throw std::logic_error(ss.str());
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse scale factors per input
|
||||
* Format : <input_name1>:<sf1>,<input2>:<sf2> or just <sf>
|
||||
* @param inputs model inputs
|
||||
* @param values_string values_string input string
|
||||
* @return map of scale factors per input
|
||||
*/
|
||||
std::map<std::string, float> parse_scale_factors(const ov::OutputVector& inputs, const std::string& values_string) {
|
||||
auto get_sf = [&](const std::string& sf_string, const std::string& input_name = "") -> float {
|
||||
float sf;
|
||||
try {
|
||||
sf = std::stof(sf_string);
|
||||
} catch (...) {
|
||||
throw std::logic_error("Can't get float scale factor from: " + sf_string);
|
||||
}
|
||||
if (sf <= 0.0f) {
|
||||
throw std::logic_error("Scale factor for input '" + input_name +
|
||||
"' (counting from zero) is out of range (must be positive).");
|
||||
}
|
||||
return sf;
|
||||
};
|
||||
std::map<std::string, float> result;
|
||||
auto scale_factor_strings = split(values_string, ',');
|
||||
for (auto& scale_factor_string : scale_factor_strings) {
|
||||
auto values = split(scale_factor_string, ':');
|
||||
if (values.size() == 1) {
|
||||
if (scale_factor_strings.size() != 1) {
|
||||
throw std::logic_error("Unrecognized scale factor format! "
|
||||
"Please specify <input_name1>:<sf1>,<input_name2>:<sf2> or "
|
||||
"just <sf> to be applied to all inputs");
|
||||
}
|
||||
auto scale_factor = get_sf(values.at(0));
|
||||
for (auto& input : inputs) {
|
||||
result[input.get_any_name()] = scale_factor;
|
||||
}
|
||||
} else if (values.size() > 0) {
|
||||
auto sf_sting = values.back();
|
||||
values.pop_back();
|
||||
// input name can contain port, concat back
|
||||
auto input_name = concat(values, ':');
|
||||
check_name(inputs, input_name);
|
||||
result[input_name] = get_sf(sf_sting, input_name);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,8 @@ test_data = get_tests(cmd_params={'i': [os.path.join('ark', 'dev93_10.ark')],
|
||||
'o': ['res_output.ark'],
|
||||
'r': [os.path.join('ark', 'dev93_scores_10.ark')],
|
||||
'qb': [8, 16],
|
||||
'sf': ["Parameter:2175.43", "2175.43"],
|
||||
'q': ["static", "user"],
|
||||
'd': ['GNA_SW_EXACT']},
|
||||
use_device=False
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user