[tools] Allow to use node name in command line parameters in python benchmark app (#9874)
* support node names in model specific parameters * allow to use node name in -i parameter
This commit is contained in:
parent
41d4fcdf25
commit
fe5c16ba6a
@ -155,13 +155,13 @@ def get_image_tensors(image_paths, info, batch_sizes):
|
|||||||
logger.warning(f"Image is resized from ({image.shape[:-1]}) to ({new_im_size})")
|
logger.warning(f"Image is resized from ({image.shape[:-1]}) to ({new_im_size})")
|
||||||
image = cv2.resize(image, new_im_size)
|
image = cv2.resize(image, new_im_size)
|
||||||
|
|
||||||
if info.scale or info.mean:
|
if info.scale.size or info.mean.size:
|
||||||
blue, green, red = cv2.split(image)
|
blue, green, red = cv2.split(image)
|
||||||
if info.mean:
|
if info.mean.size:
|
||||||
blue = np.subtract(blue, info.mean[0])
|
blue = np.subtract(blue, info.mean[0])
|
||||||
green = np.subtract(green, info.mean[1])
|
green = np.subtract(green, info.mean[1])
|
||||||
red = np.subtract(red, info.mean[2])
|
red = np.subtract(red, info.mean[2])
|
||||||
if info.scale:
|
if info.scale.size:
|
||||||
blue = np.divide(blue, info.scale[0])
|
blue = np.divide(blue, info.scale[0])
|
||||||
green = np.divide(green, info.scale[1])
|
green = np.divide(green, info.scale[1])
|
||||||
red = np.divide(red, info.scale[2])
|
red = np.divide(red, info.scale[2])
|
||||||
@ -314,20 +314,22 @@ def parse_path(path, app_input_info):
|
|||||||
"""
|
"""
|
||||||
Parse "input_1:file1/dir1,file2/dir2,input_2:file3/dir3 or file1/dir1,file2/dir2" into two dicts - with binary files and with images
|
Parse "input_1:file1/dir1,file2/dir2,input_2:file3/dir3 or file1/dir1,file2/dir2" into two dicts - with binary files and with images
|
||||||
"""
|
"""
|
||||||
input_names = sorted(list(info.name for info in app_input_info))
|
input_names = list(info.name for info in app_input_info)
|
||||||
|
input_node_names = list(info.node_name for info in app_input_info)
|
||||||
parsed_names = re.findall(r"([^,]\w+):", path)
|
parsed_names = re.findall(r"([^,]\w+):", path)
|
||||||
wrong_names = list(name for name in parsed_names if name not in input_names)
|
wrong_names = list(name for name in parsed_names if name not in input_names + input_node_names)
|
||||||
if wrong_names:
|
if wrong_names:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
f"Wrong input mapping! Cannot find inputs: {wrong_names}. "
|
f"Wrong input mapping! Cannot find inputs: {wrong_names}. "
|
||||||
f"Available inputs: {input_names}. "
|
f"Available inputs: {input_names}. "
|
||||||
"Please check `-i` input data"
|
"Please check `-i` input data"
|
||||||
)
|
)
|
||||||
|
tensor_names = [parsed_name if parsed_name in input_names else input_names[input_node_names.index(parsed_name)] for parsed_name in parsed_names]
|
||||||
input_pathes = [path for path in re.split(r"[^,]\w+:", path) if path]
|
input_pathes = [path for path in re.split(r"[^,]\w+:", path) if path]
|
||||||
input_path_mapping = defaultdict(list)
|
input_path_mapping = defaultdict(list)
|
||||||
# input mapping is used
|
# input mapping is used
|
||||||
if parsed_names:
|
if tensor_names:
|
||||||
input_path_mapping = {input_: files.strip(",").split(",") for input_, files in zip(parsed_names, input_pathes)}
|
input_path_mapping = {input_: files.strip(",").split(",") for input_, files in zip(tensor_names, input_pathes)}
|
||||||
else:
|
else:
|
||||||
input_files = list()
|
input_files = list()
|
||||||
_input_pathes = input_pathes[0].strip(",").split(",")
|
_input_pathes = input_pathes[0].strip(",").split(",")
|
||||||
|
@ -86,27 +86,35 @@ def pre_post_processing(model: Model, app_inputs_info, input_precision: str, out
|
|||||||
pre_post_processor.output(i).tensor().set_element_type(element_type)
|
pre_post_processor.output(i).tensor().set_element_type(element_type)
|
||||||
user_precision_map = {}
|
user_precision_map = {}
|
||||||
if input_output_precision:
|
if input_output_precision:
|
||||||
user_precision_map = _parse_arg_map(input_output_precision)
|
user_precision_map = parse_input_output_precision(input_output_precision)
|
||||||
input_names = get_input_output_names(model.inputs)
|
input_names = get_input_output_names(model.inputs)
|
||||||
|
input_node_names = get_node_names(model.inputs)
|
||||||
output_names = get_input_output_names(model.outputs)
|
output_names = get_input_output_names(model.outputs)
|
||||||
|
output_node_names = get_node_names(model.outputs)
|
||||||
for node_name, precision in user_precision_map.items():
|
for node_name, precision in user_precision_map.items():
|
||||||
user_precision_map[node_name] = get_element_type(precision)
|
user_precision_map[node_name] = get_element_type(precision)
|
||||||
for name, element_type in user_precision_map.items():
|
for name, element_type in user_precision_map.items():
|
||||||
if name in input_names:
|
if name in input_names or name in input_node_names:
|
||||||
port = input_names.index(name)
|
input_index = input_names.index(name) if name in input_names else input_node_names.index(name)
|
||||||
app_inputs_info[port].element_type = element_type
|
app_inputs_info[input_index].element_type = element_type
|
||||||
pre_post_processor.input(name).tensor().set_element_type(element_type)
|
pre_post_processor.input(input_index).tensor().set_element_type(element_type)
|
||||||
elif name in output_names:
|
elif name in output_names or name in output_node_names:
|
||||||
pre_post_processor.output(name).tensor().set_element_type(element_type)
|
if name in output_names:
|
||||||
|
pre_post_processor.output(name).tensor().set_element_type(element_type)
|
||||||
|
else:
|
||||||
|
pre_post_processor.output(output_node_names.index(name)).tensor().set_element_type(element_type)
|
||||||
else:
|
else:
|
||||||
raise Exception(f"Node '{name}' does not exist in network")
|
raise Exception(f"Node '{name}' does not exist in model")
|
||||||
|
|
||||||
# update app_inputs_info
|
# update app_inputs_info
|
||||||
if not input_precision:
|
if not input_precision:
|
||||||
inputs = model.inputs
|
inputs = model.inputs
|
||||||
|
input_node_names = get_node_names(model.inputs)
|
||||||
for i in range(len(inputs)):
|
for i in range(len(inputs)):
|
||||||
if app_inputs_info[i].name in user_precision_map.keys():
|
if app_inputs_info[i].name in user_precision_map:
|
||||||
app_inputs_info[i].element_type = user_precision_map[app_inputs_info[i].name]
|
app_inputs_info[i].element_type = user_precision_map[app_inputs_info[i].name]
|
||||||
|
elif input_node_names[i] in user_precision_map:
|
||||||
|
app_inputs_info[i].element_type = user_precision_map[input_node_names[i]]
|
||||||
elif app_inputs_info[i].is_image:
|
elif app_inputs_info[i].is_image:
|
||||||
app_inputs_info[i].element_type = Type.u8
|
app_inputs_info[i].element_type = Type.u8
|
||||||
pre_post_processor.input(i).tensor().set_element_type(Type.u8)
|
pre_post_processor.input(i).tensor().set_element_type(Type.u8)
|
||||||
@ -118,14 +126,19 @@ def pre_post_processing(model: Model, app_inputs_info, input_precision: str, out
|
|||||||
model = pre_post_processor.build()
|
model = pre_post_processor.build()
|
||||||
|
|
||||||
|
|
||||||
def _parse_arg_map(arg_map: str):
|
def parse_input_output_precision(arg_map: str):
|
||||||
arg_map = arg_map.replace(" ", "")
|
arg_map = arg_map.replace(" ", "")
|
||||||
pairs = [x.strip() for x in arg_map.split(',')]
|
pairs = [x.strip() for x in arg_map.split(',')]
|
||||||
|
|
||||||
parsed_map = {}
|
parsed_map = {}
|
||||||
for pair in pairs:
|
for pair in pairs:
|
||||||
key_value = [x.strip() for x in pair.split(':')]
|
key_value = [x.strip() for x in pair.split(':')]
|
||||||
parsed_map.update({key_value[0]:key_value[1]})
|
name, precision = key_value[0], key_value[1]
|
||||||
|
# input's name can contain ':'
|
||||||
|
if len(key_value) == 3:
|
||||||
|
name = key_value[0] + ':' + key_value[1]
|
||||||
|
precision = key_value[2]
|
||||||
|
parsed_map.update({name:precision})
|
||||||
|
|
||||||
return parsed_map
|
return parsed_map
|
||||||
|
|
||||||
@ -346,6 +359,8 @@ def get_command_line_arguments(argv):
|
|||||||
def get_input_output_names(ports):
|
def get_input_output_names(ports):
|
||||||
return [port.any_name for port in ports]
|
return [port.any_name for port in ports]
|
||||||
|
|
||||||
|
def get_node_names(ports):
|
||||||
|
return [port.node.friendly_name for port in ports]
|
||||||
|
|
||||||
def get_data_shapes_map(data_shape_string, input_names):
|
def get_data_shapes_map(data_shape_string, input_names):
|
||||||
# Parse parameter string like "input0[shape1][shape2],input1[shape1]" or "[shape1][shape2]" (applied to all inputs)
|
# Parse parameter string like "input0[shape1][shape2],input1[shape1]" or "[shape1][shape2]" (applied to all inputs)
|
||||||
@ -419,9 +434,10 @@ class AppInputInfo:
|
|||||||
self.original_shape = None
|
self.original_shape = None
|
||||||
self.partial_shape = None
|
self.partial_shape = None
|
||||||
self.data_shapes = []
|
self.data_shapes = []
|
||||||
self.scale = []
|
self.scale = np.empty([0])
|
||||||
self.mean = []
|
self.mean = np.empty([0])
|
||||||
self.name = None
|
self.name = None
|
||||||
|
self.node_name = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_image(self):
|
def is_image(self):
|
||||||
@ -528,6 +544,7 @@ def parse_batch_size(batch_size_str):
|
|||||||
|
|
||||||
def get_inputs_info(shape_string, data_shape_string, layout_string, batch_size, scale_string, mean_string, inputs):
|
def get_inputs_info(shape_string, data_shape_string, layout_string, batch_size, scale_string, mean_string, inputs):
|
||||||
input_names = get_input_output_names(inputs)
|
input_names = get_input_output_names(inputs)
|
||||||
|
input_node_names = get_node_names(inputs)
|
||||||
shape_map = parse_input_parameters(shape_string, input_names)
|
shape_map = parse_input_parameters(shape_string, input_names)
|
||||||
data_shape_map = get_data_shapes_map(data_shape_string, input_names)
|
data_shape_map = get_data_shapes_map(data_shape_string, input_names)
|
||||||
layout_map = parse_input_parameters(layout_string, input_names)
|
layout_map = parse_input_parameters(layout_string, input_names)
|
||||||
@ -539,19 +556,26 @@ def get_inputs_info(shape_string, data_shape_string, layout_string, batch_size,
|
|||||||
info = AppInputInfo()
|
info = AppInputInfo()
|
||||||
# Input name
|
# Input name
|
||||||
info.name = input_names[i]
|
info.name = input_names[i]
|
||||||
|
# Input node name
|
||||||
|
info.node_name = input_node_names[i]
|
||||||
# Input precision
|
# Input precision
|
||||||
info.element_type = inputs[i].element_type
|
info.element_type = inputs[i].element_type
|
||||||
# Shape
|
# Shape
|
||||||
info.original_shape = inputs[i].partial_shape
|
info.original_shape = inputs[i].partial_shape
|
||||||
if info.name in shape_map.keys():
|
if info.name in shape_map:
|
||||||
info.partial_shape = parse_partial_shape(shape_map[info.name])
|
info.partial_shape = parse_partial_shape(shape_map[info.name])
|
||||||
reshape = True
|
reshape = True
|
||||||
|
elif info.node_name in shape_map:
|
||||||
|
info.partial_shape = parse_partial_shape(shape_map[info.node_name])
|
||||||
|
reshape = True
|
||||||
else:
|
else:
|
||||||
info.partial_shape = inputs[i].partial_shape
|
info.partial_shape = inputs[i].partial_shape
|
||||||
|
|
||||||
# Layout
|
# Layout
|
||||||
if info.name in layout_map.keys():
|
if info.name in layout_map:
|
||||||
info.layout = Layout(layout_map[info.name])
|
info.layout = Layout(layout_map[info.name])
|
||||||
|
elif info.node_name in layout_map:
|
||||||
|
info.layout = Layout(layout_map[info.node_name])
|
||||||
elif inputs[i].node.layout != Layout():
|
elif inputs[i].node.layout != Layout():
|
||||||
info.layout = inputs[i].node.layout
|
info.layout = inputs[i].node.layout
|
||||||
else:
|
else:
|
||||||
@ -592,8 +616,9 @@ def get_inputs_info(shape_string, data_shape_string, layout_string, batch_size,
|
|||||||
raise Exception(f"Batch dimension is not specified for this model!")
|
raise Exception(f"Batch dimension is not specified for this model!")
|
||||||
|
|
||||||
# Data shape
|
# Data shape
|
||||||
if info.name in data_shape_map.keys() and info.is_dynamic:
|
if (info.name in data_shape_map or info.node_name in data_shape_map) and info.is_dynamic:
|
||||||
for p_shape in data_shape_map[info.name]:
|
used_name = info.name if info.name in data_shape_map else info.node_name
|
||||||
|
for p_shape in data_shape_map[used_name]:
|
||||||
if p_shape.is_dynamic:
|
if p_shape.is_dynamic:
|
||||||
raise Exception(f"Data shape always should be static, {str(p_shape)} is dynamic.")
|
raise Exception(f"Data shape always should be static, {str(p_shape)} is dynamic.")
|
||||||
elif info.partial_shape.compatible(p_shape):
|
elif info.partial_shape.compatible(p_shape):
|
||||||
@ -601,7 +626,7 @@ def get_inputs_info(shape_string, data_shape_string, layout_string, batch_size,
|
|||||||
else:
|
else:
|
||||||
raise Exception(f"Data shape '{str(p_shape)}' provided for input '{info.name}' "
|
raise Exception(f"Data shape '{str(p_shape)}' provided for input '{info.name}' "
|
||||||
f"is not compatible with partial shape '{str(info.partial_shape)}' for this input.")
|
f"is not compatible with partial shape '{str(info.partial_shape)}' for this input.")
|
||||||
elif info.name in data_shape_map.keys():
|
elif info.name in data_shape_map or input_node_names[i] in data_shape_map:
|
||||||
logger.warning(f"Input '{info.name}' has static shape. Provided data shapes for this input will be ignored.")
|
logger.warning(f"Input '{info.name}' has static shape. Provided data shapes for this input will be ignored.")
|
||||||
|
|
||||||
input_info.append(info)
|
input_info.append(info)
|
||||||
@ -612,9 +637,13 @@ def get_inputs_info(shape_string, data_shape_string, layout_string, batch_size,
|
|||||||
|
|
||||||
for input in input_info:
|
for input in input_info:
|
||||||
if input.name in scale_map:
|
if input.name in scale_map:
|
||||||
input.scale = scale_map[input.name]
|
input.scale = scale_map[input.name]
|
||||||
|
elif input.node_name in scale_map:
|
||||||
|
input.scale = scale_map[input.node_name]
|
||||||
if input.name in mean_map:
|
if input.name in mean_map:
|
||||||
input.mean = mean_map[input.name]
|
input.mean = mean_map[input.name]
|
||||||
|
elif input.node_name in mean_map:
|
||||||
|
input.mean = mean_map[input.node_name]
|
||||||
|
|
||||||
return input_info, reshape
|
return input_info, reshape
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user