mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-29 20:14:01 +00:00
[Quant tool] Extend support for QDQ type conversion at graph output (#20841)
### Description Allows mixed-precision overrides that adds a QDQ quantization type conversion sequence at a graph output that **is not** consumed by other nodes. This is not a common use-case but should handle it instead of raising an error. #### Example Original model  mixed-precision overrides: ```python mixed_prec_overrides = { "input_0": [{"quant_type": QuantType.QUInt16}], "op_0_out": [ { "quant_type": QuantType.QUInt16, "convert": {"quant_type": QuantType.QUInt8}, } ], } quantize_static( float_model_path, qdq_model_path, data_reader, quant_format=QuantFormat.QDQ, activation_type=QuantType.QUInt8, op_types_to_quantize=[node.op_type for node in float_model.graph.node], extra_options={ "TensorQuantOverrides": mixed_prec_overrides, }, ) ``` QDQ model:  ### Motivation and Context This scenario is arising for certain quantization configurations. Should handle it gracefully.
This commit is contained in:
parent
d44be41e1c
commit
3044aa8743
2 changed files with 57 additions and 1 deletions
|
|
@ -636,8 +636,12 @@ class QDQQuantizer(BaseQuantizer):
|
|||
| +-> <Graph output>
|
||||
|
|
||||
+-> DQ1' ---> Q2 ---> DQ2 ---> <Consumers of converted type>
|
||||
|
||||
5) Tensor T is a graph output that is not consumed by any other nodes.
|
||||
|
||||
<Producer> ---> Q1 ---> DQ1 ---> Q2 ---> DQ2 ---> <Graph output>
|
||||
"""
|
||||
tensor_recv_nodes = set([node.name for node in self.tensor_to_its_receiving_nodes[tensor_name]])
|
||||
tensor_recv_nodes = set([node.name for node in self.tensor_to_its_receiving_nodes.get(tensor_name, [])])
|
||||
|
||||
if (
|
||||
self.dedicated_qdq_pair
|
||||
|
|
|
|||
|
|
@ -1335,6 +1335,58 @@ class TestQDQMixedPrecision(TestQDQFormat):
|
|||
|
||||
self.assertIn("op_0_out", graph_outputs)
|
||||
|
||||
def test_add_tensor_qdq_ops_case_5(self):
|
||||
"""
|
||||
Tensor T is a graph output without any consumers.
|
||||
<Producer> ---> Q1 ---> DQ1 ---> Q2 ---> DQ2 ---> <Graph output>
|
||||
"""
|
||||
float_model_path = os.path.join(self._tmp_dir_path, "case_5.onnx")
|
||||
qdq_model_path = os.path.join(self._tmp_dir_path, "case_5.qdq.onnx")
|
||||
|
||||
# Build model with input_0 -> op_0 -> op_0_out
|
||||
# The graph output has no consumers.
|
||||
float_model = self.build_test_model_for_add_qdq_ops(0, True)
|
||||
onnx.save_model(float_model, float_model_path)
|
||||
|
||||
data_reader = self.input_feeds(3, {"input_0": (1, 2, 3)}, np.float32)
|
||||
|
||||
mixed_prec_overrides = {
|
||||
"input_0": [{"quant_type": QuantType.QUInt16}],
|
||||
"op_0_out": [
|
||||
{
|
||||
"quant_type": QuantType.QUInt16,
|
||||
"convert": {"quant_type": QuantType.QUInt8},
|
||||
}
|
||||
],
|
||||
}
|
||||
quantize_static(
|
||||
float_model_path,
|
||||
qdq_model_path,
|
||||
data_reader,
|
||||
quant_format=QuantFormat.QDQ,
|
||||
activation_type=QuantType.QUInt8,
|
||||
op_types_to_quantize=[node.op_type for node in float_model.graph.node],
|
||||
extra_options={
|
||||
"TensorQuantOverrides": mixed_prec_overrides,
|
||||
},
|
||||
)
|
||||
|
||||
# Expect the following QDQ model:
|
||||
# input_0 --> Q_16 --> DQ_16 --> op_0 --> Q_16 --> DQ_16 --> Q_8 --> DQ_8 --> output_0
|
||||
qdq_node_counts = {"QuantizeLinear": 3, "DequantizeLinear": 3}
|
||||
check_op_type_count(self, qdq_model_path, **qdq_node_counts)
|
||||
|
||||
qdq_model = onnx.load_model(qdq_model_path)
|
||||
onnx.checker.check_model(qdq_model, True)
|
||||
|
||||
initializers = {init.name: init for init in qdq_model.graph.initializer}
|
||||
|
||||
# Check zero-point data types
|
||||
orig_zp_init = initializers["op_0_out_zero_point"]
|
||||
self.assertEqual(orig_zp_init.data_type, onnx.TensorProto.UINT16)
|
||||
convert_zp_init = initializers["op_0_out_zero_point_convert"]
|
||||
self.assertEqual(convert_zp_init.data_type, onnx.TensorProto.UINT8)
|
||||
|
||||
def build_test_model_1(self, shape):
|
||||
"""
|
||||
Returns the following float32 model.
|
||||
|
|
|
|||
Loading…
Reference in a new issue