|
25 | 25 | EthosUQuantizer,
|
26 | 26 | get_symmetric_quantization_config,
|
27 | 27 | TOSAQuantizer,
|
| 28 | + VgfQuantizer, |
28 | 29 | )
|
29 | 30 | from executorch.backends.arm.test import common, conftest
|
30 | 31 | from executorch.backends.arm.test.tester.arm_tester import ArmTester, RunPasses
|
@@ -827,3 +828,123 @@ def __init__(
|
827 | 828 | },
|
828 | 829 | )
|
829 | 830 | self.pop_stage("to_executorch")
|
| 831 | + |
| 832 | + |
| 833 | +class VgfPipeline(BasePipelineMaker, Generic[T]): |
| 834 | + """ |
| 835 | + Lowers a graph based on TOSA spec (with or without quantization) and converts TOSA to VFG. |
| 836 | +
|
| 837 | + Attributes: |
| 838 | + module: The module which the pipeline is applied to. |
| 839 | + test_data: Data used for quantizing and testing the module. |
| 840 | +
|
| 841 | + aten_ops: Aten dialect ops expected to be found in the graph after export. |
| 842 | + exir_ops: Exir dialect ops expected to be found in the graph after to_edge. |
| 843 | + if not using use_edge_to_transform_and_lower. |
| 844 | +
|
| 845 | + run_on_vulkan_runtime: Not yet supported. |
| 846 | +
|
| 847 | + vgf_compiler_flags: Optional compiler flags. |
| 848 | +
|
| 849 | + tosa_version: A string for identifying the TOSA version. |
| 850 | +
|
| 851 | + use_edge_to_transform_and_lower: Selects betweeen two possible ways of lowering the module. |
| 852 | + custom_path : Path to dump intermediate artifacts such as tosa and pte to. |
| 853 | + """ |
| 854 | + |
| 855 | + def __init__( |
| 856 | + self, |
| 857 | + module: torch.nn.Module, |
| 858 | + test_data: T, |
| 859 | + aten_op: str | List[str], |
| 860 | + exir_op: Optional[str | List[str]] = None, |
| 861 | + run_on_vulkan_runtime: bool = False, |
| 862 | + vgf_compiler_flags: Optional[str] = "", |
| 863 | + tosa_version: str = "TOSA-1.0+FP", |
| 864 | + symmetric_io_quantization: bool = False, |
| 865 | + per_channel_quantization: bool = False, |
| 866 | + use_to_edge_transform_and_lower: bool = True, |
| 867 | + custom_path: str = None, |
| 868 | + atol: float = 1e-03, |
| 869 | + rtol: float = 1e-03, |
| 870 | + qtol: int = 1, |
| 871 | + dynamic_shapes: Optional[Tuple[Any]] = None, |
| 872 | + ): |
| 873 | + |
| 874 | + if ( |
| 875 | + symmetric_io_quantization or per_channel_quantization |
| 876 | + ) and tosa_version == "TOSA-1.0+FP": |
| 877 | + raise ValueError("Dont configure quantization with FP TOSA profile.") |
| 878 | + if ( |
| 879 | + symmetric_io_quantization is False |
| 880 | + and per_channel_quantization is False |
| 881 | + and tosa_version == "TOSA-1.0+INT" |
| 882 | + ): |
| 883 | + raise ValueError("Missing quantization options for INT TOSA profile.") |
| 884 | + |
| 885 | + tosa_profile = TosaSpecification.create_from_string(tosa_version) |
| 886 | + compile_spec = common.get_vgf_compile_spec( |
| 887 | + tosa_profile, compiler_flags=vgf_compiler_flags, custom_path=custom_path |
| 888 | + ) |
| 889 | + |
| 890 | + super().__init__( |
| 891 | + module, |
| 892 | + test_data, |
| 893 | + aten_op, |
| 894 | + compile_spec, |
| 895 | + exir_op, |
| 896 | + use_to_edge_transform_and_lower, |
| 897 | + dynamic_shapes, |
| 898 | + ) |
| 899 | + |
| 900 | + if symmetric_io_quantization or per_channel_quantization: |
| 901 | + quantizer = VgfQuantizer(compile_spec) |
| 902 | + quantization_config = get_symmetric_quantization_config( |
| 903 | + is_per_channel=per_channel_quantization |
| 904 | + ) |
| 905 | + if symmetric_io_quantization: |
| 906 | + quantizer.set_io(quantization_config) |
| 907 | + quant_stage = Quantize(quantizer, quantization_config) |
| 908 | + else: |
| 909 | + quant_stage = None |
| 910 | + |
| 911 | + if quant_stage: |
| 912 | + self.add_stage(self.tester.quantize, quant_stage, pos=0) |
| 913 | + |
| 914 | + self.add_stage_after( |
| 915 | + "quantize", |
| 916 | + self.tester.check, |
| 917 | + [ |
| 918 | + "torch.ops.quantized_decomposed.dequantize_per_tensor.default", |
| 919 | + "torch.ops.quantized_decomposed.quantize_per_tensor.default", |
| 920 | + ], |
| 921 | + suffix="quant_nodes", |
| 922 | + ) |
| 923 | + |
| 924 | + remove_quant_nodes_stage = ( |
| 925 | + "to_edge_transform_and_lower" |
| 926 | + if use_to_edge_transform_and_lower |
| 927 | + else "partition" |
| 928 | + ) |
| 929 | + self.add_stage_after( |
| 930 | + remove_quant_nodes_stage, |
| 931 | + self.tester.check_not, |
| 932 | + [ |
| 933 | + "torch.ops.quantized_decomposed.dequantize_per_tensor.default", |
| 934 | + "torch.ops.quantized_decomposed.quantize_per_tensor.default", |
| 935 | + ], |
| 936 | + suffix="quant_nodes", |
| 937 | + ) |
| 938 | + else: |
| 939 | + self.add_stage_after( |
| 940 | + "export", |
| 941 | + self.tester.check_not, |
| 942 | + [ |
| 943 | + "torch.ops.quantized_decomposed.dequantize_per_tensor.default", |
| 944 | + "torch.ops.quantized_decomposed.quantize_per_tensor.default", |
| 945 | + ], |
| 946 | + suffix="quant_nodes", |
| 947 | + ) |
| 948 | + |
| 949 | + if run_on_vulkan_runtime: |
| 950 | + pass |
0 commit comments