fuse "dequantize -> cat -> quantize" pattern to cat operator, only happens if the quantization parameters for dequantize for all the inputs matches, and it also matches the quantization parameters for the quantize node after cat
(model: GraphModule)
| 19 | |
| 20 | |
| 21 | def _fuse_quantized_cat(model: GraphModule) -> None: |
| 22 | """fuse "dequantize -> cat -> quantize" pattern to cat operator, only happens if the quantization |
| 23 | parameters for dequantize for all the inputs matches, and it also matches the quantization |
| 24 | parameters for the quantize node after cat |
| 25 | """ |
| 26 | |
| 27 | # get quantization parameters for the node, either for quantize or dequantize node |
| 28 | def _get_qparams(node): |
| 29 | assert node.target in ( |
| 30 | exir_ops.edge.quantized_decomposed.quantize_per_tensor.default, |
| 31 | exir_ops.edge.quantized_decomposed.dequantize_per_tensor.default, |
| 32 | ) |
| 33 | args = list(node.args) |
| 34 | # skip input |
| 35 | qparams = args[1:] |
| 36 | return qparams |
| 37 | |
| 38 | for n in model.graph.nodes: |
| 39 | if ( |
| 40 | n.op != "call_function" |
| 41 | or n.target |
| 42 | != exir_ops.edge.quantized_decomposed.quantize_per_tensor.default |
| 43 | ): |
| 44 | |
| 45 | continue |
| 46 | qnode = n |
| 47 | maybe_cat = qnode.args[0] |
| 48 | if ( |
| 49 | maybe_cat.op != "call_function" |
| 50 | or maybe_cat.target != exir_ops.edge.aten.cat.default |
| 51 | ): |
| 52 | |
| 53 | continue |
| 54 | tensor_args = maybe_cat.args[0] |
| 55 | if not isinstance(tensor_args, (tuple, list)): |
| 56 | continue |
| 57 | |
| 58 | matched_quantized_cat = True |
| 59 | output_qparams = _get_qparams(qnode) |
| 60 | for tensor_arg in tensor_args: |
| 61 | if ( |
| 62 | tensor_arg.op != "call_function" |
| 63 | or tensor_arg.target |
| 64 | != exir_ops.edge.quantized_decomposed.dequantize_per_tensor.default |
| 65 | ): |
| 66 | |
| 67 | matched_quantized_cat = False |
| 68 | break |
| 69 | |
| 70 | # make sure the input qparams for each input tensor in the concat list |
| 71 | # matches the output qparams |
| 72 | current_input_qparams = _get_qparams(tensor_arg) |
| 73 | if not current_input_qparams == output_qparams: |
| 74 | matched_quantized_cat = False |
| 75 | break |
| 76 | |
| 77 | if not matched_quantized_cat: |
| 78 | continue |
no test coverage detected