
    קg[                     8   d dl Z d dlZd dlmZmZmZmZmZmZm	Z	 d dl
Z
d dlmc mZ d dlmZ d dlmZ d dlmZ d dlmZmZ d dlmZmZ d dlmZ d d	lmZ d
dgZe
j         j!        j"        j#        e
j         j!        j"        j$        e
j         j!        j%        j#        gZ&e
j         j!        j'        j#        e
j         j!        j'        j$        e
j         j!        j(        j#        gZ) e
j*        ddd           e
j*        ddd           e
j*        d           e
j*        d           e
j*        d           e
j*        d           e
j*        d          fZ+ e
j*        dddd           e
j*        dddd           e
j*        d           e
j*        d           e
j*        d           e
j*        d           e
j*        d          fZ,de
j-        j        de
j-        j        de.fdZ/de
j-        j        de
j-        j        deeef         fdZ0defdZ1de
j-        j        dee
j-        j                 fdZ2dede.fdZ3d Z4d Z5defdZ6defdZ7defdZ8defd Z9d!efd"Z:defd#Z;d$ed%ed&ee         d'ed(eddfd)Z<d(eddfd*Z=d+edee>ee>e?f         f         fd,Z@	 d=d.ed/eed0f         d1e.defd2ZAd3eddfd4ZBd5 ZC	 	 d>d6e
j-        j        d7e.d8eee                  fd9ZD	 	 d?d6e
j-        j        d8eee                  d:eee	eEeFe.e
jG        f         eFf                  fd;ZHd+efd<ZIdS )@    N)AnyCallableDictListOptionalTupleUnion)capture_pre_autograd_graph)quantized_decomposed_lib)QuantizationAnnotation)_assign_attr	_AttrKind)GraphModuleNode)fuse_conv_bn_weights)LeafSpecfold_bn_weights_into_conv_node"remove_tensor_overload_for_qdq_ops      sourcedestreturnc                 T   t           t          z   }|                    t          j        j        j        j                   |j        |v r]t          |j
        d         t          j        j                  st          d|j
        d                    |j
        d         }|j        |v ]|| k    S )z
    Assuming dest is one of the ops inserted by quant workflow, this function
    finds if source and dest are connected. Assumption is that only quant workflow
    inserted ops exist between source and dest
    r   z=expected arg[0] of quant workflow ops to be a node but found )_QUANTIZE_OPS_DEQUANTIZE_OPSappendtorchopsquantized_decomposedchoose_qparamstensortarget
isinstanceargsfxr   
ValueError)r   r   quant_workflow_opss      \/var/www/html/ai-engine/env/lib/python3.11/site-packages/torch/ao/quantization/pt2e/utils.py_is_connectedr*   <   s     '8ei<KRSSS
++
+
+$)A,66 	^PTPYZ[P\^^   y| ++
+
+ 6>    produeruserc                    d}|j         D ]N}t          |t          j        j                  r-|j        dk    r"|j        t          v rt          | |          r|} nO|V|j	        D ]N}t          |t          j        j                  r-|j        dk    r"|j        t          v rt          | |          r|} nO|dS d}|j         d         j        dk    r&|j         d         j        t          v r|j         d         }||fS )z
    Find q, dq pair corresponding to [producer -> q -> dq -> user]
    Utils works by finding dq arg of user and ensuring it is connected to
    producer
    Ncall_functionNNr   )r%   r$   r   r&   r   opr#   r   r*   kwargsr   )r,   r-   dq_nodenq_nodes        r)   _find_q_dq_node_for_userr6   M   s    GY  q%(-((	''O++Wa((  	 	A1ehm,,DO++H// !,, GE|FQo--LO"m33aGr+   nodec                 $   | j         dk    r$| j        t          j        j        j        j        k    pa| j        t          j        j        j        j        k    p=| j        t          j        j        j        k    p| j        t          j        j        j        k    S )Nr/   )r1   r#   r   r   atensym_sizedefault	sym_numel)r7   s    r)   _is_sym_size_noder=   u   ss    ?" 	;K59>2::	2;%).2::	2 ;%).22	2 ;%).11r+   c                 L    t          t          d | j                            }|S )Nc                 $    t          |           du S )NF)r=   )xs    r)   <lambda>z(_filter_sym_size_users.<locals>.<lambda>   s    ):1)=)=)F r+   )listfilterusers)r7   
node_userss     r)   _filter_sym_size_usersrF      s%    fGG$*UUVVJr+   
annotationc                 X    | dS | j         }| j        }t          |          dk    r|dS dS )NFr   T)input_qspec_mapoutput_qspeclen)rG   rI   rJ   s      r)   _is_valid_annotationrL      s?    u 0O*L
?q  \%9u4r+   c           	      $   | d S | j         dk    sJ | j                            d          }|}t          |          D ]R\  }}t	          ||          s-t          dd                    |d |                              t          ||          }S|S )Nget_attr.z#Node referenced nonexistent target )r1   r#   split	enumeratehasattrRuntimeErrorjoingetattr)r7   mtarget_atomsattr_itriatoms         r)   _get_tensor_constant_from_noder[      s    |t7j    ;$$S))LH\** + +4x&& 	Rchh|BQB?O6P6PRR   8T**Or+   c                 (   g }t          |          D ]\  }}|j        |v r!|                    ||j                            /|j        s/|t	          |           k     r|                    | |                    e|                    |j                   |S N)rQ   namer   
kwarg_onlyrK   default_value)	orig_argsorig_kwargsargs_schemaall_argsrY   schemas         r)   _get_all_argumentsrf      s    H{++ 2 2	6;+%%OOK45555" 	2q3y>>'9'9OOIaL))))OOF01111Or+   c                     t           j        j        j        j        t           j        j        j        j        t           j        j        j        j        t           j        j        j        j        g}| j        |v S )zU
    Return True if the given node refers to an aten batch norm op QAT supports.
    )	r   r   r9   
batch_normr;   _native_batch_norm_legitcudnn_batch_normmiopen_batch_normr#   )r7   supported_opss     r)   %_is_supported_batch_norm_for_trainingrm      sP    
 		!)	/7 		'/	(0M ;-''r+   r4   c                     | j         dk    o<| j        t          j        j        j        j        t          j        j        j        j        fv S )z<
    Return whether the node refers to an aten conv op.
    r/   )r1   r#   r   r   r9   conv1dr;   conv2dr4   s    r)   _is_conv_noderr      s@     4?" qx	%	%4 ( r+   c                     | j         dk    of| j        t          j        j        j        t          j        j        j        j        t          j        j        j        t          j        j        j        j        fv S )zF
    Return whether the node refers to an aten conv_transpose op.
    r/   )	r1   r#   r   r   r9   conv_transpose1dr;   conv_transpose2dinputrq   s    r)   _is_conv_transpose_noderw      sT     4?" qx	'	'/	'	'-	4 ( r+   c                 >    t          |           pt          |           S )zN
    Return whether the node refers to an aten conv or conv transpose op.
    )rr   rw   rq   s    r)   _is_conv_or_conv_transpose_nodery      s      96q999r+   conv_fnc                 6    | t           j        t           j        fv S r]   )Frt   ru   )rz   s    r)   _is_conv_transpose_fnr}      s    q)1+=>>>r+   c                 h    t          |           p#| j        t          j        j        j        j        k    S r]   )rm   r#   r   r   r9   $_native_batch_norm_legit_no_trainingr;   rq   s    r)   _is_bn_noder      s,    -a00 	S8uy~JRRr+   	conv_nodeconv_weight_nodeconv_bias_nodebn_noderV   c           
      Z   t          ||          }t          ||          }t          |           }|j        j        j        }t          |j        |j        |          }	t          |	d         |          }
t          |	d         |          }t          |	d         |          }t          |	d         |          }|j        t          j	        j
        j        j        k    rd}n't          |          rd}nt          d|j                  |	|         }t          ||||||
||          \  }}t!          | j                  }t#          |          dk    r|                    d            |j        }t'          |t(                    sJ t+          |||t,          j                   |1|j        }t+          ||t)          |          t,          j                   nr|d	z   }t+          |||t,          j                   |j                            |           5  |j                            |          }d d d            n# 1 swxY w Y   ||d<   t7          |          | _        |j        t          j	        j
        j        j        k    r|                    |            nQ|j        D ]I}|j        d
k    s&|j        t@          j!        k    s|j        d         dk    r4|                    |            J|j        "                                 t#          |j                  dk    r|j        #                    |           d S d S )Nr      r            zBN node target is unexpected )	transpose_biasr/   r   )$r[   rw   r#   _schema	argumentsrf   r%   r2   r   r   r9   r   r;   rm   r'   r   rB   rK   r   r$   strr   r   	PARAMETERgraphinserting_beforerN   tuplerh   replace_all_uses_withrD   r1   operatorgetitemeliminate_dead_code
erase_node)r   r   r   r   rV   conv_wconv_br   bn_args_schemabn_argsbn_wbn_bbn_rmbn_rveps_arg_indexbn_epsfused_weight
fused_bias	conv_argsweight_attr_namebias_attr_nameget_bias_noder-   s                          r)   r   r      sT    ,,<a@@F+NA>>F'	22I ^+5N w~~NNG)'!*a88D)'!*a88D*71:q99E*71:q99E~LTTT	.w	7	7 J8'.III]#F3ufdDI     L*
 Y^$$I
9~~ (.&,,,,,q"2I4GHHH!'.ZC$7$79LMMMM)G3ZNI4GHHHW%%i00 	= 	=G,,^<<M	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= 	= %	!9%%IN
 ~2::: 	%%i0000 M 	2 	2D?**;("2229Q<1$$&&y1111 G!!!
7=Q	7##### s   H//H36H3c                 .   t          d | j        j        D                       }|sd S | j        j        D ]}|j        dk    s=|j        t
          j        j        j        j	        t
          j        j        j
        j	        fvrK|}|j        d         }t          |          sj|}|j        d         }t          |j                  dk    r|j        d         nd }t          |||||            | j                                         |                                  d S )Nc              3   4   K   | ]}t          |          V  d S r]   )r   ).0r4   s     r)   	<genexpr>z!_fuse_conv_bn_.<locals>.<genexpr>E  s(      77AQ777777r+   r/   r   r   r   )anyr   nodesr1   r#   r   r   r9   r   r;   rh   r%   ry   rK   r   r   	recompile)rV   has_bnr4   r   r   r   r   s          r)   _fuse_conv_bn_r   D  s%   7777777F W] 
 
4?""ahIN?GIN%-7
 '
 '
 LO.q11 		$>!,.1)..A.AA.E.E**4&'!	
 	
 	
 	
 G!!!KKMMMMMr+   modelc                 8   i }| j         j        D ]}|j                            dd           }dt	          d           f}|rPt          |                                          d         }|d                             d          d         |d         f}|||j        <   |S )Nnn_module_stack r   rO   r   )	r   r   metagettyperB   valuesrP   r^   )r   node_name_to_scoper4   r   current_scopebts         r)   _get_node_name_to_scoper   ]  s    68[ 3 3&**%6==T$ZZ( 	:o,,..//3BU[[--b12a59M%216""r+   Fpatternexample_inputs.is_cudac                    |rt          d |D                       }t          | ||          }|j                                         |                                 |j        j        D ]c}|j        dk    rV|j        t          j	        j
        j        j        k    r2t          |j                  dk    r|j                            |           d|j                                         |                                 |S )zF
    Convert the pattern to an FX graph with decomposed aten ops.
    c                 n    g | ]2}t          |t          j                  r|                                n|3S  )r$   r   Tensorcuda)r   r@   s     r)   
<listcomp>z6_get_aten_graph_module_for_pattern.<locals>.<listcomp>u  s5    TTTAu|44;QVVXXX!TTTr+   r/   r   )r   r
   r   r   r   r   r1   r#   r   r   r9   copy_r;   rK   rD   r   )r   r   r   r2   aten_patternr7   s         r)   "_get_aten_graph_module_for_patternr   j  s     
TT^TTT
 
 . L
 **,,, "( 0 0G&&uy~3;;;DJ1$$))$///**,,,r+   match_patternc                    t           j        j        j        j        t           j        j        j        t           j        j        j        j        t           j        j        j        t           j        j        j        j        t           j        j        j        t           j        j        j        j        t           j        j        j        t           j        j        j        j        t           j        j        j        t           j        j        j        j        t           j        j        j        t           j        j        j        j        t           j        j        j        t           j        j        j	        j        t           j        j        j	        t           j        j
        j        j        t           j        j
        j        i	}| j        j        D ])}|j        dk    r|j        |v r||j                 |_        *dS )zRemove .tensor overload for quantize/dequantize ops so that we can
    use the match_pattern that we get from torchdynamo export to match the output of convert_pt2e
    r/   N)r   r   r    quantize_per_tensorr;   dequantize_per_tensorr"   tensor2quantize_per_channeldequantize_per_channelr9   clampr   r   r   r1   r#   )r   _MAPr4   s      r)   r   r     s-   
 		&:BEIDbDv	&<DeiFdFz	&:A59CaCu	&<CUYEcEy	&:BEIDbDv	&<DeiFdFz	&;CUYEcEx	&=EuyGeG|	#UY^%9
D  & & &4?""8tAH~AH	& &r+   c                     t          | t          t          f          rdS t          | t          t          f          r"t          t          t          |                     S dS )NTF)r$   intfloatr   rB   allmap_is_literal)args    r)   r   r     sP    #U|$$ t#t}%% *3{C(()))5r+   gm	merge_dupexclude_literalsc           	         d}d}i }|g }| j         }|j        d         }| j        j        D ]&}|j        dk    r|}|dz  }| j                            |          5  g }	|j        D ]}
t          |
          r|
|vr|r |
|v r|	                    ||
                    7| j        	                    dt          |          z             }|	                    |           |j                            t                                 |dz  }|r|||
<   |	                    |
           t          |	          }	ddd           n# 1 swxY w Y   |	|_        (|                                 |                                 | S )a  Replace the literals in the graph with placeholder nodes that's created on the fly while we
    traverse the graph, so that the literal arguments in the graph can be matched and replaced

    To use this, the pattern and replacement graph should have the exact same number of literal args
    and they should be used in the exact same order in the pattern and replacement graph.

    If the literal arguments are not used in the same order in pattern and replacement graph, please
    use `_replace_literals_with_existing_placeholders` instead

    Args:
        `gm`: input GraphModule that we'll transform
        `merge_dup`: boolean flag to indicate that if the same literal appears multiple times in
         the graph, whether they should correspond to the same placeholder or not
        `exclude_literals`: a list of literals that will not be replaced with placeholders

    Example:

    # 1. Original Graph
    def pattern(self, x):
        return x + 3

    def replacement(self, x):
        return x - 3

    example_inputs = (torch.randn(1, 3, 3, 3),)
    pattern_gm = _get_aten_graph_module_for_pattern(pattern, example_inputs)
    replacement_gm = _get_aten_graph_module_for_pattern(pattern, example_inptus)

    # 2. Before calling replace literals we'll see the following graph:
    def pattern(self, x):
        return x + 3

    def replacement(self, x):
        return x - 3

    pattern_gm = _replace_literals_with_new_placeholders(pattern_gm)
    replacement_gm = _replace_literals_with_new_placeholders(replacement_gm)

    # 3. After replacing literals with new placeholder nodes

    def pattern(self, x, new_ph):
        return x + new_ph

    def pattern(self, x, new_ph):
        return x - new_ph

    Nr   placeholderr   r   )_in_specchildren_specsr   r   r1   inserting_afterr%   r   r   r   r   r   r   __post_init__)r   r   r   last_phcntliteral_to_phin_spec	args_specr7   new_argsr   ph_nodes               r)   '_replace_literals_with_new_placeholdersr     s   h G
CFHMkG&q)I  7m##G1HCX%%g.. 	' 	'Hy ) )s## )3C(C(C  9SM%9%9 c(:;;;;"$("6"6us3xx7G"H"H 000!077

CCCq$ 918M#.OOC((((XH	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	' 	'" 		 Is   CD??E	E	literal_to_ph_idxc                 `   |g }|i }d | j         j        D             }| j         j        D ]}|j        dk    rg }|j        D ]T}t	          |          r.||vr*||v r&||         }||         }|                    |           ?|                    |           Ut          |          }||_        | S )a	  Replace the literals in the graph with **existing** placeholder nodes, so that the literal arguments
    in the graph can be matched and replaced

    To use this, all literal args in the graph should be unique and each of them should correspond
    to exactly one placeholder node

    # 1. Original Graph
    def pattern(self, x_i8, scale, zero_point, quant_min, quant_max):
        return torch.dequantize_per_tensor(x_i8, scale, zero_point, quant_min, quant_max)

    def replacement(x_i8, scale, zero_point, quant_min, quant_max):
        x_i8 = torch.clamp(x_i8, quant_min, quant_max)
        return ((x_i8.to(torch.float32) - zero_point) * scale).to(dtype=torch.float32)

    example_inputs = (
        torch.randn(1, 3, 3, 3),
        1.0,
        0,
        -128,
        127,
    )
    pattern_gm = _get_aten_graph_module_for_pattern(pattern, example_inputs)
    replacement_gm = _get_aten_graph_module_for_pattern(pattern, example_inptus)

    # 2. Before calling replace literals we'll see the following graph:
    def pattern(self, x_i8, scale, zero_point, quant_min, quant_max):
        # scale/zero_point/quant_min/quant_max are burnt in since they are scalar values
        return torch.dequantize_per_tensor(x_i8, 1.0, 0, -128, 127)

    def replacement(x_i8, scale, zero_point, quant_min, quant_max):
        # scale/zero_point/quant_min/quant_max are burnt in since they are scalar values
        x_i8 = torch.clamp(x_i8, -128, 127)
        return ((x_i8.to(torch.float32) - 0) * 1.0).to(dtype=torch.float32)

    # Note that literal args appear in different order in pattern and replacement graph, so
    # we can't use _replace_literals_with_new_placeholders

    literal_to_ph_idx = {1.0: 1, 0: 2, -128: 3, 127: 4}
    pattern_gm = _replace_literals_with_existing_placeholders(pattern_gm, literal_to_ph_idx)
    replacement_gm = _replace_literals_with_existing_placeholders(replacement_gm, literal_to_ph_idx)

    # 3. After replacing literals with existing placeholder nodes

    def pattern(self, x_i8, scale, zero_point, quant_min, quant_max):
        # scale/zero_point/quant_min/quant_max are burnt in since they are scalar values
        return torch.dequantize_per_tensor(x_i8, scale, zero_point, quant_min, quant_max)

    def replacement(x_i8, scale, zero_point, quant_min, quant_max):
        # scale/zero_point/quant_min/quant_max are burnt in since they are scalar values
        x_i8 = torch.clamp(x_i8, quant_min, quant_max)
        return ((x_i8.to(torch.float32) - zero_point) * scale).to(dtype=torch.float32)
    Nc                 (    g | ]}|j         d k    |S )r   )r1   )r   r7   s     r)   r   z@_replace_literals_with_existing_placeholders.<locals>.<listcomp>F  s$    
G
G
GDdg.F.F4.F.F.Fr+   r/   )r   r   r1   r%   r   r   r   )	r   r   r   phsr7   r   r   ph_idxr   s	            r)   ,_replace_literals_with_existing_placeholdersr     s    r  
G
GBHN
G
G
GC  7o%%9 
	% 
	%CC  	%///,,,*3/f+(((($$$$??		Ir+   c                     dddt           ffd}ddt           ffd}t          j        ||           | _        t          j        ||           | _        | S )z
    Disallow calling `model.train()` or `model.eval()` on the given GraphModule.
    This is useful for exported models, where these methods don't actually behave as expected.
    ah  
        Calling train() or eval() is not supported for exported models.
        Please call `torch.ao.quantization.move_exported_model_to_train(model)` (or eval) instead.

        If you cannot replace the calls to `model.train()` and `model.eval()`, you may override
        the behavior for these methods by calling `torch.ao.quantization.allow_exported_model_train_eval(model)`,
        which does the above automatically for you. Note that this has limited effect on switching
        behavior between train and eval modes, and should be used only for special ops such as dropout
        and batchnorm.
        Tmodec                 "    t                    r]   NotImplementedErrorselfr   error_messages     r)   _trainz$_disallow_eval_train.<locals>._trainn      !-000r+   c                 "    t                    r]   r   r   s     r)   _evalz#_disallow_eval_train.<locals>._evalq  r   r+   )T)booltypes
MethodTypetraineval)r   r   r   r   s      @r)   _disallow_eval_trainr  ^  s    
	M1 14 1 1 1 1 1 11 1$ 1 1 1 1 1 1 "6511EK!%//EJLr+   )F)FNr0   )Jr   r   typingr   r   r   r   r   r   r	   r   torch.nn.functionalnn
functionalr|   torch._exportr
   $torch.ao.quantization.fx._decomposedr   torch.ao.quantization.quantizerr   torch.export.unflattenr   r   torch.fxr   r   torch.nn.utils.fusionr   torch.utils._pytreer   __all__r   r    r   r;   r"   r   r   r   r   r   randn_conv1d_bn_example_inputs_conv2d_bn_example_inputsr&   r   r*   r6   r=   rF   rL   r[   rf   rm   rr   rw   ry   r}   r   r   r   r   r   r   r   r   r   r   r   r   dtyper   r  r   r+   r)   <module>r     s
     D D D D D D D D D D D D D D D D D D           4 4 4 4 4 4 J I I I I I B B B B B B : : : : : : : : & & & & & & & & 6 6 6 6 6 6 ( ( ( ( ( ( %( 
I"6>	I"6=	I"7? 
I"8@	I"8?	I"9A EK1aEK1aEKNNEKNNEKNNEKNNEKNN  EK1aEK1aEKNNEKNNEKNNEKNNEKNN %(- ux}     "%X]%"'(-%
38_% % % %PD     43F    
%;       	 	 	( ( ( ( ("T    	t 	 	 	 	:t : : : :?8 ? ? ? ?4    ^$^$^$ TN^$ 	^$
 ^$ 
^$ ^$ ^$ ^$Dk d    2
; 
4U39=M8M3N 
 
 
 
  " ""#s(O" "
 " " " "J&k &d & & & &,   ,0W WWW tCy)W W W Wx -1SWR RRtCy)R  U5#tU[+H%I3%N OPR R R Rn      r+   