shrinath-suresh/blogs-docs-splitted huggingface dataset:
This optimization pass rewrites the graph to replace 2D
     convolutions and linear ops with their prepacked counterparts.
     Prepacked ops are stateful ops in that, they require some state
     to be created, such as weight prepacking and use this state, i.e.
     prepacked weights, during op execution. XNNPACK is one such
     backend that provides prepacked ops, with kernels optimized for
     mobile platforms (such as ARM CPUs). Prepacking of weight enables
     efficient memory access and thus faster kernel execution. At the
     moment "optimize_for_mobile" pass rewrites the graph to replace
     "Conv2D/Linear" with 1) op that pre-packs weight for XNNPACK
     conv2d/linear ops and 2) op that takes pre-packed weight and
     activation as input and generates output activations. Since 1
     needs to be done only once, we fold the weight pre-packing such
     that it is done only once at model load time. This pass of the
     "optimize_for_mobile" does 1 and 2 and then folds, i.e. removes,
weight pre-packing ops.


ReLU/Hardtanh fusion: XNNPACK ops support fusion of clamping.
     That is clamping of output activation is done as part of the
     kernel, including for 2D convolution and linear op kernels. Thus
     clamping effectively comes for free. Thus any op that can be
     expressed as clamping op, such as "ReLU" or "hardtanh", can be
     fused with previous "Conv2D" or "linear" op in XNNPACK. This pass
     rewrites graph by finding "ReLU/hardtanh" ops that follow XNNPACK
     "Conv2D/linear" ops, written by the previous pass, and fuses them
     together.


Dropout removal (blocklisting option
     mobile_optimizer.MobileOptimizerType.REMOVE_DROPOUT): This
     optimization pass removes "dropout" and "dropout_" nodes from
     this module when training is false.


Conv packed params hoisting (blocklisting option
     mobile_optimizer.MobileOptimizerType.HOIST_CONV_PACKED_PARAMS):
     This optimization pass moves convolution packed params to the
root module, so that the convolution structs can be deleted. This
     decreases model size without impacting numerics.

Add/ReLU fusion (blocklisting option
     mobile_optimizer.MobileOptimizerType.FUSE_ADD_RELU): This pass
     finds instances of "relu" ops that follow "add" ops and fuses
     them into a single "add_relu".

for Vulkan Backend, by default, if optimization blocklist is None or
empty, "optimize_for_mobile" will run the following optimization:
   * Automatic GPU Transfer (blocklisting option mobile_optimize
     r.MobileOptimizerType.VULKAN_AUTOMATIC_GPU_TRANSFER): This
     optimization pass rewrites the graph so that moving input and
     output data to and from the GPU becomes part of the model.
"optimize_for_mobile" will also invoke freeze_module pass which only
preserves "forward" method. If you have other method to that needed to
be preserved, add them into the preserved method list and pass into
the method.
the method.
torch.utils.mobile_optimizer.optimize_for_mobile(script_module, optimization_blocklist=None, preserved_methods=None, backend='CPU')
Parameters:
      * script_module (ScriptModule) -- An instance of torch
        script module with type of ScriptModule.
  * **optimization_blocklist**
    (*Optional**[**Set**[**_MobileOptimizerType**]**]*) -- A set
    with type of MobileOptimizerType. When set is not passed,
    optimization method will run all the optimizer pass;
    otherwise, optimizer method will run the optimization pass
    that is not included inside optimization_blocklist.

  * **preserved_methods** (*Optional**[**List**]*) -- A list of
    methods that needed to be preserved when freeze_module pass is
    invoked

  * **backend** (*str*) -- Device type to use for running the
    result model ('CPU'(default), 'Vulkan' or 'Metal').

Returns:
      A new optimized torch script module
Return type:
      RecursiveScriptModule
Quantization Backend Configuration
FX Graph Mode Quantization allows the user to configure various
quantization behaviors of an op in order to match the expectation of
their backend.
In the future, this document will contain a detailed spec of these
configurations.
Default values for native configurations
Below is the output of the configuration for quantization of ops in
x86 and qnnpack (PyTorch's default quantized backends).
Results:
{
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_SHARE_OBSERVER_WITH_INPUT,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_SHARE_OBSERVER_WITH_INPUT,
   },
   {
},
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_SHARE_OBSERVER_WITH_INPUT,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'num_tensor_args_to_observation_type': {
       0: ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
       1: ObservationType.OUTPUT_SHARE_OBSERVER_WITH_INPUT,
       2: ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     },
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
},
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_SHARE_OBSERVER_WITH_INPUT,
   },
   {
     'pattern': (, ),
     'dtype_configs': [
       {
'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     'fused_module': ,
     'fuser_method': ,
   },
   {
},
   {
     'pattern': (, ),
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
'root_module': ,
     'reference_quantized_module_for_root': ,
     'fuser_method': ,
   },
   {
     'pattern': (, ),
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.float32, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
'bias_dtype': torch.float32,
         'is_dynamic': True,
       },
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.float16, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.float32, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.float16, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
         'is_dynamic': True,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
'fused_module': ,
     'fuser_method': ,
   },
   {
     'pattern': (, ),
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'bias_dtype': torch.float32,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     'fused_module': ,
     'fuser_method': ,
   },
   {
     'pattern': (, ),
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     'root_module': ,
     'reference_quantized_module_for_root': ,
     'fuser_method': ,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
   },
   {
     'pattern': (, ),
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     'fused_module': ,
     'fuser_method': ,
   },
   {
     'pattern': (, ),
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     'root_module': ,
     'reference_quantized_module_for_root': ,
     'fuser_method': ,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
   },
   {
'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_SHARE_OBSERVER_WITH_INPUT,
   },
   {
     'pattern': clamp,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_SHARE_OBSERVER_WITH_INPUT,
   },
   {
     'pattern': contiguous,
     'dtype_configs': [
       {
'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
       },
     ],
     'observation_type': ObservationType.OUTPUT_SHARE_OBSERVER_WITH_INPUT,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     'root_module': ,
     'qat_module': ,
     'reference_quantized_module_for_root': ,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     'root_module': ,
'reference_quantized_module_for_root': ,
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],
},
     ],
     'observation_type': ObservationType.OUTPUT_USE_DIFFERENT_OBSERVER_AS_INPUT,
     'input_type_to_index': {'weight': 1, 'bias': 2},
   },
   {
     'pattern': ,
     'dtype_configs': [
       {
         'input_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'output_dtype': DTypeWithConstraints(dtype=torch.quint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'weight_dtype': DTypeWithConstraints(dtype=torch.qint8, quant_min_lower_bound=None, quant_max_upper_bound=None, scale_min_lower_bound=None, scale_max_upper_bound=None, scale_exact_match=None, zero_point_exact_match=None),
         'bias_dtype': torch.float32,
       },
     ],