Files
openvino/model-optimizer/extensions/back/MarkNodesWithShapeValues.py
T
Pavel Esir 6477e8ec01 [MO] Fix fp16 in shapeof subgraphs (#4524)
* Initial working solution

* moved bfs_search_apply_on_shapeof_subgraph_nodes from utils/graph.py to MarkShapeOfSubgraphDataType.py

* Reused bfs from MarkSubgraphsWithCorrectLayout.py

* fixed e2e precomit issues: specified correct const data_types, fixed BFS search staring point to avoid nodeless shapeof subgraphs

* fixed mxnet_rnnt: added converting all Const nodes in ShapeOf subgraph in MarkAndChangeDataTypeInShapeOfSubgraphs.py, revised Const values in transformations that affect ShapeOf subgraph nodes

* reverter ReverseV2ToReverseSequence.py and DecomposeBidirectionalRNNSequence.py

* in MarkSubgraphsWithCorrectLayout BFS search beauty applied

* apply review comments, returned back 'in_shape_subgraph' attribute

* graph condition added

* MO IR reader fix for mixed FP16 models, added replacer order placement comment

* moved to back phase

* new solution with marking nodes from bottom to top (WIP)

* successfully tested on back phase

* corrected unittest

* removed check for start nodes size in bfs

* fix transformations that insert f64 to f32 in shape subgraph

* corrected log.warning -> log.debug

* revised list if shape input operations added unittest for Const shape inputs

* applied @lazarevevgeny's comments

* licence head corrections
2021-03-30 23:16:32 +03:00

79 lines
3.5 KiB
Python

# Copyright (C) 2018-2021 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
import logging as log
import numpy as np
from extensions.middle.MarkSubgraphsWithCorrectLayout import MarkSubGraphsWithCorrectLayout
from mo.back.replacement import BackReplacementPattern
from mo.graph.graph import Graph
class MarkNodesWithShapeValues(BackReplacementPattern):
"""
This transformation marks op nodes in ShapeOf subgraphs with 'returns_shape_value' bool attribute and
data nodes of float32 constants with 'correct_data_type' attribute.
So that float Consts and Cast float will be kept in FP32 even if argument --data_type=FP16 is specified.
This is needed to enable conversion to FP16 even if values in ShapeOf subgraphs exceed max(float16)
or because of FP16 lower precession shape inference is incorrect on some nodes (e.g. if Interpolate in scales mode
accepts values from ShapeOf subgraph).
This transformation should be executed after shape inference and after all transformations which insert/modify
Cast nodes in ShapeOf subgraphs therefore it's placed at the end of the back phase.
"""
enabled = True
graph_condition = [lambda graph: graph.graph['cmd_params'].data_type == 'FP16']
def run_after(self):
from extensions.back.pass_separator import BackFinish
return [BackFinish]
def run_before(self):
return []
@staticmethod
def get_operations_with_shape_inputs():
return {
'Interpolate': [1, 2], # sizes, scales inputs
'Reshape': [1], # shape
'Broadcast': [1], # target_shape
'ConvBackPropData ': [2], # output_shape
'GroupConvolutionBackpropData ': [2], # output_shape
'BatchToSpace': [1, 2, 3], # block_shape, crops_begin, crops_end
'SpaceToBatch': [1, 2, 3], # block_shape, pads_begin, pads_end
'StridedSlice': [1, 2, 3], # begin, end, strides
'VariadicSplit': [2], # split_lengths
'Tile': [1], # repeats input
'TopK': [1], # K input
'Pad': [1, 2], # pads_begin, pads_end
'Range': [0, 1, 2], # start, stop, step inputs
'OneHot': [1], # depth input
}
def find_and_replace_pattern(self, graph: Graph):
shape_input_ops_map = self.get_operations_with_shape_inputs()
nodes_with_shape_inputs = []
for node in graph.get_op_nodes():
if node.soft_get('type') in shape_input_ops_map:
nodes_with_shape_inputs.append(node)
start_nodes = []
for node in nodes_with_shape_inputs:
start_nodes.extend(
[node.in_port(port_idx).get_source().node for port_idx in shape_input_ops_map[node.type] if
node.is_in_port_connected(port_idx)])
condition = lambda node: node.soft_get('type') != 'ShapeOf'
nodes_with_shape_values = MarkSubGraphsWithCorrectLayout.bfs(start_nodes, set(), condition, forward=False)
for node in nodes_with_shape_values:
node['returns_shape_value'] = True
if node.soft_get('type') == 'Const':
if node.value.dtype == np.float32:
node.out_node(0)['correct_data_type'] = True
elif node.value.dtype in [np.float16, np.float64]:
log.debug('Const nodes {} with shape values have {} type'.format(node.soft_get('name', node.id),
node.value.dtype))