o
    /ѹg                     @  s  d dl mZ d dlZd dlZd dlZd dlmZ d dlmZ d dl	Z	d dl
Z
d dl
mZmZmZ d dl
mZ d dlmZmZmZmZ d dlmZ d d	lmZmZmZ zd d
lmZ W n eye   dZY nw z
d dlmZmZ W n ey}   dZdZY nw zd dl m!Z! W n ey   dZ!Y nw dZ"dZ#dZ$dZ%dZ&dZ'dZ(dZ)dZ*dZ+i Z,dd e-eD Z.G dd deZ/G dd deZ0G dd deZ1G dd  d eZ2ejj3e	4d!ejj5e	4d"ejj6e	4d#ejj7e	4d$ejj8eejj9eejj:eiZ;ejj5e	j<d e	j=d%e	j<d&e	j=d%fejj3e	j<d'e	j>d%e	j<d(e	j>d%fejj7e	j<d e	j?d%e	j<d)e	j?d%fejj6e	j<d*e	j@d%e	j<d+e	j@d%fejj:e	j<d ed%e	j<d,ed%fejj9e	j<d-ed%e	j<d.ed%fiZAejj5e	j<d e	j=d%e	j<d/e	j=d%fejj3e	j<d0e	j>d%e	j<d(e	j>d%fejj7e	j<d e	j?d%e	j<d1e	j?d%fejj6e	j<d2e	j@d%e	j<d+e	j@d%fiZBejj5e	j<d e	j=d%e	j<d(e	j=d%fejj3e	j<d3e	j>d%e	j<d4e	j>d%fejj7e	j<d e	j?d%e	j<d+e	j?d%fejj6e	j<d5e	j@d%e	j<d6e	j@d%fejj:e	j<d ed%e	j<d.ed%fejj9e	j<d7ed%e	j<d8ed%fiZCd9d:d;d<ZDdd=d>ZEdd@dAZFdBdC ZG	?			dddQdRZH	dddTdUZI		ddd^d_ZJdd`daZKddbdcZLddgdhZMddldmZNG dndo doZOG dpdq dqZPG drds dsZQdtdu ZRdvdw ZSdxdy ZTdzd{ ZUdddZVdd ZWdddZXdddZYdddZZdddZ[dddZ\dddZ]dddZ^dddZ_dddZ`dddZadddZbdddZcdddZddddZedddZfdddZgdddZhdS )    )annotationsN)Enum)Path)
ModelProtoTensorProtoexternal_data_helper)onnx_pb)
make_graph
make_model	make_nodemake_tensor_value_info)ReferenceEvaluator)GraphOptimizationLevelInferenceSessionSessionOptionsfloat8e4m3fn)int4uint4)to_array_extendedzonnx.quantizez0.1.0zai.onnxzcom.microsoftQuantizeLinearZ_QuantizeLinear_InputZDequantizeLinearZ_DequantizeLinear_OutputZ
_quantizedl        c                 C  s(   i | ]}t tt|trtt||qS  )
isinstancegetattrr   int).0kr   r   h/Users/admin/.pyenv/versions/3.10.0/lib/python3.10/site-packages/onnxruntime/quantization/quant_utils.py
<dictcomp>8   s   ( r   c                   @  (   e Zd ZdZdZdd Zedd ZdS )QuantizationModer      c                 C     | j S Nnameselfr   r   r   __str__C      zQuantizationMode.__str__c                 C      zt |  W S  ty   t w r#   )r    KeyError
ValueError)moder   r   r   from_stringF   
   
zQuantizationMode.from_stringN)__name__
__module____qualname__Z
IntegerOpsZ
QLinearOpsr(   staticmethodr.   r   r   r   r   r    ?       r    c                   @  r   )QuantizedValueTyper   r!   c                 C  r"   r#   r$   r&   r   r   r   r(   R   r)   zQuantizedValueType.__str__c                 C  r*   r#   )r5   r+   r,   )vr   r   r   r.   U   r/   zQuantizedValueType.from_stringN)r0   r1   r2   ZInputZInitializerr(   r3   r.   r   r   r   r   r5   N   r4   r5   c                   @  sH   e Zd ZdZdZdZdZdZdZdZ	dd	 Z
ed
d Zedd ZdS )	QuantTyper   r!                  c                 C  r"   r#   r$   r&   r   r   r   r(   f   r)   zQuantType.__str__c                 C  r*   r#   )r7   r+   r,   )tr   r   r   r.   i   r/   zQuantType.from_stringc                 C  s   | t jkrtjS | t jkrtjS | t jkrtjS | t jkr tj	S | t j
kr(tjS | t jkr0tjS | t jkr8tjS td| d)NzUnexpected value qtype=.)r7   QInt8r   INT8QUInt8UINT8QUInt16UINT16QInt16INT16QFLOAT8E4M3FNFLOAT8E4M3FNQUInt4UINT4QInt4INT4r,   r&   r   r   r   tensor_typep   s   






zQuantType.tensor_typeN)r0   r1   r2   r?   rA   rG   rE   rC   rK   rI   r(   r3   r.   propertyrM   r   r   r   r   r7   ]   s    
r7   c                   @  r   )QuantFormatr   r!   c                 C  r"   r#   r$   r&   r   r   r   r(      r)   zQuantFormat.__str__c                 C  r*   r#   )rO   r+   r,   )formatr   r   r   r.      r/   zQuantFormat.from_stringN)r0   r1   r2   Z	QOperatorZQDQr(   r3   r.   r   r   r   r   rO      r4   rO   int8uint8int16uint16dtype   i   i  i i     i      ii  ii@   i i @  r9   zero_point_indexc                 G  s   g }t |D ]H\}}tt|tjr|t| nt|tjr(|| n
t	d| d| || krN|d }|j
tjksF|j
tjkrNt	d|j
 qt|dkrYt|S |d S )Nzarg z is not an array: r^   zzero_point cannot be r!   r   )	enumeratenumpyZ
issubdtypetypenumberappendarrayr   ndarray	TypeErrorrV   float32float16lentuple)r`   argsnew_argsiar6   r   r   r   _check_type   s   rq   c                 C  s  | t v sJ d|  d| tjjtjjtjjtjjfv r|dkr(td|d|jt	j
kr2tj}n|jt	jkr<tj}n	td|j dtttdg dgtjd| g dgd	td
g ddggdtd|d td|d gtd| d g}t|}t|d ||dd S t |  }	t| ddd\}
}|d urt|
|n|
}|d urt||n|}t	|t	j
|  | }t	j||||d t||	S )NUnexpected data type > requested. Only INT8, UINT8, INT16, and UINT16 are supported.r   z2zero_point is expected to be null for float 8 not r>   zUnexpected dtype Constant
zero_point)valuer   )Xscaleru   YZqurw   rx   )rw   rx   F)reduce_range	symmetric)out) ONNX_TYPE_TO_NP_TYPE
onnx_protor   rH   ZFLOAT8E4M3FNUZZ
FLOAT8E5M2ZFLOAT8E5M2FNUZNotImplementedErrorrV   rb   ri   FLOATrj   FLOAT16r,   r
   r	   r   onnxhelpermake_tensorr   r   rq   runget_qmin_qmax_for_qTypemaxminasarrayastyperoundZclip)qTypeZarrrx   ru   lowhighZ	onnx_typeZ
onnx_modelrefrV   qminqmaxZcliplowZcliphighZarr_fp32r   r   r   quantize_nparray   sP   


r   Fc                 C  s  |dks|dk rt d| d| t| tjd| jd} t|tjd|jd}|dur;t|| tj|| jd }|rOtt| t|}| } |
 }||ks]J d|  d| tj||  tj	d}tj|tj	dtj|tj	d }t|| }	|	dksJ d|	t
|jjk rtjd	|jd}	tjd|jd}
|
|	gS |rtjt|| tjd
tj	d |jd}
ntjt|| |	  |jd}
|	|j}	|
|	gS )a  Calculate the scale s and zero point z for the quantization relation
    r = s(q-z), where r are the original values and q are the corresponding
    quantized values.

    r and z are calculated such that every value within [rmin,rmax] has an
    approximate representation within [qmin,qmax]. In addition, qmin <= z <=
    qmax is enforced. If the symmetric flag is set to True, the interval
    [rmin,rmax] is symmetrized to [-absmax, +absmax], where
    absmax = max(abs(rmin), abs(rmax)).

    :parameter rmin: minimum value of r
    :parameter rmax: maximum value of r
    :parameter qmin: minimum value representable by the target quantization data type
    :parameter qmax: maximum value representable by the target quantization data type
    :parameter symmetric: True if the floating-point range should be made symmetric. Defaults to False.
    :parameter min_real_range: Minimum floating-point range (i.e., rmax - rmin) to enforce. Defaults to None.
    :return: zero and scale [z, s]

    r   Bqmin and qmax must meet requirement: qmin <= 0 <= qmax while qmin:, qmmax:rU   Nzqmin=z > qmax=z
scale isse      ?g       @)r,   rb   Zminimumrf   rV   maximumr   r   absZfloat64ZfinfoZtinyr   r   )rminrmaxr   r   r{   min_real_rangeZabsmaxZdrZdqrx   ru   r   r   r   compute_scale_zp   s4     r   c           	        s   d}| t vr?| tjkr2ddlm  ddlm} |} fddtdD }tj	dd |D tj
d	}ntd
|  d|t | < n| tjkrLddlm} |}|du rXtd|  dtt |  }tj	d|d	}tj	|| |jd	}||gS )ar  Calculate the scale s for a float8 type (E4M3FN).
    The function assumes the coefficient distribution and the float 8
    distribution are similar to two gaussian laws.

    :return: zero and scale [z, s]

    More details in notebook `quantization_fp8.ipynb
    <https://github.com/microsoft/onnxruntime/blob/main/docs/python/notebooks/quantization_fp8.ipynb>`_.
    Nr   float8e4m3_to_float32r   c                   s   g | ]} |qS r   r   )r   ro   r   r   r   
<listcomp>J  s    z+compute_scale_zp_float8.<locals>.<listcomp>   c                 S  s$   g | ]}t |st |s|qS r   )rb   isnanisinf)r   fr   r   r   r   L  s   $ rU   zQuantization to element_type=z not implemented.zUnexpected element_type r>   )FLOAT8_DISTRIBUTIONSr   rH   Zonnx.numpy_helperr   #onnx.reference.custom_element_typesr   rangerb   rf   ri   r,   rh   stdrV   )	Zelement_typer   Zzp_dtyper   Z
all_valuesvaluesZstd_f8zerorx   r   r   r   compute_scale_zp_float89  s*   



r   datanumpy.ndarray
quant_typeonnx.TensorProto.DataTyper{   boolrz   r   float | Nonermin_overridermax_overridereturn#tuple[numpy.ndarray, numpy.ndarray]c                 C  sP  t | tjstdt|  d|dur|}n
t| r|  nd}|dur(|}n
t| r0|  nd}tj|| j	d}tj|| j	d}tjd| j	d}	|t
jkrh|rUtdt| }
t||
\}}	t||	dd	S |t
jt
jt
jt
jt
jt
jfv rt|||d
\}}t| rt||||||\}}	ntjd|j	d}t||	dd	S td| d)a  
    Returns the zero_point and scale for the given data.

    :param data: The data for which to compute quantization parameters.
    :param quant_type: The quantization data type.
    :param symmetric: whether symmetric quantization is used or not.
    :parameter reduce_range: True if the quantization range should be reduced. Defaults to False.
    :parameter min_real_range: Minimum floating-point range (i.e., rmax - rmin) to enforce. Defaults to None.
    :parameter rmin_override: The value of rmin to use if not None. Otherwise, uses min(data).
    :parameter rmax_override: The value of rmax to use if not None. Otherwise, uses max(data).
    :return: zero point and scale
    z%Weight must be given as an array not r>   Ng        rU   r   z1Unsupported option reduce_range=True for float 8.r   r_   r{   z Unexpected value for quant_type=)r   rb   rg   rh   rc   rk   r   r   rf   rV   r   rH   RuntimeErrorr   r   rq   r@   rB   rF   rD   rL   rJ   r   r   r,   )r   r   r{   rz   r   r   r   r   r   rx   r   ru   r   r   r   r   r   compute_data_quant_params^  s>   

r   2tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]c              
   C  s   t | ||||||\}}|tjkrIt|| ||}	t|	tj d@ dkrDt	| }
t
d|
  d|
  d|	  d|	  d	|||	fS |tjtjtjtjtjtjfv ret|| ||}	|||	fS td| d)	al  
    :param data: data to quantize
    :param qType: data type to quantize to.
    :param symmetric: whether symmetric quantization is used or not.
    :parameter reduce_range: True if the quantization range should be reduced. Defaults to False.
    :parameter min_real_range: Minimum floating-point range (i.e., rmax - rmin) to enforce. Defaults to None.
    :parameter rmin_override: The value of rmin to use if not None. Otherwise, uses min(data).
    :parameter rmax_override: The value of rmax to use if not None. Otherwise, uses max(data).
    :return: minimum, maximum, zero point, scale, and quantized weights

    To pack weights, we compute a linear transformation

    - when data `type == uint8` mode, from `[rmin, rmax]` -> :math:`[0, 2^{b-1}]` and
    - when data `type == int8`, from `[-m , m]` -> :math:`[-(2^{b-1}-1), 2^{b-1}-1]` where
        `m = max(abs(rmin), abs(rmax))`

    and add necessary intermediate nodes to transform quantized weight to full weight using the equation

    :math:`r = S(q-z)`, where

    - *r*: real original value
    - *q*: quantized value
    - *S*: scale
    - *z*: zero point
    rX   z+One of the quantized value is NaN data in [z, z], quantized_data in [z].zUnexpected value for qType=r>   N)r   r   rH   r   anyr   rb   rR   ravelr   r   r   r   r@   rB   rF   rD   rL   rJ   r,   )r   r   r{   rz   r   r   r   ru   rx   quantized_dataZnp_datar   r   r   quantize_data  s@   
	


r   weightonnx.TensorProtoru   rx   axis
int | Nonequant_weight_name
str | Nonec                 C  s  t | }d}|du rt|| ||}n?|j| }t|j}	d|	|< g }
t|D ]$}|||}|| }|| }t|| ||}|
t	|
|	 q(t|
|}|rW|n| j t }|tjjkrt }||_|j| j ||_|   |_tdurt|}|j|jks| | krtd|j d| dd  d| dd  d| j dt|dd	  d
|S |tjjtjjfv r|jtjtjfvrtd| dt t!| }tj"j#||| j|dd}|S tj"$|}tj	||d
| j}tj%&||}|S )aG  
    Returns a quantized version of the given ONNX initializer.

    :param weight: The ONNX initializer to quantize.
    :param quant_type: The final quantized data type.
    :param zero_point: The zero-point value to use for quantization.
    :param scale: The scale value to use for quantization.
    :param axis: The quantization axis if quantizing per-channel. Defaults to None.
    :param quant_weight_name: The name of the quantized initializer.
                              If not specified, the quantized name is generated.
    :return: The quantized ONNX initializer.
    Nr!   zThe initializer of shape z! could not be created, expecting 
   z, got z and shape=z
raw=   r>   zQuantized weights for z. must be 8-bit before packing as 4-bit values.T)rawrU   )'tensor_proto_to_arrayr   r   shapelistr   Ztakere   rb   r   ZreshapeZconcatenater%   TENSOR_NAME_QUANT_SUFFIXr   r   rH   	data_typedimsextendflattencopytobytesraw_datar   r   strrL   rJ   rV   rQ   rR   bytespack_bytes_to_4bitr   r   Ztensor_dtype_to_np_dtypenumpy_helperZ
from_array)r   r   ru   rx   r   r   Zweight_dataZq_weight_dataZchannel_countZchannel_dimsZquantized_channel_data_listro   Zchannel_dataZchannel_scaleZchannel_zero_pointZquantized_channel_dataZq_weight_nameZq_weight_initializercheckZpacked_dataZquant_np_dtyper   r   r   quantize_onnx_initializer  sb   


r   c                 C  s   | t jjkr
tdd}|rt| }n|r| tv rt|  }nt| }|s.td|  d|\}}|dks:|dk rQtd| d| d|j	 d	| d
| d|  |S )z
    Return qmin and qmax, the minimum and maximum value representable by the given qType
    :parameter qType: onnx.onnx_pb.TensorProto.UINT8 or onnx.onnx_pb.TensorProto.UINT8
    :return: qmin, qmax
    z;This function is not implemented for float 8 as not needed.Nrr   rs   r   r   r   z, dtype=z, reduce_range=z, symmetric=z, qType=)
r~   r   rH   r   ONNX_INT_TYPE_REDUCED_RANGEgetONNX_INT_TYPE_SYMMETRIC_RANGEONNX_INT_TYPE_RANGEr,   rV   )r   rz   r{   Zqranger   r   r   r   r   r   (  s8   

r   c                 C  s   t | ||d\}}|| S )z
    Helper function to get the quantization range for a type.
        parameter qType: quantization type.
        return: quantization range.
    r   N)r   )r   rz   r{   r   r   r   r   r   get_qrange_for_qTypeH  s   r   r   ranktuple[bool, int]c                 C  s,   | dk r| | n| }|dko||k }||fS )z
    Helper function that tries to return a normalized axis in the range [0, rank - 1].
    :parameter axis: The axis to normalize.
    :parameter rank: The tensor rank (number of dimensions).
    :return (is_valid, axis_norm)
    r   Nr   )r   r   Z	axis_normZis_validr   r   r   normalize_axisR  s   r   src_8bitr   	bytearrayc                 C  s   t | }|dkrt S |d d }t|}d}d}||d k r?| |d  d@ d> | | d@ B ||< |d7 }|d7 }||d k s||k rK| | d@ ||< |S )aB  
    Copies a source array of 8-bit values into a destination bytearray of packed 4-bit values.
    Assumes that the source values are already in the appropriate int4 range.
    :parameter src_8bit: The 8-bit element values to pack.
    :return A bytearray with every two 8-bit src elements packed into a single byte.
    r   r!   r8   rY   r:   N)rk   r   )r   Z	num_elemsZdst_sizedstZsrc_iZdst_ir   r   r   r   ^  s   $r   c                   @  s    e Zd ZdZg g dfddZdS )QuantizedInitializerzJ
    Represents a linearly quantized weight input from ONNX operators
    Nc
           
      C  :   || _ || _|| _|| _|| _|| _|| _|| _|	| _d S r#   )	r%   initializerrminsrmaxszero_pointsscalesr   r   r   )
r'   r%   r   r   r   r   r   r   r   r   r   r   r   __init__  s   
zQuantizedInitializer.__init__r0   r1   r2   __doc__r   r   r   r   r   r   |  s    r   c                   @  s"   e Zd ZdZ				dddZdS )QuantizedValuezI
    Represents a linearly quantized value (input\output\intializer)
    Nc
           
      C  r   r#   )	original_nameZq_name
scale_nameZzp_nameZ
value_typer   	node_type
node_qtype
scale_type)
r'   r%   Znew_quantized_namer   Zzero_point_nameZquantized_value_typer   r   r   r   r   r   r   r     s   
zQuantizedValue.__init__)NNNNr   r   r   r   r   r     s    r   c                   @  s   e Zd ZdZdd ZdS )BiasToQuantizez+
    Represents a bias to be quantized
    c                 C  s   || _ || _|| _d S r#   )	bias_name
input_nameweight_name)r'   r   r   r   r   r   r   r     s   
zBiasToQuantize.__init__Nr   r   r   r   r   r     s    r   c                 C  s   | j dkrtd| j d| j dkr| j}n^| j dkr | j}nU| j dkr)| j}nL| j dkr2| j}nC| j dkr;| j}n:| j d	krD| j}n1| j d
krM| j	}n(| j dkrV| j
}n| j dkr_| j}n| j dkrh| j}ntd| j d| j  d| j|iS )z
    Convert attribute to kwarg format for use with onnx.helper.make_node.
        :parameter attribute: attribute in AttributeProto format.
        :return: attribute in {key: value} format.
    r   z
attribute z does not have type specified.r!   r8   r9   r:   r;   r<   rZ      	   r   z has unsupported type r>   N)rc   r,   r%   r   ro   sr=   gfloatsZintsstringsZtensorsZgraphs)	attributerv   r   r   r   attribute_to_kwarg  s0   











r   c                   s*    fdd|D }t |dkr|d S dS )z
    Helper function to find item by name in a list.
        parameter item_name: name of the item.
        parameter item_list: list of items.
        return: item if found. None otherwise.
    c                   s   g | ]	}|j  kr|qS r   r$   )r   item	item_namer   r   r     s    z find_by_name.<locals>.<listcomp>r   N)rk   )r   Z	item_listitemsr   r   r   find_by_name  s   r  c                 C  s*   d}t t|D ]
}|| | kr|}q|S )zC
    Helper function to return index of an item in a node list
    r^   N)r   rk   )Z	elem_nameZ	elem_listZelem_idxro   r   r   r   get_elem_index  s   r  c                 C  s   t jd| |g|S )z
    Helper function to create a Mul node.
        parameter inputs: list of input names.
        parameter output: output name.
        parameter name: name of the node.
        return: Mul node in NodeProto format.
    ZMulN)r   r   r   )inputsoutputr%   r   r   r   get_mul_node  s   r  filenamer   
identifierr   c                 C  s   | j | j| | j S )zp
    Helper function to generate a identifiable filepath by concatenating the given identifier as a suffix.
    N)parentjoinpathstemsuffix)r  r  r   r   r   generate_identified_filename  s   r  c                 C  s   dd l }dd lm} dd l}|j|jd td t|  td t| |j| |dd |d |	d |
d	 |  d S )
Nr   )	thresholdz
Histogram:zHistogram Edges:T)fillzTensor valueZCountszTensor value V.S. Counts)sysZmatplotlib.pyplotZpyplotrb   Zset_printoptionsmaxsizeprintZstairsZxlabelZylabeltitleshow)histZ
hist_edgesr  Zpltrb   r   r   r   
apply_plot  s   


r  r>   c                   s<  ddl ddl}ddlddlm  m  m} ddlm  m  m} ddl	m
 mm td|   G  fdddj}j| |d}ttj|dd	}|| W d   n1 sfw   Y  d}|d
}	g }
t|  D ]I}| | }| }t|d| t|d| g}tt|}|	 |}|	 |}|!|	 |"|	| |#|	| |$|	}|
%| q}|&|	t'|
 |
D ]}|	(| q|	) }|*|	 |+|	| |,|	}|	-| |	. }ttj|dd}|| W d   n	1 sw   Y  tj/dddv rF|j0|d}|1 }t2|D ]}|3|}t|4  t|5  q/ttj|dd	C}t|  D ]3}| | }| }t|d| t|d| g}|d tt| }|| |d qWW d   dS 1 sw   Y  dS )z>
    Helper function to write calibration table to files.
    r   N)CalibrationMethod
TensorDataTensorsDatazcalibration cache: c                      s    e Zd Z fddZdS )z*write_calibration_table.<locals>.MyEncoderc                   sb   t |fr| S t |jr| t|jddS t | r*|jjt|dS j	| |S )Nznumpy.array)r   rV   CLS)r  rv   )
r   to_dictrg   tolistr   rV   	__class__r0   JSONEncoderdefault)r'   objr  r  r  jsonnpr   r   r  2  s   
z2write_calibration_table.<locals>.MyEncoder.defaultN)r0   r1   r2   r  r   r   r   r   	MyEncoder1  s    r#  )clszcalibration.jsonwi   ZhighestZlowestzcalibration.flatbufferswbZQUANTIZATION_DEBUG)r!   1zcalibration.cache 
)6r!  flatbuffersrb   Z5onnxruntime.quantization.CalTableFlatBuffers.KeyValueZquantizationZCalTableFlatBuffersKeyValueZ5onnxruntime.quantization.CalTableFlatBuffers.TrtTableTrtTableZ"onnxruntime.quantization.calibrater  r  r  logginginfor  dumpsopenospathjoinwriterf   ZBuildersortedkeysr  floatr   r   r   r   ZCreateStringZKeyValueStartZKeyValueAddKeyZKeyValueAddValueZKeyValueEndre   ZTrtTableStartDictVectorrk   ZPrependUOffsetTRelativeZ	EndVectorZTrtTableStartZTrtTableAddDictZTrtTableEndZFinishZOutputenvironZGetRootAsTrtTableZ
DictLengthr   DictKeyValue)Zcalibration_cachedirr*  r+  r,  r#  Z	json_datafiler   ZbuilderZkey_value_listkeyr   Zd_valuesr   rv   Zflat_keyZ
flat_value	key_valueZ	main_dictZ	cal_tablebufZdict_lenro   r   r   r   write_calibration_table!  sx   











$rA  -C6?c                 C  s   | dk tj}| dk tj}| }| j| }|sdS |t| t| }|dk s4J d|||f |  tj}||| | |  7 }|dk dksOJ |S )a~  Given a discrete distribution (may have not been normalized to 1),
    smooth it by replacing zeros with eps multiplied by a scaling factor
    and taking the corresponding amount off the non-zero values.
    Ref: http://web.engr.illinois.edu/~hanj/cs412/bk3/KL-divergence.pdf
         https://github.com//apache/incubator-mxnet/blob/master/python/mxnet/contrib/quantization.py
    r   Nr   z"n_zeros=%d, n_nonzeros=%d, eps1=%f)r   rb   ri   sumsizer7  )pZepsZis_zerosZis_nonzerosZn_zerosZ
n_nonzerosZeps1r  r   r   r   smooth_distribution}  s    
rF  
model_pathc                 C  s4   t j|  dd}|jjD ]
}t|r dS qdS )NF)Zload_external_dataT)r   loadas_posixgraphr   r   Zuses_external_data)rG  modelZ
intializerr   r   r   model_has_external_data  s   
rL  opt_model_pathc                 C  sF   t  }| |_tj|_i }dg|d< t|  |fddgi|}dS )z
        Generate model that applies graph optimization (constant folding, etc.)
        parameter model_path: path to the original onnx model
        parameter opt_model_path: path to the optimized onnx model
    :return: optimized onnx model
    ZConstantSharingZdisabled_optimizers	providersZCPUExecutionProviderN)r   rI  Zoptimized_model_filepathr   ZORT_ENABLE_BASICZgraph_optimization_levelr   )rG  rM  Zsess_optionkwargs_r   r   r   optimize_model  s   

 rQ  rK  r   c                 C  s>   ddi}| j r| j D ]}||j|ji q
tj| | dS )z>Tag the model that it went through quantization pre-processingonnx.quant.pre_processonnxruntime.quantNmetadata_propsupdater>  rv   r   r   Zset_model_props)rK  rU  propr   r   r   add_pre_process_metadata  s
   
rX  c                 C  0   | j r| j D ]}|jdkr|jdkr dS qdS )zCCheck the model whether it went through quantization pre-processingrR  rS  TFNrU  r>  rv   )rK  rW  r   r   r   model_has_pre_process_metadata  s   
r[  c                 C  s>   ddi}| j r| j D ]}||j|ji q
tj| | d S )N
onnx.inferrS  rT  )rK  rU  rE  r   r   r   add_infer_metadata  s
   
r]  c                 C  rY  )Nr\  rS  TFrZ  )rK  rE  r   r   r   model_has_infer_metadata  s   
r^  c                 C  sB   t | d}tjt| t| t| }t| |  |S )Nz	-inferred)	r  r   Zshape_inferenceZinfer_shapes_pathr   rH  rI  r]  unlink)rG  Zinferred_model_pathrK  r   r   r   load_model_with_shape_infer  s   
r`  c                 C  sZ   t jdd}t|d}tj| | dd t|W  d    S 1 s&w   Y  d S )Nz
ort.quant.)prefixz
model.onnxT)Zsave_as_external_data)tempfileTemporaryDirectoryr   r	  r   Z
save_modelrI  r`  )rK  Zquant_tmp_dirrG  r   r   r   &save_and_reload_model_with_shape_infer  s
   $rd  r   r   c                 C  s>   | j tjjtjjfv rtj| S td| j	 dt
| j   )Nz&Only float type is supported. Weights z is )r   r~   r   r   r   r   r   Zto_arrayr,   r%   type_to_name)r   r   r   r   r     s
   r   tensor_namec                 C     | d S )NZ_QuantizeLinearr   rf  r   r   r   add_quant_suffix     ri  c                 C     | t  S r#   )QUANT_INPUT_SUFFIXrh  r   r   r   add_quant_input_suffix  rj  rm  c                 C  rg  )NZ_QuantizeLinear_Outputr   rh  r   r   r   add_quant_output_suffix  rj  rn  c                 C  rg  )NZ_DequantizeLinearr   rh  r   r   r   add_dequant_suffix  rj  ro  c                 C  rg  )NZ_DequantizeLinear_Inputr   rh  r   r   r   add_dequant_input_suffix  rj  rp  c                 C  rk  r#   )DEQUANT_OUTPUT_SUFFIXrh  r   r   r   add_dequant_output_suffix  rj  rr  )NN)FN)FNNN)r   r   r   r   r{   r   rz   r   r   r   r   r   r   r   r   r   )r   r   )r   r   r   r   ru   r   rx   r   r   r   r   r   r   r   )FF)r   r   r   r   r   r   )r   r   r   r   )r  r   r  r   r   r   )r>   )rB  )rG  r   )rG  r   rM  r   )rK  r   )rK  r   r   r   )rG  r   r   r   )rK  r   r   r   )r   r   r   r   )rf  r   r   r   )r   r   )i
__future__r   r-  r1  rb  enumr   pathlibr   rb   r   r   r   r   r   r~   Zonnx.helperr	   r
   r   r   Zonnx.referencer   Zonnxruntimer   r   r   r   r   ImportErrorr   r   Zonnx.reference.op_runr   Z__producer____version__Zonnx_domainZ	ms_domainZQUANT_OP_NAMErl  ZDEQUANT_OP_NAMErq  r   ZMODEL_SIZE_THRESHOLDr   r<  re  r    r5   r7   rO   r@   rV   rB   rF   rD   rH   rL   rJ   r}   rf   rR   rQ   rT   rS   r   r   r   rq   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r  rA  rF  rL  rQ  rX  r[  r]  r^  r`  rd  r   ri  rm  rn  ro  rp  rr  r   r   r   r   <module>   s   &$$$$  $
$$$$$$$  


4?)?B
O
 


%


\



	
	


	

	



