diff --git a/nncf/experimental/torch/fx/transformations.py b/nncf/experimental/torch/fx/transformations.py index 9003fa9c1dc..e2f3bb83f69 100644 --- a/nncf/experimental/torch/fx/transformations.py +++ b/nncf/experimental/torch/fx/transformations.py @@ -116,12 +116,13 @@ def leaf_module_insertion_transformation(model: torch.fx.GraphModule): return leaf_module_insertion_transformation -def bias_update_transformation_builder(node: NNCFNode, value: torch.Tensor) -> TransformationFNType: +def bias_update_transformation_builder(node: NNCFNode, value: torch.Tensor, input_port_id: int) -> TransformationFNType: """ Return transformation which updates constant of the given node with bias to the given value. :param node: Node with bias which requires bias constant update. :param value: New value to use as the bias constant. + :param input_port_id: Input port id to get constant node from. :return: Transformation which updates constant of the given node with bias to the given value. """ @@ -137,7 +138,7 @@ def bias_update_transformation(model: torch.fx.GraphModule): raise nncf.InternalError(f"Node {graph_node.name} has {len(add_nodes)} outputs with adds, 1 expected") bias_node = add_nodes[0] - constant_update_fn(model, bias_node, value, input_port_id=1) + constant_update_fn(model, bias_node, value, input_port_id=input_port_id) return bias_update_transformation @@ -228,7 +229,7 @@ def qdq_insertion_transformation_builder( def qdq_insertion_transformation(model: torch.fx.GraphModule): if any(tp.target_type != TargetType.OPERATION_WITH_WEIGHTS for tp in target_points) and len(target_points) > 1: - raise RuntimeError( + raise nncf.InternalError( "Insertion of shared qdq pair for the weights is not supported." " Please use non shared qdq pairs for the weights quantization." ) diff --git a/nncf/quantization/algorithms/bias_correction/torch_fx_backend.py b/nncf/quantization/algorithms/bias_correction/torch_fx_backend.py index d09bafc4bcf..1f62eef00b6 100644 --- a/nncf/quantization/algorithms/bias_correction/torch_fx_backend.py +++ b/nncf/quantization/algorithms/bias_correction/torch_fx_backend.py @@ -45,7 +45,7 @@ def target_point(target_type: TargetType, target_node_name: str, port_id: int) - def create_bias_correction_command( node: NNCFNode, bias_value: Tensor, nncf_graph: NNCFGraph ) -> FXApplyTransformationCommand: - return FXApplyTransformationCommand(bias_update_transformation_builder(node, bias_value.data)) + return FXApplyTransformationCommand(bias_update_transformation_builder(node, bias_value.data, input_port_id=1)) @staticmethod def model_extraction_command( diff --git a/nncf/quantization/algorithms/fast_bias_correction/torch_fx_backend.py b/nncf/quantization/algorithms/fast_bias_correction/torch_fx_backend.py index 876afbaf066..abbbf7ea21d 100644 --- a/nncf/quantization/algorithms/fast_bias_correction/torch_fx_backend.py +++ b/nncf/quantization/algorithms/fast_bias_correction/torch_fx_backend.py @@ -41,7 +41,7 @@ def target_point(target_type: TargetType, target_node_name: str, port_id: int) - def create_bias_correction_command( node: NNCFNode, bias_value: Tensor, nncf_graph: NNCFGraph ) -> FXApplyTransformationCommand: - return FXApplyTransformationCommand(bias_update_transformation_builder(node, bias_value.data)) + return FXApplyTransformationCommand(bias_update_transformation_builder(node, bias_value.data, input_port_id=1)) @staticmethod def model_extraction_command( diff --git a/nncf/quantization/algorithms/min_max/torch_fx_backend.py b/nncf/quantization/algorithms/min_max/torch_fx_backend.py index 5a170f5bef1..a181ad41a3e 100644 --- a/nncf/quantization/algorithms/min_max/torch_fx_backend.py +++ b/nncf/quantization/algorithms/min_max/torch_fx_backend.py @@ -12,6 +12,7 @@ from typing import Dict, List, Optional, Set, Tuple import torch +from torch.quantization.fake_quantize import FakeQuantize import nncf import nncf.torch.graph.operator_metatypes as om @@ -240,7 +241,7 @@ def _create_quantizer( scale_shape: Tuple, parameters: FakeQuantizeParameters, target_type: TargetType, - ) -> BaseQuantizer: + ) -> FakeQuantize: mode = quantizer_config.mode quantizer_cls = QUANTIZATION_MODULES.get(mode) narrow_range = target_type == TargetType.OPERATION_WITH_WEIGHTS and mode == QuantizationMode.SYMMETRIC diff --git a/nncf/quantization/algorithms/smooth_quant/torch_fx_backend.py b/nncf/quantization/algorithms/smooth_quant/torch_fx_backend.py index 19127771582..6dee64469ed 100644 --- a/nncf/quantization/algorithms/smooth_quant/torch_fx_backend.py +++ b/nncf/quantization/algorithms/smooth_quant/torch_fx_backend.py @@ -105,7 +105,10 @@ def get_weight_value(node_with_weight: NNCFNode, model: torch.fx.GraphModule, nn @staticmethod def weight_update_command(node_with_weight: NNCFNode, weight_value: torch.Tensor) -> OVWeightUpdateCommand: - return FXApplyTransformationCommand(constant_update_transformation_builder(node_with_weight, weight_value.data)) + # TODO(dlyakhov): Use input port id depending on the node metatype/attributes. + return FXApplyTransformationCommand( + constant_update_transformation_builder(node_with_weight, weight_value.data, input_port_id=1) + ) @staticmethod def scale_insertion_command( diff --git a/tests/post_training/pipelines/image_classification_torchvision.py b/tests/post_training/pipelines/image_classification_torchvision.py index bbf2040c685..36cdddd4439 100644 --- a/tests/post_training/pipelines/image_classification_torchvision.py +++ b/tests/post_training/pipelines/image_classification_torchvision.py @@ -92,7 +92,9 @@ def prepare_model(self) -> None: elif self.backend in [BackendType.OV, BackendType.FP32]: with torch.no_grad(): - self.model = ov.convert_model(model, example_input=self.dummy_tensor, input=self.input_size) + with disable_patching(): + m = torch.export.export(model, args=(self.dummy_tensor,)) + self.model = ov.convert_model(m, example_input=self.dummy_tensor, input=self.input_size) self.input_name = list(inp.get_any_name() for inp in self.model.inputs)[0] self._dump_model_fp32() diff --git a/tests/torch/data/reference_graphs/fx/extracted/ConvolutionWithAllConstantInputsModel.dot b/tests/torch/data/reference_graphs/fx/extracted/ConvolutionWithAllConstantInputsModel.dot deleted file mode 100644 index 0cfbbf5840b..00000000000 --- a/tests/torch/data/reference_graphs/fx/extracted/ConvolutionWithAllConstantInputsModel.dot +++ /dev/null @@ -1,11 +0,0 @@ -strict digraph { -"0 _conv_w" [id=0, type=get_attr]; -"1 add" [id=1, type=add]; -"2 placeholder_graph_node" [id=2, type=input]; -"3 conv2d" [id=3, type=conv2d]; -"4 output" [id=4, type=output]; -"0 _conv_w" -> "1 add"; -"1 add" -> "3 conv2d"; -"2 placeholder_graph_node" -> "3 conv2d"; -"3 conv2d" -> "4 output"; -} diff --git a/tests/torch/data/reference_graphs/fx/extracted/ConvolutionWithNotTensorBiasModel.dot b/tests/torch/data/reference_graphs/fx/extracted/ConvolutionWithNotTensorBiasModel.dot deleted file mode 100644 index 47edd99d8c9..00000000000 --- a/tests/torch/data/reference_graphs/fx/extracted/ConvolutionWithNotTensorBiasModel.dot +++ /dev/null @@ -1,11 +0,0 @@ -strict digraph { -"0 _conv_w" [id=0, type=get_attr]; -"1 add" [id=1, type=add]; -"2 arg0_1" [id=2, type=input]; -"3 conv2d" [id=3, type=conv2d]; -"4 output" [id=4, type=output]; -"0 _conv_w" -> "1 add"; -"1 add" -> "3 conv2d"; -"2 arg0_1" -> "3 conv2d"; -"3 conv2d" -> "4 output"; -} diff --git a/tests/torch/data/reference_graphs/fx/transformed/constant_update.dot b/tests/torch/data/reference_graphs/fx/transformed/constant_update.dot new file mode 100644 index 00000000000..36b9e1bfff9 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/constant_update.dot @@ -0,0 +1,38 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 conv2d" [id=3, type=conv2d]; +"4 _param_constant2" [id=4, type=get_attr]; +"5 _param_constant3" [id=5, type=get_attr]; +"6 conv2d_1" [id=6, type=conv2d]; +"7 add__updated_constant0" [id=7, type=get_attr]; +"8 add_" [id=8, type=add_]; +"9 _tensor_constant0_1" [id=9, type=get_attr]; +"10 add__1" [id=10, type=add_]; +"11 add" [id=11, type=add]; +"12 _param_constant4" [id=12, type=get_attr]; +"13 _param_constant5" [id=13, type=get_attr]; +"14 conv2d_2" [id=14, type=conv2d]; +"15 _tensor_constant0_2" [id=15, type=get_attr]; +"16 add_1" [id=16, type=add]; +"17 output" [id=17, type=output]; +"0 arg0_1" -> "3 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "3 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "3 conv2d" [label="(3,)", style=solid]; +"3 conv2d" -> "6 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"3 conv2d" -> "8 add_" [label="(1, 3, 3, 3)", style=solid]; +"4 _param_constant2" -> "6 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"5 _param_constant3" -> "6 conv2d_1" [label="(3,)", style=solid]; +"6 conv2d_1" -> "10 add__1" [label="(1, 3, 3, 3)", style=solid]; +"7 add__updated_constant0" -> "8 add_" [label="(1,)", style=solid]; +"8 add_" -> "11 add" [label="(1, 3, 3, 3)", style=solid]; +"9 _tensor_constant0_1" -> "10 add__1" [label="(1,)", style=solid]; +"10 add__1" -> "11 add" [label="(1, 3, 3, 3)", style=solid]; +"11 add" -> "14 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"12 _param_constant4" -> "14 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"13 _param_constant5" -> "14 conv2d_2" [label="(3,)", style=solid]; +"14 conv2d_2" -> "16 add_1" [label="(1, 3, 3, 3)", style=solid]; +"15 _tensor_constant0_2" -> "16 add_1" [label="(1,)", style=solid]; +"16 add_1" -> "17 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/model_insertion.dot b/tests/torch/data/reference_graphs/fx/transformed/model_insertion.dot new file mode 100644 index 00000000000..a03dce9b464 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/model_insertion.dot @@ -0,0 +1,46 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 TEST_MODULE_0" [id=3, type=call_module]; +"4 TEST_MODULE_1" [id=4, type=call_module]; +"5 conv2d" [id=5, type=conv2d]; +"6 TEST_MODULE_3" [id=6, type=call_module]; +"7 _param_constant2" [id=7, type=get_attr]; +"8 _param_constant3" [id=8, type=get_attr]; +"9 TEST_MODULE_2" [id=9, type=call_module]; +"10 conv2d_1" [id=10, type=conv2d]; +"11 _tensor_constant0" [id=11, type=get_attr]; +"12 add_" [id=12, type=add_]; +"13 _tensor_constant0_1" [id=13, type=get_attr]; +"14 add__1" [id=14, type=add_]; +"15 add" [id=15, type=add]; +"16 _param_constant4" [id=16, type=get_attr]; +"17 _param_constant5" [id=17, type=get_attr]; +"18 conv2d_2" [id=18, type=conv2d]; +"19 _tensor_constant0_2" [id=19, type=get_attr]; +"20 add_1" [id=20, type=add]; +"21 output" [id=21, type=output]; +"0 arg0_1" -> "3 TEST_MODULE_0" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "4 TEST_MODULE_1" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "5 conv2d" [label="(3,)", style=solid]; +"3 TEST_MODULE_0" -> "5 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"4 TEST_MODULE_1" -> "5 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"5 conv2d" -> "6 TEST_MODULE_3" [label="(1, 3, 3, 3)", style=solid]; +"6 TEST_MODULE_3" -> "10 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"6 TEST_MODULE_3" -> "12 add_" [label="(1, 3, 3, 3)", style=solid]; +"7 _param_constant2" -> "9 TEST_MODULE_2" [label="(3, 3, 1, 1)", style=solid]; +"8 _param_constant3" -> "10 conv2d_1" [label="(3,)", style=solid]; +"9 TEST_MODULE_2" -> "10 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"10 conv2d_1" -> "14 add__1" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0" -> "12 add_" [label="(1,)", style=solid]; +"12 add_" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"13 _tensor_constant0_1" -> "14 add__1" [label="(1,)", style=solid]; +"14 add__1" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"15 add" -> "18 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"16 _param_constant4" -> "18 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"17 _param_constant5" -> "18 conv2d_2" [label="(3,)", style=solid]; +"18 conv2d_2" -> "20 add_1" [label="(1, 3, 3, 3)", style=solid]; +"19 _tensor_constant0_2" -> "20 add_1" [label="(1,)", style=solid]; +"20 add_1" -> "21 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/model_insertion_leaf.dot b/tests/torch/data/reference_graphs/fx/transformed/model_insertion_leaf.dot new file mode 100644 index 00000000000..236ed5d745c --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/model_insertion_leaf.dot @@ -0,0 +1,46 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 TEST_MODULE_0" [id=3, type=call_module]; +"4 TEST_MODULE_1" [id=4, type=call_module]; +"5 conv2d" [id=5, type=conv2d]; +"6 TEST_MODULE_3" [id=6, type=call_module]; +"7 _param_constant2" [id=7, type=get_attr]; +"8 _param_constant3" [id=8, type=get_attr]; +"9 TEST_MODULE_2" [id=9, type=call_module]; +"10 conv2d_1" [id=10, type=conv2d]; +"11 _tensor_constant0" [id=11, type=get_attr]; +"12 add_" [id=12, type=add_]; +"13 _tensor_constant0_1" [id=13, type=get_attr]; +"14 add__1" [id=14, type=add_]; +"15 add" [id=15, type=add]; +"16 _param_constant4" [id=16, type=get_attr]; +"17 _param_constant5" [id=17, type=get_attr]; +"18 conv2d_2" [id=18, type=conv2d]; +"19 _tensor_constant0_2" [id=19, type=get_attr]; +"20 add_1" [id=20, type=add]; +"21 output" [id=21, type=output]; +"0 arg0_1" -> "3 TEST_MODULE_0" [label="(1, 3, 3, 3)", style=solid]; +"0 arg0_1" -> "5 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "4 TEST_MODULE_1" [label="(3, 3, 1, 1)", style=solid]; +"1 _param_constant0" -> "5 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "5 conv2d" [label="(3,)", style=solid]; +"5 conv2d" -> "6 TEST_MODULE_3" [label="(1, 3, 3, 3)", style=solid]; +"5 conv2d" -> "10 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"5 conv2d" -> "12 add_" [label="(1, 3, 3, 3)", style=solid]; +"7 _param_constant2" -> "9 TEST_MODULE_2" [label="(3, 3, 1, 1)", style=solid]; +"7 _param_constant2" -> "10 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"8 _param_constant3" -> "10 conv2d_1" [label="(3,)", style=solid]; +"10 conv2d_1" -> "14 add__1" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0" -> "12 add_" [label="(1,)", style=solid]; +"12 add_" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"13 _tensor_constant0_1" -> "14 add__1" [label="(1,)", style=solid]; +"14 add__1" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"15 add" -> "18 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"16 _param_constant4" -> "18 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"17 _param_constant5" -> "18 conv2d_2" [label="(3,)", style=solid]; +"18 conv2d_2" -> "20 add_1" [label="(1, 3, 3, 3)", style=solid]; +"19 _tensor_constant0_2" -> "20 add_1" [label="(1,)", style=solid]; +"20 add_1" -> "21 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/node_removal_ref.dot b/tests/torch/data/reference_graphs/fx/transformed/node_removal_ref.dot new file mode 100644 index 00000000000..ff4dfc03eb1 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/node_removal_ref.dot @@ -0,0 +1,32 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant2" [id=1, type=get_attr]; +"2 _param_constant3" [id=2, type=get_attr]; +"3 conv2d_1" [id=3, type=conv2d]; +"4 _tensor_constant0" [id=4, type=get_attr]; +"5 add_" [id=5, type=add_]; +"6 _tensor_constant0_1" [id=6, type=get_attr]; +"7 add__1" [id=7, type=add_]; +"8 add" [id=8, type=add]; +"9 _param_constant4" [id=9, type=get_attr]; +"10 _param_constant5" [id=10, type=get_attr]; +"11 conv2d_2" [id=11, type=conv2d]; +"12 _tensor_constant0_2" [id=12, type=get_attr]; +"13 add_1" [id=13, type=add]; +"14 output" [id=14, type=output]; +"0 arg0_1" -> "3 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"0 arg0_1" -> "5 add_" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant2" -> "3 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant3" -> "3 conv2d_1" [label="(3,)", style=solid]; +"3 conv2d_1" -> "7 add__1" [label="(1, 3, 3, 3)", style=solid]; +"4 _tensor_constant0" -> "5 add_" [label="(1,)", style=solid]; +"5 add_" -> "8 add" [label="(1, 3, 3, 3)", style=solid]; +"6 _tensor_constant0_1" -> "7 add__1" [label="(1,)", style=solid]; +"7 add__1" -> "8 add" [label="(1, 3, 3, 3)", style=solid]; +"8 add" -> "11 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"9 _param_constant4" -> "11 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"10 _param_constant5" -> "11 conv2d_2" [label="(3,)", style=solid]; +"11 conv2d_2" -> "13 add_1" [label="(1, 3, 3, 3)", style=solid]; +"12 _tensor_constant0_2" -> "13 add_1" [label="(1,)", style=solid]; +"13 add_1" -> "14 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_1_5_1_ref.dot b/tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_1_5_1.dot similarity index 100% rename from tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_1_5_1_ref.dot rename to tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_1_5_1.dot diff --git a/tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_6_0_ref.dot b/tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_6_0.dot similarity index 100% rename from tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_6_0_ref.dot rename to tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_6_0.dot diff --git a/tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_6_1_ref.dot b/tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_6_1.dot similarity index 100% rename from tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_6_1_ref.dot rename to tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_6_1.dot diff --git a/tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_7_None_ref.dot b/tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_7_None.dot similarity index 100% rename from tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_7_None_ref.dot rename to tests/torch/data/reference_graphs/fx/transformed/output_insertion_conv2d_7_None.dot diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_1_5_1_per_channel.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_1_5_1_per_channel.dot new file mode 100644 index 00000000000..b295abfc940 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_1_5_1_per_channel.dot @@ -0,0 +1,48 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 conv2d" [id=3, type=conv2d]; +"4 _param_constant2" [id=4, type=get_attr]; +"5 _param_constant3" [id=5, type=get_attr]; +"6 conv2d_1_scale_0" [id=6, type=get_attr]; +"7 conv2d_1_zero_point_0" [id=7, type=get_attr]; +"8 quantize_per_channel_default" [id=8, type=quantize_per_channel]; +"9 dequantize_per_channel_default" [id=9, type=dequantize_per_channel]; +"10 conv2d_1" [id=10, type=conv2d]; +"11 _tensor_constant0" [id=11, type=get_attr]; +"12 add_" [id=12, type=add_]; +"13 _tensor_constant0_1" [id=13, type=get_attr]; +"14 add__1" [id=14, type=add_]; +"15 add" [id=15, type=add]; +"16 _param_constant4" [id=16, type=get_attr]; +"17 _param_constant5" [id=17, type=get_attr]; +"18 conv2d_2" [id=18, type=conv2d]; +"19 _tensor_constant0_2" [id=19, type=get_attr]; +"20 add_1" [id=20, type=add]; +"21 output" [id=21, type=output]; +"0 arg0_1" -> "3 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "3 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "3 conv2d" [label="(3,)", style=solid]; +"3 conv2d" -> "10 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"3 conv2d" -> "12 add_" [label="(1, 3, 3, 3)", style=solid]; +"4 _param_constant2" -> "8 quantize_per_channel_default" [label="(3, 3, 1, 1)", style=solid]; +"5 _param_constant3" -> "10 conv2d_1" [label="(3,)", style=solid]; +"6 conv2d_1_scale_0" -> "8 quantize_per_channel_default" [label="(1,)", style=solid]; +"6 conv2d_1_scale_0" -> "9 dequantize_per_channel_default" [label="(1,)", style=solid]; +"7 conv2d_1_zero_point_0" -> "8 quantize_per_channel_default" [label="(1,)", style=solid]; +"7 conv2d_1_zero_point_0" -> "9 dequantize_per_channel_default" [label="(1,)", style=solid]; +"8 quantize_per_channel_default" -> "9 dequantize_per_channel_default" [label="(3, 3, 1, 1)", style=solid]; +"9 dequantize_per_channel_default" -> "10 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"10 conv2d_1" -> "14 add__1" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0" -> "12 add_" [label="(1,)", style=solid]; +"12 add_" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"13 _tensor_constant0_1" -> "14 add__1" [label="(1,)", style=solid]; +"14 add__1" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"15 add" -> "18 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"16 _param_constant4" -> "18 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"17 _param_constant5" -> "18 conv2d_2" [label="(3,)", style=solid]; +"18 conv2d_2" -> "20 add_1" [label="(1, 3, 3, 3)", style=solid]; +"19 _tensor_constant0_2" -> "20 add_1" [label="(1,)", style=solid]; +"20 add_1" -> "21 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_1_5_1_per_tensor.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_1_5_1_per_tensor.dot new file mode 100644 index 00000000000..895d90e44b8 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_1_5_1_per_tensor.dot @@ -0,0 +1,42 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 conv2d" [id=3, type=conv2d]; +"4 _param_constant2" [id=4, type=get_attr]; +"5 _param_constant3" [id=5, type=get_attr]; +"6 quantize_per_tensor_default" [id=6, type=quantize_per_tensor]; +"7 dequantize_per_tensor_default" [id=7, type=dequantize_per_tensor]; +"8 conv2d_1" [id=8, type=conv2d]; +"9 _tensor_constant0" [id=9, type=get_attr]; +"10 add_" [id=10, type=add_]; +"11 _tensor_constant0_1" [id=11, type=get_attr]; +"12 add__1" [id=12, type=add_]; +"13 add" [id=13, type=add]; +"14 _param_constant4" [id=14, type=get_attr]; +"15 _param_constant5" [id=15, type=get_attr]; +"16 conv2d_2" [id=16, type=conv2d]; +"17 _tensor_constant0_2" [id=17, type=get_attr]; +"18 add_1" [id=18, type=add]; +"19 output" [id=19, type=output]; +"0 arg0_1" -> "3 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "3 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "3 conv2d" [label="(3,)", style=solid]; +"3 conv2d" -> "8 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"3 conv2d" -> "10 add_" [label="(1, 3, 3, 3)", style=solid]; +"4 _param_constant2" -> "6 quantize_per_tensor_default" [label="(3, 3, 1, 1)", style=solid]; +"5 _param_constant3" -> "8 conv2d_1" [label="(3,)", style=solid]; +"6 quantize_per_tensor_default" -> "7 dequantize_per_tensor_default" [label="(3, 3, 1, 1)", style=solid]; +"7 dequantize_per_tensor_default" -> "8 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"8 conv2d_1" -> "12 add__1" [label="(1, 3, 3, 3)", style=solid]; +"9 _tensor_constant0" -> "10 add_" [label="(1,)", style=solid]; +"10 add_" -> "13 add" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0_1" -> "12 add__1" [label="(1,)", style=solid]; +"12 add__1" -> "13 add" [label="(1, 3, 3, 3)", style=solid]; +"13 add" -> "16 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"14 _param_constant4" -> "16 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"15 _param_constant5" -> "16 conv2d_2" [label="(3,)", style=solid]; +"16 conv2d_2" -> "18 add_1" [label="(1, 3, 3, 3)", style=solid]; +"17 _tensor_constant0_2" -> "18 add_1" [label="(1,)", style=solid]; +"18 add_1" -> "19 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_0_per_channel.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_0_per_channel.dot new file mode 100644 index 00000000000..91e9f02c918 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_0_per_channel.dot @@ -0,0 +1,48 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 conv2d_scale_0" [id=3, type=get_attr]; +"4 conv2d_zero_point_0" [id=4, type=get_attr]; +"5 quantize_per_channel_default" [id=5, type=quantize_per_channel]; +"6 dequantize_per_channel_default" [id=6, type=dequantize_per_channel]; +"7 conv2d" [id=7, type=conv2d]; +"8 _param_constant2" [id=8, type=get_attr]; +"9 _param_constant3" [id=9, type=get_attr]; +"10 conv2d_1" [id=10, type=conv2d]; +"11 _tensor_constant0" [id=11, type=get_attr]; +"12 add_" [id=12, type=add_]; +"13 _tensor_constant0_1" [id=13, type=get_attr]; +"14 add__1" [id=14, type=add_]; +"15 add" [id=15, type=add]; +"16 _param_constant4" [id=16, type=get_attr]; +"17 _param_constant5" [id=17, type=get_attr]; +"18 conv2d_2" [id=18, type=conv2d]; +"19 _tensor_constant0_2" [id=19, type=get_attr]; +"20 add_1" [id=20, type=add]; +"21 output" [id=21, type=output]; +"0 arg0_1" -> "5 quantize_per_channel_default" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "7 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "7 conv2d" [label="(3,)", style=solid]; +"3 conv2d_scale_0" -> "5 quantize_per_channel_default" [label="(1,)", style=solid]; +"3 conv2d_scale_0" -> "6 dequantize_per_channel_default" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "5 quantize_per_channel_default" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "6 dequantize_per_channel_default" [label="(1,)", style=solid]; +"5 quantize_per_channel_default" -> "6 dequantize_per_channel_default" [label="(1, 3, 3, 3)", style=solid]; +"6 dequantize_per_channel_default" -> "7 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"7 conv2d" -> "10 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"7 conv2d" -> "12 add_" [label="(1, 3, 3, 3)", style=solid]; +"8 _param_constant2" -> "10 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"9 _param_constant3" -> "10 conv2d_1" [label="(3,)", style=solid]; +"10 conv2d_1" -> "14 add__1" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0" -> "12 add_" [label="(1,)", style=solid]; +"12 add_" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"13 _tensor_constant0_1" -> "14 add__1" [label="(1,)", style=solid]; +"14 add__1" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"15 add" -> "18 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"16 _param_constant4" -> "18 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"17 _param_constant5" -> "18 conv2d_2" [label="(3,)", style=solid]; +"18 conv2d_2" -> "20 add_1" [label="(1, 3, 3, 3)", style=solid]; +"19 _tensor_constant0_2" -> "20 add_1" [label="(1,)", style=solid]; +"20 add_1" -> "21 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_0_per_tensor.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_0_per_tensor.dot new file mode 100644 index 00000000000..eec47cacece --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_0_per_tensor.dot @@ -0,0 +1,42 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 quantize_per_tensor_default" [id=3, type=quantize_per_tensor]; +"4 dequantize_per_tensor_default" [id=4, type=dequantize_per_tensor]; +"5 conv2d" [id=5, type=conv2d]; +"6 _param_constant2" [id=6, type=get_attr]; +"7 _param_constant3" [id=7, type=get_attr]; +"8 conv2d_1" [id=8, type=conv2d]; +"9 _tensor_constant0" [id=9, type=get_attr]; +"10 add_" [id=10, type=add_]; +"11 _tensor_constant0_1" [id=11, type=get_attr]; +"12 add__1" [id=12, type=add_]; +"13 add" [id=13, type=add]; +"14 _param_constant4" [id=14, type=get_attr]; +"15 _param_constant5" [id=15, type=get_attr]; +"16 conv2d_2" [id=16, type=conv2d]; +"17 _tensor_constant0_2" [id=17, type=get_attr]; +"18 add_1" [id=18, type=add]; +"19 output" [id=19, type=output]; +"0 arg0_1" -> "3 quantize_per_tensor_default" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "5 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "5 conv2d" [label="(3,)", style=solid]; +"3 quantize_per_tensor_default" -> "4 dequantize_per_tensor_default" [label="(1, 3, 3, 3)", style=solid]; +"4 dequantize_per_tensor_default" -> "5 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"5 conv2d" -> "8 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"5 conv2d" -> "10 add_" [label="(1, 3, 3, 3)", style=solid]; +"6 _param_constant2" -> "8 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"7 _param_constant3" -> "8 conv2d_1" [label="(3,)", style=solid]; +"8 conv2d_1" -> "12 add__1" [label="(1, 3, 3, 3)", style=solid]; +"9 _tensor_constant0" -> "10 add_" [label="(1,)", style=solid]; +"10 add_" -> "13 add" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0_1" -> "12 add__1" [label="(1,)", style=solid]; +"12 add__1" -> "13 add" [label="(1, 3, 3, 3)", style=solid]; +"13 add" -> "16 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"14 _param_constant4" -> "16 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"15 _param_constant5" -> "16 conv2d_2" [label="(3,)", style=solid]; +"16 conv2d_2" -> "18 add_1" [label="(1, 3, 3, 3)", style=solid]; +"17 _tensor_constant0_2" -> "18 add_1" [label="(1,)", style=solid]; +"18 add_1" -> "19 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_1_per_channel.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_1_per_channel.dot new file mode 100644 index 00000000000..b6138a0a70b --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_1_per_channel.dot @@ -0,0 +1,48 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 conv2d_scale_0" [id=3, type=get_attr]; +"4 conv2d_zero_point_0" [id=4, type=get_attr]; +"5 quantize_per_channel_default" [id=5, type=quantize_per_channel]; +"6 dequantize_per_channel_default" [id=6, type=dequantize_per_channel]; +"7 conv2d" [id=7, type=conv2d]; +"8 _param_constant2" [id=8, type=get_attr]; +"9 _param_constant3" [id=9, type=get_attr]; +"10 conv2d_1" [id=10, type=conv2d]; +"11 _tensor_constant0" [id=11, type=get_attr]; +"12 add_" [id=12, type=add_]; +"13 _tensor_constant0_1" [id=13, type=get_attr]; +"14 add__1" [id=14, type=add_]; +"15 add" [id=15, type=add]; +"16 _param_constant4" [id=16, type=get_attr]; +"17 _param_constant5" [id=17, type=get_attr]; +"18 conv2d_2" [id=18, type=conv2d]; +"19 _tensor_constant0_2" [id=19, type=get_attr]; +"20 add_1" [id=20, type=add]; +"21 output" [id=21, type=output]; +"0 arg0_1" -> "7 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "5 quantize_per_channel_default" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "7 conv2d" [label="(3,)", style=solid]; +"3 conv2d_scale_0" -> "5 quantize_per_channel_default" [label="(1,)", style=solid]; +"3 conv2d_scale_0" -> "6 dequantize_per_channel_default" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "5 quantize_per_channel_default" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "6 dequantize_per_channel_default" [label="(1,)", style=solid]; +"5 quantize_per_channel_default" -> "6 dequantize_per_channel_default" [label="(3, 3, 1, 1)", style=solid]; +"6 dequantize_per_channel_default" -> "7 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"7 conv2d" -> "10 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"7 conv2d" -> "12 add_" [label="(1, 3, 3, 3)", style=solid]; +"8 _param_constant2" -> "10 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"9 _param_constant3" -> "10 conv2d_1" [label="(3,)", style=solid]; +"10 conv2d_1" -> "14 add__1" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0" -> "12 add_" [label="(1,)", style=solid]; +"12 add_" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"13 _tensor_constant0_1" -> "14 add__1" [label="(1,)", style=solid]; +"14 add__1" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"15 add" -> "18 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"16 _param_constant4" -> "18 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"17 _param_constant5" -> "18 conv2d_2" [label="(3,)", style=solid]; +"18 conv2d_2" -> "20 add_1" [label="(1, 3, 3, 3)", style=solid]; +"19 _tensor_constant0_2" -> "20 add_1" [label="(1,)", style=solid]; +"20 add_1" -> "21 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_1_per_tensor.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_1_per_tensor.dot new file mode 100644 index 00000000000..62478def9d7 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_6_1_per_tensor.dot @@ -0,0 +1,42 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 quantize_per_tensor_default" [id=3, type=quantize_per_tensor]; +"4 dequantize_per_tensor_default" [id=4, type=dequantize_per_tensor]; +"5 conv2d" [id=5, type=conv2d]; +"6 _param_constant2" [id=6, type=get_attr]; +"7 _param_constant3" [id=7, type=get_attr]; +"8 conv2d_1" [id=8, type=conv2d]; +"9 _tensor_constant0" [id=9, type=get_attr]; +"10 add_" [id=10, type=add_]; +"11 _tensor_constant0_1" [id=11, type=get_attr]; +"12 add__1" [id=12, type=add_]; +"13 add" [id=13, type=add]; +"14 _param_constant4" [id=14, type=get_attr]; +"15 _param_constant5" [id=15, type=get_attr]; +"16 conv2d_2" [id=16, type=conv2d]; +"17 _tensor_constant0_2" [id=17, type=get_attr]; +"18 add_1" [id=18, type=add]; +"19 output" [id=19, type=output]; +"0 arg0_1" -> "5 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "3 quantize_per_tensor_default" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "5 conv2d" [label="(3,)", style=solid]; +"3 quantize_per_tensor_default" -> "4 dequantize_per_tensor_default" [label="(3, 3, 1, 1)", style=solid]; +"4 dequantize_per_tensor_default" -> "5 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"5 conv2d" -> "8 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"5 conv2d" -> "10 add_" [label="(1, 3, 3, 3)", style=solid]; +"6 _param_constant2" -> "8 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"7 _param_constant3" -> "8 conv2d_1" [label="(3,)", style=solid]; +"8 conv2d_1" -> "12 add__1" [label="(1, 3, 3, 3)", style=solid]; +"9 _tensor_constant0" -> "10 add_" [label="(1,)", style=solid]; +"10 add_" -> "13 add" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0_1" -> "12 add__1" [label="(1,)", style=solid]; +"12 add__1" -> "13 add" [label="(1, 3, 3, 3)", style=solid]; +"13 add" -> "16 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"14 _param_constant4" -> "16 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"15 _param_constant5" -> "16 conv2d_2" [label="(3,)", style=solid]; +"16 conv2d_2" -> "18 add_1" [label="(1, 3, 3, 3)", style=solid]; +"17 _tensor_constant0_2" -> "18 add_1" [label="(1,)", style=solid]; +"18 add_1" -> "19 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_7_None_per_channel.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_7_None_per_channel.dot new file mode 100644 index 00000000000..af758b9085b --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_7_None_per_channel.dot @@ -0,0 +1,52 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 conv2d_scale_0" [id=3, type=get_attr]; +"4 conv2d_zero_point_0" [id=4, type=get_attr]; +"5 conv2d" [id=5, type=conv2d]; +"6 quantize_per_channel_default" [id=6, type=quantize_per_channel]; +"7 dequantize_per_channel_default_1" [id=7, type=dequantize_per_channel]; +"8 dequantize_per_channel_default" [id=8, type=dequantize_per_channel]; +"9 _param_constant2" [id=9, type=get_attr]; +"10 _param_constant3" [id=10, type=get_attr]; +"11 conv2d_1" [id=11, type=conv2d]; +"12 _tensor_constant0" [id=12, type=get_attr]; +"13 add_" [id=13, type=add_]; +"14 _tensor_constant0_1" [id=14, type=get_attr]; +"15 add__1" [id=15, type=add_]; +"16 add" [id=16, type=add]; +"17 _param_constant4" [id=17, type=get_attr]; +"18 _param_constant5" [id=18, type=get_attr]; +"19 conv2d_2" [id=19, type=conv2d]; +"20 _tensor_constant0_2" [id=20, type=get_attr]; +"21 add_1" [id=21, type=add]; +"22 output" [id=22, type=output]; +"0 arg0_1" -> "5 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "5 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "5 conv2d" [label="(3,)", style=solid]; +"3 conv2d_scale_0" -> "6 quantize_per_channel_default" [label="(1,)", style=solid]; +"3 conv2d_scale_0" -> "7 dequantize_per_channel_default_1" [label="(1,)", style=solid]; +"3 conv2d_scale_0" -> "8 dequantize_per_channel_default" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "6 quantize_per_channel_default" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "7 dequantize_per_channel_default_1" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "8 dequantize_per_channel_default" [label="(1,)", style=solid]; +"5 conv2d" -> "6 quantize_per_channel_default" [label="(1, 3, 3, 3)", style=solid]; +"6 quantize_per_channel_default" -> "7 dequantize_per_channel_default_1" [label="(1, 3, 3, 3)", style=solid]; +"6 quantize_per_channel_default" -> "8 dequantize_per_channel_default" [label="(1, 3, 3, 3)", style=solid]; +"7 dequantize_per_channel_default_1" -> "13 add_" [label="(1, 3, 3, 3)", style=solid]; +"8 dequantize_per_channel_default" -> "11 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"9 _param_constant2" -> "11 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"10 _param_constant3" -> "11 conv2d_1" [label="(3,)", style=solid]; +"11 conv2d_1" -> "15 add__1" [label="(1, 3, 3, 3)", style=solid]; +"12 _tensor_constant0" -> "13 add_" [label="(1,)", style=solid]; +"13 add_" -> "16 add" [label="(1, 3, 3, 3)", style=solid]; +"14 _tensor_constant0_1" -> "15 add__1" [label="(1,)", style=solid]; +"15 add__1" -> "16 add" [label="(1, 3, 3, 3)", style=solid]; +"16 add" -> "19 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"17 _param_constant4" -> "19 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"18 _param_constant5" -> "19 conv2d_2" [label="(3,)", style=solid]; +"19 conv2d_2" -> "21 add_1" [label="(1, 3, 3, 3)", style=solid]; +"20 _tensor_constant0_2" -> "21 add_1" [label="(1,)", style=solid]; +"21 add_1" -> "22 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_7_None_per_tensor.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_7_None_per_tensor.dot new file mode 100644 index 00000000000..7d4f98cd99b --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_insert_conv2d_7_None_per_tensor.dot @@ -0,0 +1,44 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 conv2d" [id=3, type=conv2d]; +"4 quantize_per_tensor_default" [id=4, type=quantize_per_tensor]; +"5 dequantize_per_tensor_default_1" [id=5, type=dequantize_per_tensor]; +"6 dequantize_per_tensor_default" [id=6, type=dequantize_per_tensor]; +"7 _param_constant2" [id=7, type=get_attr]; +"8 _param_constant3" [id=8, type=get_attr]; +"9 conv2d_1" [id=9, type=conv2d]; +"10 _tensor_constant0" [id=10, type=get_attr]; +"11 add_" [id=11, type=add_]; +"12 _tensor_constant0_1" [id=12, type=get_attr]; +"13 add__1" [id=13, type=add_]; +"14 add" [id=14, type=add]; +"15 _param_constant4" [id=15, type=get_attr]; +"16 _param_constant5" [id=16, type=get_attr]; +"17 conv2d_2" [id=17, type=conv2d]; +"18 _tensor_constant0_2" [id=18, type=get_attr]; +"19 add_1" [id=19, type=add]; +"20 output" [id=20, type=output]; +"0 arg0_1" -> "3 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "3 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "3 conv2d" [label="(3,)", style=solid]; +"3 conv2d" -> "4 quantize_per_tensor_default" [label="(1, 3, 3, 3)", style=solid]; +"4 quantize_per_tensor_default" -> "5 dequantize_per_tensor_default_1" [label="(1, 3, 3, 3)", style=solid]; +"4 quantize_per_tensor_default" -> "6 dequantize_per_tensor_default" [label="(1, 3, 3, 3)", style=solid]; +"5 dequantize_per_tensor_default_1" -> "11 add_" [label="(1, 3, 3, 3)", style=solid]; +"6 dequantize_per_tensor_default" -> "9 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"7 _param_constant2" -> "9 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"8 _param_constant3" -> "9 conv2d_1" [label="(3,)", style=solid]; +"9 conv2d_1" -> "13 add__1" [label="(1, 3, 3, 3)", style=solid]; +"10 _tensor_constant0" -> "11 add_" [label="(1,)", style=solid]; +"11 add_" -> "14 add" [label="(1, 3, 3, 3)", style=solid]; +"12 _tensor_constant0_1" -> "13 add__1" [label="(1,)", style=solid]; +"13 add__1" -> "14 add" [label="(1, 3, 3, 3)", style=solid]; +"14 add" -> "17 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"15 _param_constant4" -> "17 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"16 _param_constant5" -> "17 conv2d_2" [label="(3,)", style=solid]; +"17 conv2d_2" -> "19 add_1" [label="(1, 3, 3, 3)", style=solid]; +"18 _tensor_constant0_2" -> "19 add_1" [label="(1,)", style=solid]; +"19 add_1" -> "20 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_shared_insert_weights_per_channel.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_shared_insert_weights_per_channel.dot new file mode 100644 index 00000000000..b2333db9ef0 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_shared_insert_weights_per_channel.dot @@ -0,0 +1,58 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 conv2d_scale_0" [id=3, type=get_attr]; +"4 conv2d_zero_point_0" [id=4, type=get_attr]; +"5 quantize_per_channel_default" [id=5, type=quantize_per_channel]; +"6 dequantize_per_channel_default" [id=6, type=dequantize_per_channel]; +"7 conv2d" [id=7, type=conv2d]; +"8 _param_constant2" [id=8, type=get_attr]; +"9 _param_constant3" [id=9, type=get_attr]; +"10 conv2d_1_scale_0" [id=10, type=get_attr]; +"11 conv2d_1_zero_point_0" [id=11, type=get_attr]; +"12 quantize_per_channel_default_1" [id=12, type=quantize_per_channel]; +"13 dequantize_per_channel_default_1" [id=13, type=dequantize_per_channel]; +"14 conv2d_1" [id=14, type=conv2d]; +"15 _tensor_constant0" [id=15, type=get_attr]; +"16 add_" [id=16, type=add_]; +"17 _tensor_constant0_1" [id=17, type=get_attr]; +"18 add__1" [id=18, type=add_]; +"19 add" [id=19, type=add]; +"20 _param_constant4" [id=20, type=get_attr]; +"21 _param_constant5" [id=21, type=get_attr]; +"22 conv2d_2" [id=22, type=conv2d]; +"23 _tensor_constant0_2" [id=23, type=get_attr]; +"24 add_1" [id=24, type=add]; +"25 output" [id=25, type=output]; +"0 arg0_1" -> "7 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "5 quantize_per_channel_default" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "7 conv2d" [label="(3,)", style=solid]; +"3 conv2d_scale_0" -> "5 quantize_per_channel_default" [label="(1,)", style=solid]; +"3 conv2d_scale_0" -> "6 dequantize_per_channel_default" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "5 quantize_per_channel_default" [label="(1,)", style=solid]; +"4 conv2d_zero_point_0" -> "6 dequantize_per_channel_default" [label="(1,)", style=solid]; +"5 quantize_per_channel_default" -> "6 dequantize_per_channel_default" [label="(3, 3, 1, 1)", style=solid]; +"6 dequantize_per_channel_default" -> "7 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"7 conv2d" -> "14 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"7 conv2d" -> "16 add_" [label="(1, 3, 3, 3)", style=solid]; +"8 _param_constant2" -> "12 quantize_per_channel_default_1" [label="(3, 3, 1, 1)", style=solid]; +"9 _param_constant3" -> "14 conv2d_1" [label="(3,)", style=solid]; +"10 conv2d_1_scale_0" -> "12 quantize_per_channel_default_1" [label="(1,)", style=solid]; +"10 conv2d_1_scale_0" -> "13 dequantize_per_channel_default_1" [label="(1,)", style=solid]; +"11 conv2d_1_zero_point_0" -> "12 quantize_per_channel_default_1" [label="(1,)", style=solid]; +"11 conv2d_1_zero_point_0" -> "13 dequantize_per_channel_default_1" [label="(1,)", style=solid]; +"12 quantize_per_channel_default_1" -> "13 dequantize_per_channel_default_1" [label="(3, 3, 1, 1)", style=solid]; +"13 dequantize_per_channel_default_1" -> "14 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"14 conv2d_1" -> "18 add__1" [label="(1, 3, 3, 3)", style=solid]; +"15 _tensor_constant0" -> "16 add_" [label="(1,)", style=solid]; +"16 add_" -> "19 add" [label="(1, 3, 3, 3)", style=solid]; +"17 _tensor_constant0_1" -> "18 add__1" [label="(1,)", style=solid]; +"18 add__1" -> "19 add" [label="(1, 3, 3, 3)", style=solid]; +"19 add" -> "22 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"20 _param_constant4" -> "22 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"21 _param_constant5" -> "22 conv2d_2" [label="(3,)", style=solid]; +"22 conv2d_2" -> "24 add_1" [label="(1, 3, 3, 3)", style=solid]; +"23 _tensor_constant0_2" -> "24 add_1" [label="(1,)", style=solid]; +"24 add_1" -> "25 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/data/reference_graphs/fx/transformed/qdq_shared_insert_weights_per_tensor.dot b/tests/torch/data/reference_graphs/fx/transformed/qdq_shared_insert_weights_per_tensor.dot new file mode 100644 index 00000000000..6c8925fe8d2 --- /dev/null +++ b/tests/torch/data/reference_graphs/fx/transformed/qdq_shared_insert_weights_per_tensor.dot @@ -0,0 +1,46 @@ +strict digraph { +"0 arg0_1" [id=0, type=input]; +"1 _param_constant0" [id=1, type=get_attr]; +"2 _param_constant1" [id=2, type=get_attr]; +"3 quantize_per_tensor_default" [id=3, type=quantize_per_tensor]; +"4 dequantize_per_tensor_default" [id=4, type=dequantize_per_tensor]; +"5 conv2d" [id=5, type=conv2d]; +"6 _param_constant2" [id=6, type=get_attr]; +"7 _param_constant3" [id=7, type=get_attr]; +"8 quantize_per_tensor_default_1" [id=8, type=quantize_per_tensor]; +"9 dequantize_per_tensor_default_1" [id=9, type=dequantize_per_tensor]; +"10 conv2d_1" [id=10, type=conv2d]; +"11 _tensor_constant0" [id=11, type=get_attr]; +"12 add_" [id=12, type=add_]; +"13 _tensor_constant0_1" [id=13, type=get_attr]; +"14 add__1" [id=14, type=add_]; +"15 add" [id=15, type=add]; +"16 _param_constant4" [id=16, type=get_attr]; +"17 _param_constant5" [id=17, type=get_attr]; +"18 conv2d_2" [id=18, type=conv2d]; +"19 _tensor_constant0_2" [id=19, type=get_attr]; +"20 add_1" [id=20, type=add]; +"21 output" [id=21, type=output]; +"0 arg0_1" -> "5 conv2d" [label="(1, 3, 3, 3)", style=solid]; +"1 _param_constant0" -> "3 quantize_per_tensor_default" [label="(3, 3, 1, 1)", style=solid]; +"2 _param_constant1" -> "5 conv2d" [label="(3,)", style=solid]; +"3 quantize_per_tensor_default" -> "4 dequantize_per_tensor_default" [label="(3, 3, 1, 1)", style=solid]; +"4 dequantize_per_tensor_default" -> "5 conv2d" [label="(3, 3, 1, 1)", style=solid]; +"5 conv2d" -> "10 conv2d_1" [label="(1, 3, 3, 3)", style=solid]; +"5 conv2d" -> "12 add_" [label="(1, 3, 3, 3)", style=solid]; +"6 _param_constant2" -> "8 quantize_per_tensor_default_1" [label="(3, 3, 1, 1)", style=solid]; +"7 _param_constant3" -> "10 conv2d_1" [label="(3,)", style=solid]; +"8 quantize_per_tensor_default_1" -> "9 dequantize_per_tensor_default_1" [label="(3, 3, 1, 1)", style=solid]; +"9 dequantize_per_tensor_default_1" -> "10 conv2d_1" [label="(3, 3, 1, 1)", style=solid]; +"10 conv2d_1" -> "14 add__1" [label="(1, 3, 3, 3)", style=solid]; +"11 _tensor_constant0" -> "12 add_" [label="(1,)", style=solid]; +"12 add_" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"13 _tensor_constant0_1" -> "14 add__1" [label="(1,)", style=solid]; +"14 add__1" -> "15 add" [label="(1, 3, 3, 3)", style=solid]; +"15 add" -> "18 conv2d_2" [label="(1, 3, 3, 3)", style=solid]; +"16 _param_constant4" -> "18 conv2d_2" [label="(3, 3, 1, 1)", style=solid]; +"17 _param_constant5" -> "18 conv2d_2" [label="(3,)", style=solid]; +"18 conv2d_2" -> "20 add_1" [label="(1, 3, 3, 3)", style=solid]; +"19 _tensor_constant0_2" -> "20 add_1" [label="(1,)", style=solid]; +"20 add_1" -> "21 output" [label="(1, 3, 3, 3)", style=solid]; +} diff --git a/tests/torch/fx/test_model_transformer.py b/tests/torch/fx/test_model_transformer.py index 93e89dee8fc..dcbac2e2bae 100644 --- a/tests/torch/fx/test_model_transformer.py +++ b/tests/torch/fx/test_model_transformer.py @@ -14,19 +14,29 @@ from typing import Any, Tuple import pytest -import torch +import torch.fx from torch._export import capture_pre_autograd_graph +from torch.ao.quantization.observer import MinMaxObserver +from torch.ao.quantization.observer import PerChannelMinMaxObserver +from torch.quantization.fake_quantize import FakeQuantize +import nncf from nncf.common.factory import NNCFGraph from nncf.common.factory import NNCFGraphFactory from nncf.common.graph.transformations.commands import TargetType from nncf.common.graph.transformations.layout import TransformationLayout +from nncf.common.quantization.structs import QuantizationScheme as QuantizationMode from nncf.experimental.torch.fx.model_transformer import FXModelTransformer from nncf.experimental.torch.fx.nncf_graph_builder import GraphConverter from nncf.experimental.torch.fx.node_utils import get_graph_node_by_name from nncf.experimental.torch.fx.node_utils import get_tensor_constant_from_node +from nncf.experimental.torch.fx.transformations import bias_update_transformation_builder from nncf.experimental.torch.fx.transformations import constant_update_transformation_builder +from nncf.experimental.torch.fx.transformations import leaf_module_insertion_transformation_builder +from nncf.experimental.torch.fx.transformations import module_insertion_transformation_builder +from nncf.experimental.torch.fx.transformations import node_removal_transformation_builder from nncf.experimental.torch.fx.transformations import output_insertion_transformation_builder +from nncf.experimental.torch.fx.transformations import qdq_insertion_transformation_builder from nncf.experimental.torch.fx.transformations import shared_constants_unification_transformation from nncf.torch import disable_patching from nncf.torch.graph.operator_metatypes import CONST_NOOP_METATYPES @@ -45,8 +55,8 @@ class ModelExtractionTestCase: command: PTModelExtractionCommand -EXTRACTED_GRAPHS_DIR_NAME = Path("fx") / "extracted" -TRANSFORMED_GRAPH_DIR_NAME = Path("fx") / "transformed" +EXTRACTED_GRAPHS_DIR_NAME = str(Path("fx") / "extracted") +TRANSFORMED_GRAPH_DIR_NAME = str(Path("fx") / "transformed") MODEL_EXTRACTION_CASES = ( ModelExtractionTestCase( @@ -98,11 +108,12 @@ def _capture_model(model: torch.nn.Module, inputs: torch.Tensor) -> torch.fx.Gra @pytest.mark.parametrize("test_case", MODEL_EXTRACTION_CASES, ids=idfn) def test_model_extraction(test_case: ModelExtractionTestCase): captured_model = _capture_model(test_case.model(), torch.ones(test_case.input_shape)) + layout = TransformationLayout() layout.register(test_case.command) extracted_model = FXModelTransformer(captured_model).transform(layout) nncf_graph = GraphConverter.create_nncf_graph(extracted_model) - check_graph(nncf_graph, f"{get_test_id(test_case)}.dot", str(EXTRACTED_GRAPHS_DIR_NAME), extended=True) + check_graph(nncf_graph, f"{get_test_id(test_case)}.dot", EXTRACTED_GRAPHS_DIR_NAME, extended=True) MultiBranchesConnectedModel_TARGET_POINTS = ( @@ -113,9 +124,225 @@ def test_model_extraction(test_case: ModelExtractionTestCase): ) +@pytest.mark.parametrize("leaf", [False, True], ids=["no_leaf", "leaf"]) +def test_model_insertion_transformation(leaf: bool): + class TestInsertModule(torch.nn.Module): + def forward(self, x): + return x + 1 + + target_points = list(MultiBranchesConnectedModel_TARGET_POINTS) + target_node_name = "TEST_MODULE" + test_module_instance = TestInsertModule() + builder = leaf_module_insertion_transformation_builder if leaf else module_insertion_transformation_builder + transformation = builder(test_module_instance, target_points, target_node_name) + + model = MultiBranchesConnectedModel() + captured_model = _capture_model(model, torch.ones((1, 3, 3, 3))) + transformation(captured_model) + + nncf_graph = GraphConverter.create_nncf_graph(captured_model) + assert getattr(captured_model, target_node_name) is test_module_instance + check_graph(nncf_graph, f"model_insertion{'_leaf' if leaf else ''}.dot", TRANSFORMED_GRAPH_DIR_NAME, extended=True) + + +@pytest.mark.parametrize("bias", [True, False], ids=["bias", "constant"]) +def test_constant_update_transformation(bias: bool): + model = MultiBranchesConnectedModel() + captured_model = _capture_model(model, torch.ones((1, 3, 3, 3))) + nncf_graph = GraphConverter.create_nncf_graph(captured_model) + target_node = nncf_graph.get_node_by_name("conv2d" if bias else "add_") + + builder = bias_update_transformation_builder if bias else constant_update_transformation_builder + new_value = torch.tensor((42.0,)) + transformation = builder(target_node, value=new_value, input_port_id=1) + transformation(captured_model) + + add_node = get_graph_node_by_name(captured_model.graph, "add_") + assert get_tensor_constant_from_node(add_node.args[1], captured_model) == new_value + + transformed_nncf_graph = GraphConverter.create_nncf_graph(captured_model) + check_graph(transformed_nncf_graph, "constant_update.dot", TRANSFORMED_GRAPH_DIR_NAME, extended=True) + + +@pytest.mark.parametrize("bias", [True, False], ids=["bias", "constant"]) +def test_constant_update_transformation_no_constant(bias: bool): + model = MultiBranchesConnectedModel() + captured_model = _capture_model(model, torch.ones((1, 3, 3, 3))) + nncf_graph = GraphConverter.create_nncf_graph(captured_model) + target_node = nncf_graph.get_node_by_name("add") + + builder = bias_update_transformation_builder if bias else constant_update_transformation_builder + new_value = torch.tensor((42.0,)) + transformation = builder(target_node, value=new_value, input_port_id=1) + with pytest.raises(nncf.InternalError): + transformation(captured_model) + + +@pytest.mark.parametrize( + "q_min,q_max,dtype", + [(-128, 127, torch.qint8), (0, 255, torch.quint8)], + ids=["int8", "uint8"], +) +class TestQDQInsertion: + REF_SCALE = torch.tensor([1.0]) + REF_ZERO_POINT = torch.tensor([0.0]) + + def _get_quantizer( + self, per_channel: bool, symmetric: bool, q_min: torch.Tensor, q_max: torch.Tensor, dtype: torch.dtype + ) -> FakeQuantize: + if symmetric: + qscheme = torch.per_channel_symmetric if per_channel else torch.per_tensor_symmetric + else: + qscheme = torch.per_channel_affine if per_channel else torch.per_tensor_affine + observer = PerChannelMinMaxObserver if per_channel else MinMaxObserver + + quantizer = FakeQuantize( + observer=observer, + quant_min=q_min, + quant_max=q_max, + dtype=dtype, + qscheme=qscheme, + eps=1e-5, + ) + quantizer.scale = self.REF_SCALE + quantizer.zero_point = self.REF_ZERO_POINT + + return quantizer + + def _check_qdq_params( + self, captured_model: torch.fx.GraphModule, target_point: PTTargetPoint, dtype: torch.dtype, per_channel: bool + ): + target_node = get_graph_node_by_name(captured_model.graph, target_point.target_node_name) + if target_point.target_type in [TargetType.OPERATION_WITH_WEIGHTS, TargetType.OPERATOR_PRE_HOOK]: + dq_node = target_node.args[target_point.input_port_id] + q_node = dq_node.args[0] + else: + q_node = list(target_node.users)[0] + + ref_dtype = torch.int8 if dtype == torch.qint8 else torch.uint8 + if per_channel: + + def get_value(node: torch.fx.Node): + return get_tensor_constant_from_node(node, captured_model) + + else: + + def get_value(node: torch.fx.Node): + return node + + assert q_node.args[-1] == ref_dtype + assert get_value(q_node.args[1]) == self.REF_SCALE + assert get_value(q_node.args[2]) == self.REF_ZERO_POINT + for dq_node in q_node.users: + assert get_value(dq_node.args[1]) == self.REF_SCALE + assert get_value(dq_node.args[2]) == self.REF_ZERO_POINT + assert dq_node.args[-1] == ref_dtype + + @pytest.mark.parametrize("target_point", MultiBranchesConnectedModel_TARGET_POINTS) + def test_one_target_point( + self, + is_per_channel: bool, + quantization_mode: QuantizationMode, + q_min: int, + q_max: int, + dtype: torch.dtype, + target_point: PTTargetPoint, + ): + symmetric = quantization_mode == QuantizationMode.SYMMETRIC + quantizer = self._get_quantizer(is_per_channel, symmetric, q_min, q_max, dtype) + transformation = qdq_insertion_transformation_builder(quantizer, [target_point]) + + model = MultiBranchesConnectedModel() + captured_model = _capture_model(model, torch.ones((1, 3, 3, 3))) + transformation(captured_model) + + self._check_qdq_params(captured_model, target_point, dtype, is_per_channel) + + nncf_graph = GraphConverter.create_nncf_graph(captured_model) + ref_name = ( + f"qdq_insert_{_target_point_to_str(target_point)}" + f"_{'per_channel' if is_per_channel else 'per_tensor'}.dot" + ) + check_graph( + nncf_graph, + ref_name, + TRANSFORMED_GRAPH_DIR_NAME, + extended=True, + ) + + @pytest.mark.parametrize( + "target_points,weights", + [ + ( + [ + PTTargetPoint(TargetType.OPERATOR_PRE_HOOK, "conv2d", input_port_id=0), + PTTargetPoint(TargetType.OPERATOR_PRE_HOOK, "conv2d", input_port_id=1), + PTTargetPoint(TargetType.OPERATOR_POST_HOOK, "conv2d"), + ], + False, + ), + ( + [ + PTTargetPoint(TargetType.OPERATION_WITH_WEIGHTS, "conv2d", input_port_id=1), + PTTargetPoint(TargetType.OPERATION_WITH_WEIGHTS, "conv2d_1", input_port_id=1), + ], + True, + ), + ], + ) + def test_shared_target_point( + self, + is_per_channel: bool, + quantization_mode: QuantizationMode, + q_min: int, + q_max: int, + dtype: torch.dtype, + target_points: PTTargetPoint, + weights: bool, + ): + symmetric = quantization_mode == QuantizationMode.SYMMETRIC + quantizer = self._get_quantizer(is_per_channel, symmetric, q_min, q_max, dtype) + transformation = qdq_insertion_transformation_builder(quantizer, target_points) + + model = MultiBranchesConnectedModel() + captured_model = _capture_model(model, torch.ones((1, 3, 3, 3))) + if not weights: + with pytest.raises(nncf.InternalError): + transformation(captured_model) + return + + transformation(captured_model) + + for target_point in target_points: + self._check_qdq_params(captured_model, target_point, dtype, is_per_channel) + + nncf_graph = GraphConverter.create_nncf_graph(captured_model) + ref_name = ( + f"qdq_shared_insert_{'weights' if weights else 'activations'}" + f"_{'per_channel' if is_per_channel else 'per_tensor'}.dot" + ) + check_graph( + nncf_graph, + ref_name, + TRANSFORMED_GRAPH_DIR_NAME, + extended=True, + ) + + +def test_node_removal_transformation(): + model = MultiBranchesConnectedModel() + captured_model = _capture_model(model, torch.ones((1, 3, 3, 3))) + nncf_graph = GraphConverter.create_nncf_graph(captured_model) + node = nncf_graph.get_node_by_name("conv2d") + transformation = node_removal_transformation_builder(node, input_port_id=0) + transformation(captured_model) + transformed_nncf_graph = GraphConverter.create_nncf_graph(captured_model) + check_graph(transformed_nncf_graph, "node_removal_ref.dot", TRANSFORMED_GRAPH_DIR_NAME, extended=True) + + @pytest.mark.parametrize("tuple_output", [False, True], ids=["node_out", "tuple_out"]) @pytest.mark.parametrize("target_point", MultiBranchesConnectedModel_TARGET_POINTS) -def test_output_insertion_transformation(tuple_output, target_point): +def test_output_insertion_transformation(tuple_output: bool, target_point: PTTargetPoint): model = MultiBranchesConnectedModel() captured_model = _capture_model(model, torch.ones((1, 3, 3, 3))) @@ -128,15 +355,16 @@ def test_output_insertion_transformation(tuple_output, target_point): transformation(captured_model) nncf_graph = GraphConverter.create_nncf_graph(captured_model) + ref_name = f"output_insertion_{_target_point_to_str(target_point)}.dot" check_graph( nncf_graph, - f"output_insertion_{_target_point_to_str(target_point)}_ref.dot", + ref_name, TRANSFORMED_GRAPH_DIR_NAME, extended=True, ) -def count_constants(model) -> int: +def count_constants(model: torch.fx.GraphModule) -> int: num_constant_nodes = 0 for node in model.graph.nodes: if node.op == "get_attr":