B
    #=6\65                 @   sJ  d dl mZ d dl mZ d dl mZ d dl 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 d d
lZd d
lZd d
lZd d
lZd dlmZmZmZmZ dZdZd0ddZdd Zdd Zd1ddZdd Z dd Z!dd Z"dd Z#dd Z$d d! Z%d"d# Z&G d$d% d%e'Z(d&d' Z)d(d) Z*d2d*d+Z+d,d- Z,d.d/ Z-d
S )3    )absolute_import)division)print_function)unicode_literals)
caffe2_pb2)container_abcs)	viewitems)DecodeErrorMessage)text_formatN)integer_typesbinary_type	text_typestring_typesZoptimizer_iterationZiteration_mutexc                s\    pg  t  ts g tdd  D s8td  fdd}|| } ||}| |kS )zM
    Two ops are identical except for each field in the `ignore_fields`.
    c             s   s   | ]}t |tV  qd S )N)
isinstancer   ).0f r   6/tmp/pip-install-l3r2oljg/torch/caffe2/python/utils.py	<genexpr>    s    z OpAlmostEqual.<locals>.<genexpr>z*Expect each field is text type, but got {}c                s0   t | } x  D ]}| |r| | qW | S )N)copydeepcopyHasFieldZ
ClearField)opfield)ignore_fieldsr   r   clean_op#   s
    


zOpAlmostEqual.<locals>.clean_op)r   listallAssertionErrorformat)Zop_aZop_br   r   r   )r   r   OpAlmostEqual   s    
r!   c             C   sP   | j dkr0tj| jtjd| j | j| j| jS tj| jtjd| j	j
S d S )Nr   )dtype)numnpasarraydatafloat32reshapeZchannelsheightwidthshapeZdim)Zblobr   r   r   CaffeBlobToNumpyArray/   s
    
r,   c             C   s0  | j tjjkr(tj| jtjd| j	S | j tjj
krPtj| jtjd| j	S | j tjjkrxtj| jtjd| j	S | j tjjkrtj| jtjd| j	S | j tjjkrtj| jtjd| j	S | j tjjkrtj| jtjd| j	S | j tjjkrtj| jtjd| j	S tdt| j  d S )N)r"   z$Tensor data type not supported yet: )	data_typer   TensorProtoFLOATr$   r%   
float_datar'   r(   dimsDOUBLEdouble_datafloat64INT32
int32_dataintINT16int16UINT16uint16INT8int8UINT8uint8RuntimeErrorstr)tensorr   r   r   Caffe2TensorToNumpyArray:   s.    rC   c             C   s  t  }|j| j |r ||_| jtjkrTt jj	|_
|jt|  t n^| jtjkrt jj|_
|jt|  tj n(| jtjks| jtjkrt jj|_
|j|  tj  n| jtjkrt jj|_
|jt|  tj n| jtjkr4t jj|_
|jt|  tj n~| jtjkrjt jj|_
|jt|  tj nH| jtjkrt jj|_
|jt|  tj nt dt!| j |S )Nz#Numpy data type not supported yet: )"r   r.   r1   extendr+   namer"   r$   r'   r/   r-   r0   r   flattenZastypefloatr4   r2   r3   r7   Zint32r5   r6   tolistr9   r8   r;   r:   r=   r<   r?   r>   r@   rA   )ZarrrE   rB   r   r   r   NumpyArrayToCaffe2TensorV   s8    

 




rI   c          	   C   sR  t  }| |_t|tj}t|tjrL|jj	tj
krL|j|   |S t|tjrf|  }nt|tjr|t|}t	|tkr||_nt	|tkst	|tkr||_nt|tr||_nt|tr|d|_nlt|t jr|j| nPt|tr| |_n6|rLtdd |D rL|jdd |D  n|r~tdd |D r~|j dd |D  n|rtdd |D r|j!dd |D  n|rtd	d |D r|j"| nv|r
td
d |D r
|j!dd |D  nD|r8t#d$| |t	|t%dd |D nt#d$| |t	||S )z*Makes an argument based on the value type.zutf-8c             s   s    | ]}t |ttjgkV  qd S )N)typerG   r$   float_)r   vr   r   r   r      s    zMakeArgument.<locals>.<genexpr>c             s   s(   | ] }t |tjkr| n|V  qd S )N)rJ   r$   rK   item)r   rL   r   r   r   r      s    c             s   s,   | ]$}t |tkp"t |ttjgkV  qd S )N)rJ   r   boolr$   int_)r   rL   r   r   r   r      s    c             s   s(   | ] }t |tjkr| n|V  qd S )N)rJ   r$   rO   rM   )r   rL   r   r   r   r      s    c             s   s"   | ]}t |tpt |tV  qd S )N)r   r   r   )r   rL   r   r   r   r      s    c             s   s&   | ]}t |tr|d n|V  qdS )zutf-8N)r   r   encode)r   rL   r   r   r   r      s   c             s   s   | ]}t |tjV  qd S )N)r   r   NetDef)r   rL   r   r   r   r      s    c             s   s   | ]}t |tV  qd S )N)r   r
   )r   rL   r   r   r   r      s    c             s   s   | ]}|  V  qd S )N)SerializeToString)r   rL   r   r   r   r      s    zBUnknown iterable argument type: key={} value={}, value type={}[{}]c             s   s   | ]}t |V  qd S )N)rJ   )r   rL   r   r   r   r      s    z5Unknown argument type: key={} value={}, value type={})&r   ZArgumentrE   r   r   Iterabler$   Zndarrayr"   rJ   r'   ZfloatsrD   rF   rH   ZgenericZasscalarrG   r   r   rN   ir   sr   rP   rQ   nZCopyFromr
   rR   r   intsstringsnets
ValueErrorr    set)keyvalueargumentiterabler   r   r   MakeArgumentw   s\    





"r`   c             C   s<   |  }yt || |S  t jk
r6   || |S X dS )a,  Reads a protobuffer with the given proto class.

    Inputs:
      cls: a protobuffer class.
      s: a string of either binary or text protobuffer content.

    Outputs:
      proto: the protobuffer of cls

    Throws:
      google.protobuf.message.DecodeError: if we cannot decode the message.
    N)r   Parse
ParseErrorZParseFromString)clsrU   objr   r   r   TryReadProtoWithClass   s    
re   c             C   s.   x(t |D ]\}}t| |kr
|| S q
W dS )zNGets a specific field from a protocol buffer that matches the given class
    N)r   rJ   )rd   function_maprc   funcr   r   r   GetContentFromProto   s    rh   c          	   C   sL   xFt |D ]2\}}yt|| }||S  tk
r:   w
Y q
X q
W tdd S )Nz$Cannot find a fit protobuffer class.)r   re   r	   )rU   rf   rc   rg   rd   r   r   r   GetContentFromProtoString   s    
ri   c          	   C   s:   t | t| }t|d}||  W dQ R X dS )z:Convert a text file of the given protobuf class to binary.wN)re   openreadwriterR   )Zproto_classfilenameZout_filenameprotoZfidr   r   r   ConvertProtoToBinary   s    rp   c           
   C   s   ddl m} m} | |jdg dg|| jdd | d}|dddf |dddf t	|dddf t	|dddf dS )	z|Get GPU memory usage stats from CUDAContext/HIPContext. This requires flag
       --caffe2_gpu_memory_tracking to be enabledr   )	workspacecoreZGetGPUMemoryUsageZ____mem____)device_optionN   )Ztotal_by_gpuZ
max_by_gputotalZ	max_total)
caffe2.pythonrq   rr   RunOperatorOnceCreateOperatorDeviceOptionZGpuDeviceTypeZ	FetchBlobr$   sum)rq   rr   br   r   r   GetGPUMemoryUsageStats   s    
r|   c          	   C   s<   ddl m}m} ||jdt| t| |tjd d S )Nr   )rq   rr   ZFree)rs   )	rv   rq   rr   rw   rx   r   ry   r   CPU)Zblobsrq   rr   r   r   r   
ResetBlobs  s    r~   c               @   s   e Zd ZdZedd ZdS )	DebugModea=  
    This class allows to drop you into an interactive debugger
    if there is an unhandled exception in your python script

    Example of usage:

    def main():
        # your code here
        pass

    if __name__ == '__main__':
        from caffe2.python.utils import DebugMode
        DebugMode.run(main)
    c             C   sl   y| S  t k
r    Y nL tk
rf   dd l}td tt d  t |  td  Y nX d S )Nr   zjEntering interactive debugger. Type "bt" to print the full stacktrace. Type "help" to see command listing.rt   )KeyboardInterrupt	Exceptionpdbprintsysexc_infoZpost_mortemexit)rc   rg   r   r   r   r   run   s    
zDebugMode.runN)__name__
__module____qualname____doc__classmethodr   r   r   r   r   r     s   r   c             C   s   | |krt d|| |d S )Nz{}. {} != {})r   r    )ar{   msgr   r   r   raiseIfNotEqual4  s    r   c                s   t   fdd}|S )z
    Use this method to decorate your function with DebugMode's functionality

    Example:

    @debug
    def test_foo(self):
        raise Exception("Bar")

    c                 s    fdd}t |S )Nc                  s
    S )Nr   r   )argsr   kwargsr   r   rg   G  s    z$debug.<locals>.wrapper.<locals>.func)r   r   )r   r   rg   )r   )r   r   r   wrapperE  s    zdebug.<locals>.wrapper)	functoolswraps)r   r   r   )r   r   debug9  s    r   c          	   C   s   |dk	r|nt }|dk	r|nt}ddlm} | |s||tj@ | j	g |dg||j
jd}| g |g}|||g|g W dQ R X n
| |}|S )z
    Often, a mutex guarded iteration counter is needed. This function creates a
    mutex iter in the net uniquely (if the iter already existing, it does
    nothing)

    This function returns the iter blob
    Nr   )rr   rt   )r+   r]   r"   )OPTIMIZER_ITERATION_NAMEITERATION_MUTEX_NAMErv   rr   ZBlobIsDefinedZDeviceScopery   r   r}   ZConstantFillZDataTypeZINT64ZCreateMutexZ
AtomicIterZ
GetBlobRef)Zinit_netnetiterZ
iter_mutexZiter_valrr   	iterationr   r   r   BuildUniqueMutexIterN  s    

r   c          
      s   t | t ksti  xnt| D ]b}|| krt| |ttr  ksxtd| | fdd D d  |< qW  S )Nz<Failed to resolve {} as Enum: duplicate entries {}={}, {}={}c                s   g | ]} | kr|qS r   r   )r   r\   )enumrL   r   r   
<listcomp>|  s    z$EnumClassKeyVals.<locals>.<listcomp>r   )	rJ   r   diruppergetattrr   r   valuesr    )rc   kr   )r   rL   r   EnumClassKeyValsp  s    

$r   c             C   s   i }x| D ]}| dsq
x|jjD ]n}|jdkr4q$|j|jkrb| |jrbt||j||j< P q$|j|jkr$t||j}t|dkr$|||j< P q$W d||j< q
W |S )z
    Convert a list of arguments to a name, value dictionary. Assumes that
    each argument has a name. Otherwise, the argument is skipped.
    rE   r   N)	r   Z
DESCRIPTORfieldsrE   labelZLABEL_OPTIONALr   ZLABEL_REPEATEDlen)r   Zansargdlist_r   r   r   
ArgsToDict  s"    



r   )N)N)NNr   ).
__future__r   r   r   r   Zcaffe2.protor   Zcaffe2.python.compatibilityr   Zfuture.utilsr   Zgoogle.protobuf.messager	   r
   Zgoogle.protobufr   r   r   r   Znumpyr$   sixr   r   r   r   r   r   r!   r,   rC   rI   r`   re   rh   ri   rp   r|   r~   objectr   r   r   r   r   r   r   r   r   r   <module>   sD   

!H$  
