replace benchmark_app imean and iscale parameters (#14621)
* replace benchmark_app imean and iscale parameters Tickets 80777 and 80900 * Warn about difference with imean and iscale, note that in help * Clang format * Clang format * mean->scale * Keep mean scale empty if not set Co-authored-by: Andrei Kochin <andrei.kochin@intel.com>
This commit is contained in:
@@ -183,14 +183,8 @@ Options:
|
||||
Example: -iop "input:FP16, output:FP16".
|
||||
Notice that quotes are required.
|
||||
Overwrites precision from ip and op options for specified layers.
|
||||
-iscale Optional. Scale values to be used for the input image per channel.
|
||||
Values to be provided in the [R, G, B] format. Can be defined for desired input of the model.
|
||||
Example: -iscale data[255,255,255],info[255,255,255]
|
||||
|
||||
-imean Optional. Mean values to be used for the input image per channel.
|
||||
Values to be provided in the [R, G, B] format. Can be defined for desired input of the model,
|
||||
Example: -imean data[255,255,255],info[255,255,255]
|
||||
|
||||
-mean_values [R,G,B] Optional. Mean values to be used for the input image per channel. Values to be provided in the [R,G,B] format. Can be defined for desired input of the model, for example: "--mean_values data[255,255,255],info[255,255,255]". The exact meaning and order of channels depend on how the original model was trained. Applying the values affects performance and may cause type conversion
|
||||
-scale_values [R,G,B] Optional. Scale values to be used for the input image per channel. Values are provided in the [R,G,B] format. Can be defined for desired input of the model, for example: "--scale_values data[255,255,255],info[255,255,255]". The exact meaning and order of channels depend on how the original model was trained. If both --mean_values and --scale_values are specified, the mean is subtracted first and then scale is applied regardless of the order of options in command line. Applying the values affects performance and may cause type conversion
|
||||
-inference_only Optional. Measure only inference stage. Default option for static models. Dynamic models are measured in full mode which includes inputs setup stage, inference only mode available for them with single input data shape only. To enable full mode for static models pass "false" value to this argument: ex. "-inference_only=false".
|
||||
```
|
||||
|
||||
|
||||
@@ -244,10 +244,18 @@ static constexpr char input_image_scale_message[] =
|
||||
"Values to be provided in the [R, G, B] format. Can be defined for desired input of the model.\n"
|
||||
"Example: -iscale data[255,255,255],info[255,255,255]\n";
|
||||
|
||||
static constexpr char input_image_mean_message[] =
|
||||
"Optional. Mean values to be used for the input image per channel.\n"
|
||||
"Values to be provided in the [R, G, B] format. Can be defined for desired input of the model,\n"
|
||||
"Example: -imean data[255,255,255],info[255,255,255]\n";
|
||||
static constexpr char mean_values_message[] =
|
||||
"Optional. Mean values to be used for the input image per channel. Values to be provided in the [R,G,B] format. "
|
||||
"Can be defined for desired input of the model, for example: \"--mean_values "
|
||||
"data[255,255,255],info[255,255,255]\". The exact meaning and order of channels depend on how the original model "
|
||||
"was trained. Applying the values affects performance and may cause type conversion";
|
||||
|
||||
static constexpr char scale_values_message[] =
|
||||
"Optional. Scale values to be used for the input image per channel. Values are provided in the [R,G,B] format. Can "
|
||||
"be defined for desired input of the model, for example: \"--scale_values data[255,255,255],info[255,255,255]\". "
|
||||
"The exact meaning and order of channels depend on how the original model was trained. If both --mean_values and "
|
||||
"--scale_values are specified, the mean is subtracted first and then scale is applied regardless of the order of "
|
||||
"options in command line. Applying the values affects performance and may cause type conversion";
|
||||
|
||||
static constexpr char inference_only_message[] =
|
||||
"Optional. Measure only inference stage. Default option for static models. Dynamic models"
|
||||
@@ -377,11 +385,11 @@ DEFINE_string(cache_dir, "", cache_dir_message);
|
||||
/// @brief Define flag for load network from model file by name without ReadNetwork <br>
|
||||
DEFINE_bool(load_from_file, false, load_from_file_message);
|
||||
|
||||
/// @brief Define flag for using input image scale <br>
|
||||
DEFINE_string(iscale, "", input_image_scale_message);
|
||||
|
||||
/// @brief Define flag for using input image mean <br>
|
||||
DEFINE_string(imean, "", input_image_mean_message);
|
||||
DEFINE_string(mean_values, "", mean_values_message);
|
||||
|
||||
/// @brief Define flag for using input image scale <br>
|
||||
DEFINE_string(scale_values, "", scale_values_message);
|
||||
|
||||
/// @brief Define flag for inference only mode <br>
|
||||
DEFINE_bool(inference_only, true, inference_only_message);
|
||||
@@ -435,7 +443,7 @@ static void show_usage() {
|
||||
std::cout << " -ip <value> " << inputs_precision_message << std::endl;
|
||||
std::cout << " -op <value> " << outputs_precision_message << std::endl;
|
||||
std::cout << " -iop \"<value>\" " << iop_message << std::endl;
|
||||
std::cout << " -iscale " << input_image_scale_message << std::endl;
|
||||
std::cout << " -imean " << input_image_mean_message << std::endl;
|
||||
std::cout << " -mean_values [R,G,B] " << mean_values_message << std::endl;
|
||||
std::cout << " -scale_values [R,G,B] " << scale_values_message << std::endl;
|
||||
std::cout << " -inference_only " << inference_only_message << std::endl;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ ov::Tensor create_tensor_from_image(const std::vector<std::string>& files,
|
||||
if (!inputInfo.layout.empty() && ov::layout::has_batch(inputInfo.layout)) {
|
||||
imgBatchSize = batchSize;
|
||||
} else {
|
||||
slog::warn << inputName << ": layout does not contain batch dimension. Assuming bath 1 for this input"
|
||||
slog::warn << inputName << ": layout does not contain batch dimension. Assuming batch 1 for this input"
|
||||
<< slog::endl;
|
||||
}
|
||||
|
||||
@@ -83,10 +83,7 @@ ov::Tensor create_tensor_from_image(const std::vector<std::string>& files,
|
||||
(((inputInfo.layout == "NCHW") || (inputInfo.layout == "CHW"))
|
||||
? (ch * width * height + h * width + w)
|
||||
: (h * width * numChannels + w * numChannels + ch));
|
||||
data[offset] =
|
||||
(static_cast<T>(vreader.at(b).get()[h * width * numChannels + w * numChannels + ch]) -
|
||||
static_cast<T>(inputInfo.mean[ch])) /
|
||||
static_cast<T>(inputInfo.scale[ch]);
|
||||
data[offset] = static_cast<T>(vreader.at(b).get()[h * width * numChannels + w * numChannels + ch]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,6 +200,35 @@ void warn_if_no_batch(const benchmark_app::InputsInfo& first_inputs) {
|
||||
<< slog::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void fuse_mean_scale(ov::preprocess::PrePostProcessor& preproc, const benchmark_app::InputsInfo& app_inputs_info) {
|
||||
// TODO: remove warning after 23.3 release
|
||||
bool warned = false;
|
||||
constexpr char warn_msg[] = "Mean/scale values are fused into the model. This slows down performance compared to "
|
||||
"--imean and --iscale which existed before";
|
||||
for (const std::pair<std::string, benchmark_app::InputInfo>& input_info : app_inputs_info) {
|
||||
if (!input_info.second.mean.empty()) {
|
||||
if (!warned) {
|
||||
slog::warn << warn_msg << slog::endl;
|
||||
warned = true;
|
||||
}
|
||||
preproc.input(input_info.first)
|
||||
.preprocess()
|
||||
.convert_element_type(ov::element::f32)
|
||||
.mean(input_info.second.mean);
|
||||
}
|
||||
if (!input_info.second.scale.empty()) {
|
||||
if (!warned) {
|
||||
slog::warn << warn_msg << slog::endl;
|
||||
warned = true;
|
||||
}
|
||||
preproc.input(input_info.first)
|
||||
.preprocess()
|
||||
.convert_element_type(ov::element::f32)
|
||||
.scale(input_info.second.scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/**
|
||||
@@ -607,6 +636,10 @@ int main(int argc, char* argv[]) {
|
||||
bool isDynamicNetwork = false;
|
||||
|
||||
if (FLAGS_load_from_file && !isNetworkCompiled) {
|
||||
if (!FLAGS_mean_values.empty() || !FLAGS_scale_values.empty()) {
|
||||
throw std::runtime_error("--mean_values and --scale_values aren't supported with --load_from_file. "
|
||||
"The values can be set via model_optimizer while generating xml");
|
||||
}
|
||||
next_step();
|
||||
slog::info << "Skipping the step for loading model from file" << slog::endl;
|
||||
next_step();
|
||||
@@ -631,8 +664,8 @@ int main(int argc, char* argv[]) {
|
||||
batchSize,
|
||||
FLAGS_data_shape,
|
||||
inputFiles,
|
||||
FLAGS_iscale,
|
||||
FLAGS_imean,
|
||||
FLAGS_scale_values,
|
||||
FLAGS_mean_values,
|
||||
compiledModel.inputs());
|
||||
if (batchSize == 0) {
|
||||
batchSize = 1;
|
||||
@@ -678,8 +711,8 @@ int main(int argc, char* argv[]) {
|
||||
FLAGS_b,
|
||||
FLAGS_data_shape,
|
||||
inputFiles,
|
||||
FLAGS_iscale,
|
||||
FLAGS_imean,
|
||||
FLAGS_scale_values,
|
||||
FLAGS_mean_values,
|
||||
inputInfo,
|
||||
reshape);
|
||||
if (reshape) {
|
||||
@@ -752,6 +785,8 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
fuse_mean_scale(preproc, app_inputs_info.at(0));
|
||||
|
||||
const auto& outs = model->outputs();
|
||||
for (int i = 0; i < outs.size(); i++) {
|
||||
const auto& item = outs[i];
|
||||
@@ -799,6 +834,10 @@ int main(int argc, char* argv[]) {
|
||||
StatisticsReport::Category::EXECUTION_RESULTS,
|
||||
{StatisticsVariant("compile model time (ms)", "load_model_time", duration_ms)});
|
||||
} else {
|
||||
if (!FLAGS_mean_values.empty() || !FLAGS_scale_values.empty()) {
|
||||
throw std::runtime_error("--mean_values and --scale_values aren't supported for compiled model. "
|
||||
"The values can be set via model_optimizer while generating xml");
|
||||
}
|
||||
next_step();
|
||||
slog::info << "Skipping the step for compiled model" << slog::endl;
|
||||
next_step();
|
||||
@@ -833,8 +872,8 @@ int main(int argc, char* argv[]) {
|
||||
FLAGS_b,
|
||||
FLAGS_data_shape,
|
||||
inputFiles,
|
||||
FLAGS_iscale,
|
||||
FLAGS_imean,
|
||||
FLAGS_scale_values,
|
||||
FLAGS_mean_values,
|
||||
compiledModel.inputs());
|
||||
if (batchSize == 0) {
|
||||
batchSize = 1;
|
||||
|
||||
@@ -223,7 +223,7 @@ std::string get_shapes_string(const benchmark_app::PartialShapes& shapes) {
|
||||
|
||||
std::map<std::string, std::vector<float>> parse_scale_or_mean(const std::string& scale_mean,
|
||||
const benchmark_app::InputsInfo& inputs_info) {
|
||||
// Format: data:[255,255,255],info[255,255,255]
|
||||
// Format: data[255,255,255],info[255,255,255]
|
||||
std::map<std::string, std::vector<float>> return_value;
|
||||
|
||||
std::string search_string = scale_mean;
|
||||
@@ -630,9 +630,6 @@ std::vector<benchmark_app::InputsInfo> get_inputs_info(const std::string& shape_
|
||||
|
||||
for (auto& item : info_map) {
|
||||
if (item.second.is_image()) {
|
||||
item.second.scale.assign({1, 1, 1});
|
||||
item.second.mean.assign({0, 0, 0});
|
||||
|
||||
if (scale_map.count(item.first)) {
|
||||
item.second.scale = scale_map.at(item.first);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ usage: benchmark_app.py [-h [HELP]] [-i PATHS_TO_INPUT [PATHS_TO_INPUT ...]] -m
|
||||
[-pin {YES,NO,NUMA,HYBRID_AWARE}] [-exec_graph_path EXEC_GRAPH_PATH] [-pc [PERF_COUNTS]] [-pcsort {no_sort,sort,simple_sort}] [-pcseq [PCSEQ]]
|
||||
[-inference_only [INFERENCE_ONLY]] [-report_type {no_counters,average_counters,detailed_counters}] [-report_folder REPORT_FOLDER] [-dump_config DUMP_CONFIG]
|
||||
[-load_config LOAD_CONFIG] [-infer_precision INFER_PRECISION] [-ip {u8,U8,f16,FP16,f32,FP32}] [-op {u8,U8,f16,FP16,f32,FP32}] [-iop INPUT_OUTPUT_PRECISION]
|
||||
[-cdir CACHE_DIR] [-lfile [LOAD_FROM_FILE]] [-iscale INPUT_SCALE] [-imean INPUT_MEAN]
|
||||
[-cdir CACHE_DIR] [-lfile [LOAD_FROM_FILE]] [--mean_values [R,G,B]] [--scale_values [R,G,B]]
|
||||
|
||||
Options:
|
||||
-h [HELP], --help [HELP]
|
||||
@@ -214,12 +214,16 @@ Options:
|
||||
Optional. Enable model caching to specified directory
|
||||
-lfile [LOAD_FROM_FILE], --load_from_file [LOAD_FROM_FILE]
|
||||
Optional. Loads model from file directly without read_model.
|
||||
-iscale INPUT_SCALE, --input_scale INPUT_SCALE
|
||||
Optional. Scale values to be used for the input image per channel. Values to be provided in the [R, G, B] format. Can be defined for desired input of the model.
|
||||
Example: -iscale data[255,255,255],info[255,255,255]
|
||||
-imean INPUT_MEAN, --input_mean INPUT_MEAN
|
||||
Optional. Mean values to be used for the input image per channel. Values to be provided in the [R, G, B] format. Can be defined for desired input of the model. Example:
|
||||
-imean data[255,255,255],info[255,255,255]
|
||||
--mean_values [R,G,B]
|
||||
Optional. Mean values to be used for the input image per channel. Values to be provided in the [R,G,B] format. Can be defined for desired input
|
||||
of the model, for example: "--mean_values data[255,255,255],info[255,255,255]". The exact meaning and order of channels depend on how the
|
||||
original model was trained. Applying the values affects performance and may cause type conversion
|
||||
|
||||
--scale_values [R,G,B]
|
||||
Optional. Scale values to be used for the input image per channel. Values are provided in the [R,G,B] format. Can be defined for desired input
|
||||
of the model, for example: "--scale_values data[255,255,255],info[255,255,255]". The exact meaning and order of channels depend on how the
|
||||
original model was trained. If both --mean_values and --scale_values are specified, the mean is subtracted first and then scale is applied
|
||||
regardless of the order of options in command line. Applying the values affects performance and may cause type conversion
|
||||
```
|
||||
|
||||
Running the application with the empty list of options yields the usage message given above and an error message.
|
||||
|
||||
@@ -338,6 +338,9 @@ def main():
|
||||
topology_name = ""
|
||||
load_from_file_enabled = is_flag_set_in_command_line('load_from_file') or is_flag_set_in_command_line('lfile')
|
||||
if load_from_file_enabled and not is_network_compiled:
|
||||
if not args.mean_values or not args.scale_values:
|
||||
raise RuntimeError("--mean_values and --scale_values aren't supported with --load_from_file. "
|
||||
"The values can be set via model_optimizer while generating xml")
|
||||
next_step()
|
||||
print("Skipping the step for loading model from file")
|
||||
next_step()
|
||||
@@ -357,7 +360,7 @@ def main():
|
||||
[
|
||||
('compile model time (ms)', duration_ms)
|
||||
])
|
||||
app_inputs_info, _ = get_inputs_info(args.shape, args.data_shape, args.layout, args.batch_size, args.input_scale, args.input_mean, compiled_model.inputs)
|
||||
app_inputs_info, _ = get_inputs_info(args.shape, args.data_shape, args.layout, args.batch_size, args.scale_values, args.mean_values, compiled_model.inputs)
|
||||
batch_size = get_network_batch_size(app_inputs_info)
|
||||
elif not is_network_compiled:
|
||||
# --------------------- 4. Read the Intermediate Representation of the network -----------------------------
|
||||
@@ -382,7 +385,7 @@ def main():
|
||||
# --------------------- 5. Resizing network to match image sizes and given batch ---------------------------
|
||||
next_step()
|
||||
|
||||
app_inputs_info, reshape = get_inputs_info(args.shape, args.data_shape, args.layout, args.batch_size, args.input_scale, args.input_mean, model.inputs)
|
||||
app_inputs_info, reshape = get_inputs_info(args.shape, args.data_shape, args.layout, args.batch_size, args.scale_values, args.mean_values, model.inputs)
|
||||
|
||||
# use batch size according to provided layout and shapes
|
||||
batch_size = get_network_batch_size(app_inputs_info)
|
||||
@@ -421,6 +424,9 @@ def main():
|
||||
('compile model time (ms)', duration_ms)
|
||||
])
|
||||
else:
|
||||
if not args.mean_values or not args.scale_values:
|
||||
raise RuntimeError("--mean_values and --scale_values aren't supported for compiled model. "
|
||||
"The values can be set via model_optimizer while generating xml")
|
||||
next_step()
|
||||
print("Skipping the step for compiled model")
|
||||
next_step()
|
||||
@@ -440,7 +446,7 @@ def main():
|
||||
[
|
||||
('import model time (ms)', duration_ms)
|
||||
])
|
||||
app_inputs_info, _ = get_inputs_info(args.shape, args.data_shape, args.layout, args.batch_size, args.input_scale, args.input_mean, compiled_model.inputs)
|
||||
app_inputs_info, _ = get_inputs_info(args.shape, args.data_shape, args.layout, args.batch_size, args.scale_values, args.mean_values, compiled_model.inputs)
|
||||
batch_size = get_network_batch_size(app_inputs_info)
|
||||
|
||||
# --------------------- 8. Querying optimal runtime parameters --------------------------------------------------
|
||||
|
||||
@@ -172,12 +172,15 @@ def parse_args():
|
||||
help="Optional. Enable model caching to specified directory")
|
||||
args.add_argument('-lfile', '--load_from_file', required=False, nargs='?', default=argparse.SUPPRESS,
|
||||
help="Optional. Loads model from file directly without read_model.")
|
||||
args.add_argument('-iscale', '--input_scale', type=str, required=False, default='',
|
||||
help="Optional. Scale values to be used for the input image per channel.\n Values to be provided in the [R, G, B] format. Can be defined for desired input of the model.\n"
|
||||
"Example: -iscale data[255,255,255],info[255,255,255]\n")
|
||||
args.add_argument('-imean', '--input_mean', type=str, required=False, default='',
|
||||
help="Optional. Mean values to be used for the input image per channel.\n Values to be provided in the [R, G, B] format. Can be defined for desired input of the model.\n"
|
||||
"Example: -imean data[255,255,255],info[255,255,255]\n")
|
||||
args.add_argument('--mean_values', type=str, required=False, default='', metavar='[R,G,B]',
|
||||
help='Optional. Mean values to be used for the input image per channel. Values to be provided in the [R,G,B] format. Can be defined for '
|
||||
'desired input of the model, for example: "--mean_values data[255,255,255],info[255,255,255]". The exact meaning and order of '
|
||||
'channels depend on how the original model was trained')
|
||||
args.add_argument('--scale_values', type=str, required=False, default='', metavar='[R,G,B]',
|
||||
help='Optional. Scale values to be used for the input image per channel. Values are provided in the [R,G,B] format. Can be defined for '
|
||||
'desired input of the model, for example: "--scale_values data[255,255,255],info[255,255,255]". The exact meaning and order of '
|
||||
'channels depend on how the original model was trained. If both --mean_values and --scale_values are specified, the mean is '
|
||||
'subtracted first and then scale is applied regardless of the order of options in command line')
|
||||
parsed_args = parser.parse_args()
|
||||
|
||||
return parsed_args, parser
|
||||
|
||||
@@ -169,18 +169,6 @@ def get_image_tensors(image_paths, info, batch_sizes):
|
||||
logger.warning(f"Image is resized from ({image.shape[:-1]}) to ({new_im_size})")
|
||||
image = cv2.resize(image, new_im_size)
|
||||
|
||||
if info.scale.size or info.mean.size:
|
||||
blue, green, red = cv2.split(image)
|
||||
if info.mean.size:
|
||||
blue = np.subtract(blue, info.mean[0])
|
||||
green = np.subtract(green, info.mean[1])
|
||||
red = np.subtract(red, info.mean[2])
|
||||
if info.scale.size:
|
||||
blue = np.divide(blue, info.scale[0])
|
||||
green = np.divide(green, info.scale[1])
|
||||
red = np.divide(red, info.scale[2])
|
||||
image = cv2.merge([blue, green, red])
|
||||
|
||||
model_channel = int(str(info.channels))
|
||||
image_channel = image.shape[-1]
|
||||
if model_channel == 1 and image_channel == 3:
|
||||
|
||||
@@ -72,6 +72,25 @@ def get_element_type(precision):
|
||||
raise Exception(f"Undefined precision: '{precision}' !")
|
||||
|
||||
|
||||
def fuse_mean_scale(preproc: PrePostProcessor, app_inputs_info):
|
||||
# TODO: remove warning after 23.3 release
|
||||
warned = False;
|
||||
warn_msg = 'Mean/scale values are fused into the model. This slows down performance compared to --imean and --iscale which existed before'
|
||||
for input_info in app_inputs_info:
|
||||
print(input_info)
|
||||
print(input_info.mean)
|
||||
if input_info.mean.size:
|
||||
if not warned:
|
||||
logger.warning(warn_msg)
|
||||
warned = True
|
||||
preproc.input(input_info.name).preprocess().convert_element_type(Type.f32).mean(input_info.mean)
|
||||
if input_info.scale.size:
|
||||
if not warned:
|
||||
logger.warning(warn_msg)
|
||||
warned = True
|
||||
preproc.input(input_info.name).preprocess().convert_element_type(Type.f32).scale(input_info.scale)
|
||||
|
||||
|
||||
def pre_post_processing(model: Model, app_inputs_info, input_precision: str, output_precision: str, input_output_precision: str):
|
||||
pre_post_processor = PrePostProcessor(model)
|
||||
if input_precision:
|
||||
@@ -118,6 +137,8 @@ def pre_post_processing(model: Model, app_inputs_info, input_precision: str, out
|
||||
app_inputs_info[i].element_type = Type.u8
|
||||
pre_post_processor.input(i).tensor().set_element_type(Type.u8)
|
||||
|
||||
fuse_mean_scale(pre_post_processor, app_inputs_info)
|
||||
|
||||
# set layout for model input
|
||||
for info in app_inputs_info:
|
||||
pre_post_processor.input(info.name).model().set_layout(info.layout)
|
||||
|
||||
@@ -464,7 +464,7 @@ mo_convert_params = {
|
||||
'value. When a list of inputs is overridden by the --input ' +
|
||||
'parameter, this scale ' +
|
||||
'is not applied for any input that does not match with ' +
|
||||
'the original input of the model.' +
|
||||
'the original input of the model. ' +
|
||||
'If both --mean_values and --scale are specified, ' +
|
||||
'the mean is subtracted first and then scale is applied ' +
|
||||
'regardless of the order of options in command line.', '', '', None),
|
||||
@@ -526,7 +526,7 @@ mo_convert_params = {
|
||||
'Can be defined for desired input of the model, for example: ' +
|
||||
'"--scale_values data[255,255,255],info[255,255,255]". ' +
|
||||
'The exact meaning and order ' +
|
||||
'of channels depend on how the original model was trained.' +
|
||||
'of channels depend on how the original model was trained. ' +
|
||||
'If both --mean_values and --scale_values are specified, ' +
|
||||
'the mean is subtracted first and then scale is applied ' +
|
||||
'regardless of the order of options in command line.', '',
|
||||
|
||||
Reference in New Issue
Block a user