Ë
    Fêñi“#  ã                  ó   — d dl mZ d dlZd dlmZ d dlmZ d dlmZ  G d„ d«      Z	e
dk(  r^d	Zd	Zd
Z e	«       Zej                  «        ej!                  eee¬«      xZr* ede› �«       eD � cg c]  } d| › �‘Œ	 c} Z ede› �«       yyyc c} w )é    )ÚannotationsN)ÚAny)ÚLOGGER)Úcheck_requirementsc                  óP   — e Zd ZdZd„ Zd„ Zd„ Zd„ Zd
d„Zd„ Z		 d	 	 	 	 	 	 	 dd„Z
y	)ÚGPUInfoak  Manages NVIDIA GPU information via pynvml with robust error handling.

    Provides methods to query detailed GPU statistics (utilization, memory, temp, power) and select the most idle GPUs
    based on configurable criteria. It safely handles the absence or initialization failure of the pynvml library by
    logging warnings and disabling related features, preventing application crashes.

    Includes fallback logic using `torch.cuda` for basic device counting if NVML is unavailable during GPU
    selection. Manages NVML initialization and shutdown internally.

    Attributes:
        pynvml (module | None): The `pynvml` module if successfully imported and initialized, otherwise `None`.
        nvml_available (bool): Indicates if `pynvml` is ready for use. True if import and `nvmlInit()` succeeded, False
            otherwise.
        gpu_stats (list[dict[str, Any]]): A list of dictionaries, each holding stats for one GPU, populated on
        initialization and by `refresh_stats()`. Keys include: 'index', 'name', 'utilization' (%), 'memory_used' (MiB),
            'memory_total' (MiB), 'memory_free' (MiB), 'temperature' (C), 'power_draw' (W), 'power_limit' (W or 'N/A').
            Empty if NVML is unavailable or queries fail.

    Methods:
        refresh_stats: Refresh the internal gpu_stats list by querying NVML.
        print_status: Print GPU status in a compact table format using current stats.
        select_idle_gpu: Select the most idle GPUs based on utilization and free memory.
        shutdown: Shut down NVML if it was initialized.

    Examples:
        Initialize GPUInfo and print status
        >>> gpu_info = GPUInfo()
        >>> gpu_info.print_status()

        Select idle GPUs with minimum memory requirements
        >>> selected = gpu_info.select_idle_gpu(count=2, min_memory_fraction=0.2)
        >>> print(f"Selected GPU indices: {selected}")
    c                ó$  — d| _         d| _        g | _        	 t        d«       t	        d«      | _         | j                   j                  «        d| _        | j                  «        y# t        $ r"}t        j                  d|› �«       Y d}~yd}~ww xY w)z?Initialize GPUInfo, attempting to import and initialize pynvml.NFznvidia-ml-py>=12.0.0ÚpynvmlTz1Failed to initialize pynvml, GPU stats disabled: )
r
   Únvml_availableÚ	gpu_statsr   Ú
__import__ÚnvmlInitÚrefresh_statsÚ	Exceptionr   Úwarning)ÚselfÚes     ú^/var/www/pod-logistic/pod-ai/venv/lib/python3.12/site-packages/ultralytics/utils/autodevice.pyÚ__init__zGPUInfo.__init__/   s€   € à"&ˆŒØ$)ˆÔØ/1ˆŒð	TÜÐ5Ô6Ü$ XÓ.ˆDŒKØ�K‰K× Ñ Ô"Ø"&ˆDÔØ×ÑÕ øÜò 	TÜ�N‰NÐNÈqÈcÐR×SÑSûð	Tús   —AA$ Á$	BÁ-B
Â
Bc                ó$   — | j                  «        y)z>Ensure NVML is shut down when the object is garbage collected.N)Úshutdown©r   s    r   Ú__del__zGPUInfo.__del__>   s   € à�‰�ó    c                óš   — | j                   r0| j                  r#	 | j                  j                  «        d| _         yyy# t        $ r Y Œw xY w)z%Shut down NVML if it was initialized.FN)r   r
   ÚnvmlShutdownr   r   s    r   r   zGPUInfo.shutdownB   sL   € à×Ò 4§;¢;ðØ—‘×(Ñ(Ô*ð #(ˆDÕð $/Ðøô ò Ùðús   š> ¾	A
Á	A
c                ó@  ‡ — g ‰ _         ‰ j                  r‰ j                  sy	 ‰ j                  j                  «       }‰ j                   j	                  ˆ fd„t        |«      D «       «       y# t        $ r)}t        j                  d|› �«       g ‰ _         Y d}~yd}~ww xY w)z5Refresh the internal gpu_stats list by querying NVML.Nc              3  ó@   •K  — | ]  }‰j                  |«      –— Œ y ­w)N)Ú_get_device_stats)Ú.0Úir   s     €r   ú	<genexpr>z(GPUInfo.refresh_stats.<locals>.<genexpr>S   s   øè ø€ Ò!YÀ $×"8Ñ"8¸×";Ñ!Yùs   ƒzError during device query: )	r   r   r
   ÚnvmlDeviceGetCountÚextendÚranger   r   r   )r   Údevice_countr   s   `  r   r   zGPUInfo.refresh_statsK   s}   ø€ àˆŒØ×"Ò"¨$¯+ª+Øð	 ØŸ;™;×9Ñ9Ó;ˆLØ�N‰N×!Ñ!Ó!YÄUÈ<ÓEXÔ!YÕYøÜò 	 Ü�N‰NÐ8¸¸Ð<Ô=ØˆD�N‰Nûð	 ús   £AA+ Á+	BÁ4BÂBc                óX  — | j                   j                  |«      }| j                   j                  |«      }| j                   j                  |«      }dddœd„}t	        | j                   dd«      }|| j                   j                  |«      |r|j                  nd|r|j                  dz	  nd|r|j                  dz	  nd|r|j                  dz	  nd || j                   j                  ||«       || j                   j                  |d¬«       || j                   j                  |d¬«      d	œ	S )
z"Get stats for a single GPU device.éÿÿÿÿé   )ÚdefaultÚdivisorc               ót   — 	  | |Ž }|dk7  rt        |t        t        f«      r||z  S |S # t        $ r |cY S w xY w)Nr)   )Ú
isinstanceÚintÚfloatr   )Úfuncr*   r+   ÚargsÚvals        r   Úsafe_getz+GPUInfo._get_device_stats.<locals>.safe_get^   sH   € ðÙ˜D�k�Ø)0°Aª¼*ÀSÌ3ÔPUÈ,Ô:W�s˜g‘~Ð`Ð]`Ð`øÜò Ø’ðús   ‚$) §) ©7¶7ÚNVML_TEMPERATURE_GPUé   iè  )r+   )	ÚindexÚnameÚutilizationÚmemory_usedÚmemory_totalÚmemory_freeÚtemperatureÚ
power_drawÚpower_limit)r
   ÚnvmlDeviceGetHandleByIndexÚnvmlDeviceGetMemoryInfoÚnvmlDeviceGetUtilizationRatesÚgetattrÚnvmlDeviceGetNameÚgpuÚusedÚtotalÚfreeÚnvmlDeviceGetTemperatureÚnvmlDeviceGetPowerUsageÚnvmlDeviceGetEnforcedPowerLimit)r   r6   ÚhandleÚmemoryÚutilr3   Ú	temp_types          r   r   zGPUInfo._get_device_statsX   sÿ   € à—‘×7Ñ7¸Ó>ˆØ—‘×4Ñ4°VÓ<ˆØ�{‰{×8Ñ8¸Ó@ˆà*,°aô 	ô ˜DŸK™KÐ)?ÀÓDˆ	ð Ø—K‘K×1Ñ1°&Ó9Ù'+˜4Ÿ8š8°Ù06˜6Ÿ;™;¨"Ò,¸BÙ28˜FŸL™L¨BÒ.¸bÙ06˜6Ÿ;™;¨"Ò,¸BÙ# D§K¡K×$HÑ$HÈ&ÐR[Ó\Ù" 4§;¡;×#FÑ#FÈÐX\Ô]Ù# D§K¡K×$OÑ$OÐQWÐaeÔfñ

ð 
	
r   c                óÎ  — | j                  «        | j                  st        j                  d«       y| j                  }t	        d„ |D «       «      }dd›ddd|› d	�›dd
d›ddd›ddd›ddd›�}t        j
                  d|› ddt        |«      z  › �«       |D ]¨  }|d   dk\  r	|d   d›d�nd}|d   dk\  r|d   d›d|d   d›�nd}|d   dk\  r|d   › d�nd}|d    dk\  r|d    d!›d|d"   d›�nd}t        j
                  |j                  d#«      d$›d|j                  d%d&«      d|› d	�›d|d›d|d›d|d›d|d›�«       Œª t        j
                  dt        |«      z  › d�«       y)'z?Print GPU status in a compact table format using current stats.zNo GPU stats available.Nc              3  óR   K  — | ]  }t        |j                  d d«      «      –— Œ! y­w)r7   úN/AN)ÚlenÚget)r    rD   s     r   r"   z'GPUInfo.print_status.<locals>.<genexpr>{   s    è ø€ ÒD°s”s˜3Ÿ7™7 6¨5Ó1×2ÑDùs   ‚%'ÚIdxz<3ú ÚNameú<Ú ÚUtilz>6z	Mem (MiB)z>15ÚTempz>5zPwr (W)z>10z
--- GPU Status ---
ú
ú-r8   r   ú%z N/A r9   ú/r:   z<6z N/A / N/A r<   ÚCr=   z>3r>   r6   z<3dr7   rQ   )r   r   r   r   ÚmaxÚinforR   rS   )	r   ÚstatsÚname_lenÚhdrrD   ÚuÚmÚtÚps	            r   Úprint_statuszGPUInfo.print_statuss   sß  € à×ÑÔØ�~Š~Ü�N‰NÐ4Ô5Øà—‘ˆÜÑD¸eÔDÓDˆØ�r�
˜!˜F 1 X J¨` ,Ð/¨q°¸°¸1¸[ÈÐ<MÈQÈvÐVXÈkÐYZÐ[dÐehÐZiÐjˆÜ�‰Ð,¨S¨E°°C¼#¸c»(±NÐ3CÐDÔEàò 	vˆCØ/2°=Ñ/AÀQÒ/F�3�}Ñ% bÐ)¨Ñ+ÈGˆAØGJÈ=ÑGYÐ]^ÒG^�3�}Ñ% bÐ)¨¨3¨~Ñ+>¸rÐ*BÑCÐdqˆAØ,/°Ñ,>À!Ò,C�3�}Ñ%Ð& aÑ(ÈˆAØEHÈÑEVÐZ[ÒE[�3�|Ñ$ RÐ(¨¨#¨mÑ*<¸RÐ)@ÑAÐahˆAä�K‰K˜3Ÿ7™7 7Ó+¨CÐ0°°#·'±'¸&À%Ó2HÈÈ8È*ÐTTÈÐ1UÐUVÐWXÐY[ÐV\Ð\]Ð^_Ð`cÐ]dÐdeÐfgÐhjÐekÐklÐmnÐorÐlsÐtÕuð	vô 	�‰�sœS ›X‘~Ð& bÐ)Õ*r   c                óü  — |dk  s
J d|› �«       ‚|dk  s
J d|› �«       ‚d|dz  d›d|dz  d›d�}t        j                  d	|› d
|› d�«       |dk  rg S | j                  «        | j                  st        j                  d«       g S | j                  D �cg c]G  }|j                  dd«      |j                  dd«      z  |k\  rd|j                  dd«      z
  |dz  k\  r|‘ŒI }}|j                  d„ ¬«       |d| D �cg c]  }|d   ‘Œ	 }}|rMt        |«      |k  r%t        j                  d|› dt        |«      › d�«       t        j                  d|› �«       |S t        j                  d|› d�«       |S c c}w c c}w )a‚  Select the most idle GPUs based on utilization and free memory.

        Args:
            count (int): The number of idle GPUs to select.
            min_memory_fraction (float): Minimum free memory required as a fraction of total memory.
            min_util_fraction (float): Minimum free utilization rate required from 0.0 - 1.0.

        Returns:
            (list[int]): Indices of the selected GPUs, sorted by idleness (lowest utilization first).

        Notes:
             Returns fewer than 'count' if not enough qualify or exist.
             Returns empty list if NVML stats are unavailable or no GPUs meet the criteria.
        g      ð?z(min_memory_fraction must be <= 1.0, got z&min_util_fraction must be <= 1.0, got zfree memory >= éd   z.1fz% and free utilization >= r]   zSearching for z idle GPUs with z...r   zNVML stats unavailable.r;   r:   r)   r8   c                ór   — | j                  dd«      | j                  dd«       t        j                  «       fS )Nr8   ée   r;   r   )rS   Úrandom)Úxs    r   ú<lambda>z)GPUInfo.select_idle_gpu.<locals>.<lambda>²   s1   € ¨!¯%©%°¸sÓ*CÀaÇeÁeÈMÐ[\ÓF]ÐE]Ô_e×_lÑ_lÓ_nÐ)o€ r   )ÚkeyNr6   z
Requested z GPUs but only z met the idle criteria.zSelected idle CUDA devices zNo GPUs met criteria (z).)r   ra   r   r   r   rS   ÚsortrR   )r   ÚcountÚmin_memory_fractionÚmin_util_fractionÚcriteriarD   Úeligible_gpusÚselecteds           r   Úselect_idle_gpuzGPUInfo.select_idle_gpu‰   sÅ  € ð" # cÒ)ÐkÐ-UÐViÐUjÐ+kÓkÐ)Ø  CÒ'ÐeÐ+QÐRcÐQdÐ)eÓeÐ'àÐ1°CÑ7¸Ð<Ð<VÐWhÐknÑWnÐorÐVsÐstÐuð 	ô 	�‰�n U GÐ+;¸H¸:ÀSÐIÔJà�AŠ:ØˆIà×ÑÔØ�~Š~Ü�N‰NÐ4Ô5ØˆIð
 —~‘~ö
àØ�w‰w�} aÓ(¨3¯7©7°>À1Ó+EÑEÐI\Ò\Ø�s—w‘w˜}¨cÓ2Ñ2Ð7HÈ3Ñ7NÒNò ð
ˆð 
ð 	×ÑÑoÐÔpð -:¸&¸5Ð,AÖB S�C˜“LÐBˆÐBáÜ�8‹}˜uÒ$Ü—‘ ¨E¨7°/Ä#ÀhÃ-ÀÐPgÐhÔiÜ�K‰KÐ5°h°ZÐ@ÔAð ˆô �N‰NÐ3°H°:¸RÐ@ÔAàˆùò)
ùò Cs   ÂAE4Ã<E9N)r6   r.   Úreturnzdict[str, Any])r)   r   r   )rs   r.   rt   r/   ru   r/   rz   z	list[int])Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   ri   ry   © r   r   r   r      sS   „ ñ òDTòò(ò ó
ò6+ð. Z[ð5Øð5Ø38ð5ØQVð5à	ô5r   r   Ú__main__gš™™™™™É?r)   )rs   rt   ru   z!
==> Using selected GPU indices: zcuda:z    Target devices: )Ú
__future__r   rn   Útypingr   Úultralytics.utilsr   Úultralytics.utils.checksr   r   r{   Úrequired_free_mem_fractionÚrequired_free_util_fractionÚnum_gpus_to_selectÚgpu_infori   ry   rx   ÚprintÚdevices)Úidxs   0r   ú<module>rŒ      sÁ   ðõ #ã Ý å $Ý 7÷rñ rðj ˆzÒØ!$ÐØ"%ÐØÐá‹y€HØ×ÑÔà×+Ñ+Ø Ø6Ø5ð ,ó ð €xð ñ
 	Ð2°8°*Ð=Ô>Ø,4Ö5 S�U˜3˜%’=Ò5ˆÙÐ$ W IÐ.Õ/ðð ùò 6s   Á.B