B
    d*                 @   s  d Z ddlZddlZddlmZ ddlZddlmZ yeddgZW n   dZY nX G dd de	Z
e
 ZdZdZG d	d
 d
e	Zg Zdd Zdd ZG dd deZG dd deZG dd deZG dd deZedededediZdd e D ZeddZyee ZW n@ ek
rV Z z eded e!e"eW ddZ[X Y nX G d d! d!eZe Zee_#eee< d"d# Z$i Z%d$d% Z&d&d' Z'd(d) Z(d*d+ Z)d,d- Z*G d.d/ d/e+Z,dS )0zX
This modules provides python contexts that set the default behavior for PyCBC
objects.
    N)wraps   )get_ctypes_libraryZgompc               @   s0   e Zd ZdZdd Zdd Zdd Zdd	 ZdS )
_SchemeManagerNc             C   s(   t jd k	rtd| t _d | _d| _d S )Nz SchemeManager is a private classF)r   _singleRuntimeErrorstate_lock)self r   Y/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/pycbc/scheme.py__init__.   s
    
z_SchemeManager.__init__c             C   s
   d| _ d S )NT)r	   )r
   r   r   r   lock7   s    z_SchemeManager.lockc             C   s
   d| _ d S )NF)r	   )r
   r   r   r   unlock:   s    z_SchemeManager.unlockc             C   s   | j dkr|| _ntdd S )NFz)The state is locked, cannot shift schemes)r	   r   r   )r
   r   r   r   r   shift_to=   s    
z_SchemeManager.shift_to)__name__
__module____qualname__r   r   r   r   r   r   r   r   r   r   +   s
   	r   c               @   s4   e Zd ZdZdZdd Zdd Zdd Zd	d
 ZdS )Schemez7Context that sets PyCBC objects to use CPU processing. Nc             C   s,   t t| krd S tjd k	r"tddt_d S )Nz&Only one processing scheme can be usedT)DefaultSchemetyper   r   r   )r
   r   r   r   r   L   s
    
zScheme.__init__c             C   s   t |  t   d S )N)mgrr   r   )r
   r   r   r   	__enter__R   s    
zScheme.__enter__c             C   s   t   t t d S )N)r   r   r   default_context)r
   r   value	tracebackr   r   r   __exit__U   s    zScheme.__exit__c             C   s   t d k	rd t _d S )N)r   r   )r
   r   r   r   __del__X   s    zScheme.__del__)	r   r   r   __doc__r   r   r   r   r   r   r   r   r   r   I   s   r   c             C   s   t |  d S )N)_cuda_cleanup_listappend)functionr   r   r   register_clean_cuda^   s    r"   c             C   s:   t   xt D ]
}|  qW |   ddlm} |  d S )Nr   )clear_context_caches)r   reversepopZpycuda.toolsr#   )contextfuncr#   r   r   r   
clean_cudaa   s    

r(   c               @   s   e Zd ZdZdddZdS )
CUDASchemezAContext that sets PyCBC objects to use a CUDA processing scheme. r   c             C   sh   t |  tjstddd l}|j  |j|| _	| j	j
|jjjd| _dd l}|t| j d S )Nz%Install PyCUDA to use CUDA processingr   )flags)r   r   pycbcZ	HAVE_CUDAr   Zpycuda.driverZdriverinitZDeviceZdeviceZmake_contextZ	ctx_flagsZSCHED_BLOCKING_SYNCr&   atexitregisterr(   )r
   Z
device_numZpycudar-   r   r   r   r   p   s    

zCUDAScheme.__init__N)r   )r   r   r   r   r   r   r   r   r   r)   n   s   r)   c               @   s&   e Zd Zd	ddZdd Zdd ZdS )
	CPUSchemer   c             C   sL   t |tr|| _n6|dkr6dtjkr6ttjd | _ndd l}| | _d S )NenvZPYCBC_NUM_THREADSr   )
isinstanceintnum_threadsosenvironmultiprocessing	cpu_count)r
   r3   r6   r   r   r   r   |   s    
zCPUScheme.__init__c             C   s6   t |  t| jtjd< td k	r2tt| j d S )NOMP_NUM_THREADS)	r   r   strr3   r4   r5   _libgompomp_set_num_threadsr2   )r
   r   r   r   r      s    
zCPUScheme.__enter__c             C   s0   dt jd< td k	rtd t| ||| d S )N1r8   r   )r4   r5   r:   r;   r   r   )r
   r   r   r   r   r   r   r      s    

zCPUScheme.__exit__N)r   )r   r   r   r   r   r   r   r   r   r   r/   {   s   
	r/   c               @   s   e Zd ZdddZdS )	MKLSchemer   c             C   s   t | | tjstdd S )NzCan't find MKL libraries)r/   r   r+   ZHAVE_MKLr   )r
   r3   r   r   r   r      s    zMKLScheme.__init__N)r   )r   r   r   r   r   r   r   r   r=      s   r=   c               @   s   e Zd ZdS )NumpySchemeN)r   r   r   r   r   r   r   r>      s   r>   cudacpumklnumpyc             C   s   i | ]\}}||qS r   r   ).0kvr   r   r   
<dictcomp>   s    rF   ZPYCBC_SCHEMEz:PYCBC_SCHEME={!r} not recognised, please select one of: {}z, c               @   s   e Zd ZdS )r   N)r   r   r   r   r   r   r   r      s   r   c               C   s   t ttj S )N)scheme_prefixr   r   r   r   r   r   r   current_prefix   s    rH   c                s    fdd}|S )Nc                s   t   fdd}|S )Nc        	         s   yt tj   | |S  tk
r   g }xtjjjdd D ]}y(tt|   jgd}t	| j}W n2 t
tfk
r } z||g7 }w<W d d }~X Y nX tjt kri t tj< |t tj  < || |S W d}x|D ]}|t|7 }qW t|Y nX d S )Nr   )fromlistziFailed to find implementation of (%s)
                      for %s scheme." % (str(fn), current_prefix()))_import_cacher   r   KeyError	__class____mro__
__import__rG   r   getattrImportErrorAttributeErrorprintr   )	argskwdsZ
exc_errorsZschbackendZ
schemed_fneerrZemsg)r'   prefixr   r   _scheming_function   s(    



z>schemed.<locals>.scheming_function.<locals>._scheming_function)r   )r'   rZ   )rY   )r'   r   scheming_function   s    z"schemed.<locals>.scheming_functionr   )rY   r[   r   )rY   r   schemed   s    r\   c                s   t   fdd}|S )Nc                 s.   t ttjts ttjd n
 | |S d S )Nz1 can only be called from a CPU processing scheme.)
issubclassr   r   r   r/   	TypeErrorfnr   )rT   rU   )r'   r   r   _cpuonly   s    
zcpuonly.<locals>._cpuonly)r   )r'   r`   r   )r'   r   cpuonly   s    ra   c             C   sH   |  d}|jddtttt  d dd |jddd	td
 dS )z
    Adds the options used to choose a processing scheme. This should be used
    if your program supports the ability to select the processing scheme.

    Parameters
    ----------
    parser : object
        OptionParser instance
    z<Options for selecting the processing scheme in this program.z--processing-schemez-The choice of processing scheme. Choices are a  . (optional for CPU scheme) The number of execution threads can be indicated by cpu:NUM_THREADS, where NUM_THREADS is an integer. The default is a single thread. If the scheme is provided as cpu:env, the number of threads can be provided by the PYCBC_NUM_THREADS environment variable. If the environment variable is not set, the number of threads matches the number of logical cores. r@   )helpdefaultz--processing-device-idz6(optional) ID of GPU to use for accelerated processingr   )rb   rc   r   N)add_argument_groupadd_argumentr9   listsetrG   valuesr2   )parserZprocessing_groupr   r   r   insert_processing_option_group   s    


rj   c             C   s   | j d}|d }|dkr2td t| j}n|dkrt|dkrj|d }| r^t|}t	|d}nt	 }td|j
  nFt|dkr|d }| rt|}t|d}nt }td	|j
  |S )
a7  Parses the command line options and returns a precessing scheme.

    Parameters
    ----------
    opt: object
        Result of parsing the CLI with OptionParser, or any object with
        the required attributes.

    Returns
    -------
    ctx: Scheme
        Returns the requested processing scheme.
    :r   r?   zRunning with CUDA supportrA   r   )r3   z$Running with MKL support: %s threadsz$Running with CPU support: %s threads)processing_schemesplitlogginginfor)   Zprocessing_device_idlenisdigitr2   r=   r3   r/   )optZ
scheme_strnamectxZnumtr   r   r   from_cli  s*    
ru   c             C   s*   t  }| jdd |kr&|d dS )a%  Parses the  processing scheme options and verifies that they are
       reasonable.


    Parameters
    ----------
    opt : object
        Result of parsing the CLI with OptionParser, or any object with the
        required attributes.
    parser : object
        OptionParser instance.
    rk   r   z (%s) is not a valid scheme type.N)rG   rh   rl   rm   error)rr   ri   Zscheme_typesr   r   r   verify_processing_options-  s    rw   c               @   s   e Zd ZdZdd ZdS )ChooseBySchemeDictz This class represents a dictionary whose purpose is to chose objects
    based on their processing scheme. The keys are intended to be processing
    schemes.
    c             C   s6   x0|j dd D ]}yt| |S    Y qX qW d S )Nr   )rN   dict__getitem__)r
   schemebaser   r   r   r{   C  s     zChooseBySchemeDict.__getitem__N)r   r   r   r   r{   r   r   r   r   rx   >  s   rx   )-r   r4   r+   	functoolsr   rn   Zlibutilsr   r:   objectr   r   r   r   r   r   r"   r(   r)   r/   r=   r>   rG   itemsZ_scheme_mapgetenvZ_default_scheme_prefixZ_default_scheme_classrL   excr   formatjoinmapreprr   rH   rK   r\   ra   rj   ru   rw   rz   rx   r   r   r   r   <module>   s\   
&"
 (