U
    /e)                     @  s>  d dl mZ d dlZd dlmZmZ d dlmZ d dlm	Z	 d dl
mZ d dlZzd dlZW n ek
rt   dZY nX G dd deZG d	d
 d
e	ZG dd de	ZedkrejnejadadZdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Z d d! Z!d"d# Z"d$d% Z#d&d' Z$d(d) Z%d*d+ Z&dS ),    )annotationsN)IntEnumauto)uname)
NamedTuple)parsec                   @  s0   e Zd Ze Ze Ze Ze Ze Ze Z	dS )	NVMLStateN)
__name__
__module____qualname__r   UNINITIALIZEDINITIALIZEDDISABLED_PYNVML_NOT_AVAILABLEDISABLED_CONFIGDISABLED_LIBRARY_NOT_FOUND DISABLED_WSL_INSUFFICIENT_DRIVER r   r   @/tmp/pip-unpacked-wheel-g426oqom/distributed/diagnostics/nvml.pyr      s   r   c                   @  s2   e Zd ZU dZded< dZded< dZded< dS )CudaDeviceInfoNzbytes | Noneuuidz
int | Nonedevice_index	mig_index)r	   r
   r   r   __annotations__r   r   r   r   r   r   r   !   s   
r   c                   @  s"   e Zd ZU ded< dZded< dS )CudaContextboolhas_contextNzCudaDeviceInfo | Nonedevice_info)r	   r
   r   r   r   r   r   r   r   r   '   s   
r   z512.15c                   C  s   t tjkott kS )z&Is pynvml initialized on this process?)
NVML_STATEr   r   NVML_OWNER_PIDosgetpidr   r   r   r   is_initialized;   s    r!   c                   C  s   dt  jkS )zCheck if we are in Windows Subsystem for Linux; some PyNVML queries are not supported there.
    Taken from https://www.scivision.dev/python-detect-wsl/
    zmicrosoft-standard)r   releaser   r   r   r   _in_wsl@   s    r#   c               
   C  s  t tjtjtjtjhkrdS t tjkr6tt	 kr6dS t tj
krVtjdsVtja dS t tjkrltt	 ksxt tj
k rzt  W n( tjtjtjfk
r   tja Y dS X t rtt  ttk rtja dS ddlm}  tja t	 a|   ntdt dtddS )zIdempotent (per-process) initialization of PyNVML

    Notes
    -----

    Modifies global variables NVML_STATE and NVML_OWNER_PIDNzdistributed.diagnostics.nvmlr   add_gpu_metricsz+Unhandled initialisation state (NVML_STATE=z, NVML_OWNER_PID=))r   r   r   r   r   r   r   r   r   r    r   daskconfiggetpynvmlZnvmlInitZNVMLError_LibraryNotFoundZNVMLError_DriverNotLoadedZNVMLError_Unknownr#   parse_versionZnvmlSystemGetDriverVersiondecodeMINIMUM_WSL_VERSIONZdistributed.workerr%   RuntimeErrorr$   r   r   r   	init_onceG   sV    	

r/   c                   C  s   t   t sdS t S d S )Nr   )r/   r!   r*   ZnvmlDeviceGetCountr   r   r   r   device_get_count}   s    r0   c                  C  s   t  } ttjkrtdnttjkr.tdnttjkrJtdt dnlttjkr^tdnX| dkrptdnFz"t	t
ttjdd	d
}W n tk
r   d}Y nX t|S d S )Nz8NVML monitoring requires PyNVML and NVML to be installedz$PyNVML is installed, but NVML is notz3Outdated NVIDIA drivers for WSL, please upgrade to z	 or newerzKPyNVML monitoring disabled by 'distributed.diagnostics.nvml' config settingr   zNo GPUs availableZCUDA_VISIBLE_DEVICES ,)r0   r   r   r   r.   r   r   r-   r   nextmapintr   environr)   split
ValueErrorr*   nvmlDeviceGetHandleByIndex)countZgpu_idxr   r   r   _pynvml_handles   s,    








r;   c                 C  s8   t   ttdrt| }n
t| }tdd |D S )a)  Check whether the current process is same as that of handle

    Parameters
    ----------
    handle : pyvnml.nvml.LP_struct_c_nvmlDevice_t
        NVML handle to CUDA device

    Returns
    -------
    out : bool
        Whether the device handle has a CUDA context on the running process.
    'nvmlDeviceGetComputeRunningProcesses_v2c                 s  s   | ]}t  |jkV  qd S N)r   r    pid).0procr   r   r   	<genexpr>   s     z+_running_process_matches.<locals>.<genexpr>)r/   hasattrr*   r<   Z$nvmlDeviceGetComputeRunningProcessesany)handleZrunning_processesr   r   r   _running_process_matches   s
    

rE   c               
   C  s  t   t rtt D ]} t| }zt|\}}W n tjk
rR   tj}Y nX |tj	krtt
|D ]`}zt||}W n tjk
r   Y qlY nX t|rlt|}tdt|| |dd    S qlqt|rt|}tdt|| dd  S qtddS )aK  Check whether the current process already has a CUDA context created.

    Returns
    -------
    out : CudaContext
        Object containing information as to whether the current process has a CUDA
        context created, and in the positive case containing also information about
        the device the context belongs to.
    T)r   r   r   )r   r   r   r   F)r   )r/   r!   ranger0   r*   r9   nvmlDeviceGetMigModeNVMLError_NotSupportedZNVML_DEVICE_MIG_DISABLEZNVML_DEVICE_MIG_ENABLEZnvmlDeviceGetMaxMigDeviceCountZ#nvmlDeviceGetMigDeviceHandleByIndexZNVMLError_NotFoundrE   nvmlDeviceGetUUIDr   r   )indexrD   Zmig_current_modeZmig_pending_moder   Z
mig_handler   r   r   r   has_cuda_context   sD    


 

  

rL   c                 C  s~   t   z t| }t|}t|}W nJ tk
rp   t| trD| nt| d}t|}t	|}t|}Y nX t
||dS )a`  Get both device index and UUID from device index or UUID

    Parameters
    ----------
    device : int, bytes or str
        An ``int`` with the index of a GPU, or ``bytes`` or ``str`` with the UUID
        of a CUDA (either GPU or MIG) device.

    Returns
    -------
    out : CudaDeviceInfo
        Object containing information about the device.

    Examples
    --------
    >>> get_device_index_and_uuid(0)  # doctest: +SKIP
    {'device-index': 0, 'uuid': b'GPU-e1006a74-5836-264f-5c26-53d19d212dfe'}

    >>> get_device_index_and_uuid('GPU-e1006a74-5836-264f-5c26-53d19d212dfe')  # doctest: +SKIP
    {'device-index': 0, 'uuid': b'GPU-e1006a74-5836-264f-5c26-53d19d212dfe'}

    >>> get_device_index_and_uuid('MIG-7feb6df5-eccf-5faa-ab00-9a441867e237')  # doctest: +SKIP
    {'device-index': 0, 'uuid': b'MIG-7feb6df5-eccf-5faa-ab00-9a441867e237'}
    utf-8rF   )r/   r5   r*   r9   rJ   r8   
isinstancebytesnvmlDeviceGetHandleByUUIDZnvmlDeviceGetIndexr   )devicer   Zdevice_handler   Zuuid_handler   r   r   get_device_index_and_uuid   s    


rR   c                 C  s   t   zt| }t|}W n6 tk
rR   t| tr:| nt| d}t|}Y nX zt|W S  tj	k
r~   ddg Y S X dS )aX  Get MIG mode for a device index or UUID

    Parameters
    ----------
    device: int, bytes or str
        An ``int`` with the index of a GPU, or ``bytes`` or ``str`` with the UUID
        of a CUDA (either GPU or MIG) device.

    Returns
    -------
    out : list
        A ``list`` with two integers ``[current_mode, pending_mode]``.
    rM   r   N)
r/   r5   r*   r9   r8   rN   rO   rP   rH   rI   )rQ   r   rD   r   r   r   r   get_device_mig_mode  s    rS   c                 C  s,   zt | jW S  t jk
r&   Y d S X d S r=   )r*   ZnvmlDeviceGetUtilizationRatesZgpurI   hr   r   r   _get_utilization(  s    rV   c                 C  s,   zt | jW S  t jk
r&   Y d S X d S r=   )r*   nvmlDeviceGetMemoryInfousedrI   rT   r   r   r   _get_memory_used/  s    rY   c                 C  s,   zt | jW S  t jk
r&   Y d S X d S r=   )r*   rW   totalrI   rT   r   r   r   _get_memory_total6  s    r[   c                 C  s.   zt |  W S  t jk
r(   Y d S X d S r=   )r*   ZnvmlDeviceGetNamer,   rI   rT   r   r   r   	_get_name=  s    r\   c                  C  s   t  } t| t| dS )N)Zutilizationzmemory-used)r;   rV   rY   rT   r   r   r   	real_timeD  s    r]   c                  C  s   t  } t| t| dS )N)zmemory-totalname)r;   r[   r\   rT   r   r   r   one_timeL  s    r_   )'
__future__r   r   enumr   r   platformr   typingr   Zpackaging.versionr   r+   r'   r*   ImportErrorr   r   r   r   r   r   r   r-   r!   r#   r/   r0   r;   rE   rL   rR   rS   rV   rY   r[   r\   r]   r_   r   r   r   r   <module>   sD   
	6-)