U
    0-e                     @   sb   d Z ddlZddlZddlZddlZddlmZmZ dd Ze	e
ddd	ZdeedddZdS )z
A collection of utilities for ensuring that training can always occur. Heavily influenced by the
[toma](https://github.com/BlackHC/toma) library.
    N   )is_npu_availableis_xpu_availablec                  G   sf   t | tst| } tt| D ]}d| |< qt  t rFtj	  nt
 rXtj	  n
tj	  | S )aN  
    Releases memory from `objects` by setting them to `None` and calls `gc.collect()` and `torch.cuda.empty_cache()`.
    Returned objects should be reassigned to the same variables.

    Args:
        objects (`Iterable`):
            An iterable of objects
    Returns:
        A list of `None` objects to replace `objects`

    Example:

        ```python
        >>> import torch
        >>> from accelerate.utils import release_memory

        >>> a = torch.ones(1000, 1000).cuda()
        >>> b = torch.ones(1000, 1000).cuda()
        >>> a, b = release_memory(a, b)
        ```
    N)
isinstancelistrangelengccollectr   torchxpuempty_cacher   npucuda)objectsi r   X/var/www/html/Darija-Ai-Train/env/lib/python3.8/site-packages/accelerate/utils/memory.pyrelease_memory   s    


r   )	exceptionreturnc                    s<   dddg}t  tr8t jdkr8t fdd|D S dS )z
    Checks if `exception` relates to CUDA out-of-memory, CUDNN not supported, or CPU out-of-memory

    Args:
        exception (`Exception`):
            An exception
    zCUDA out of memory.z(cuDNN error: CUDNN_STATUS_NOT_SUPPORTED.z*DefaultCPUAllocator: can't allocate memoryr   c                 3   s   | ]}| j d  kV  qdS )r   N)args).0errr   r   r   	<genexpr>O   s     z+should_reduce_batch_size.<locals>.<genexpr>F)r   RuntimeErrorr   r   any)r   Z_statementsr   r   r   should_reduce_batch_sizeA   s    	r      )functionstarting_batch_sizec                    s,   dkrt jt|dS |  fdd}|S )a  
    A basic decorator that will try to execute `function`. If it fails from exceptions related to out-of-memory or
    CUDNN, the batch size is cut in half and passed to `function`

    `function` must take in a `batch_size` parameter as its first argument.

    Args:
        function (`callable`, *optional*):
            A function to wrap
        starting_batch_size (`int`, *optional*):
            The batch size to try and fit into memory

    Example:

    ```python
    >>> from accelerate.utils import find_executable_batch_size


    >>> @find_executable_batch_size(starting_batch_size=128)
    ... def train(batch_size, model, optimizer):
    ...     ...


    >>> train(model, optimizer)
    ```
    N)r!   c               
      sF  t   t rtj  nt r,tj  n
tj  t	t
j }t|t| d k rddd t|dd  | dd  D }tdj dj d| d d	krtd
z f| |W S  tk
r> } zTt|r,t   t rtj  nt rtj  n
tj   d  n W 5 d }~X Y qX qd S )Nr   z, c                 S   s   g | ]\}}| d | qS )=r   )r   argvaluer   r   r   
<listcomp>   s     zAfind_executable_batch_size.<locals>.decorator.<locals>.<listcomp>zBatch size was passed into `zS` as the first argument when called.Remove this as the decorator already does so: `(z)`r   z-No executable batch size found, reached zero.   )r	   r
   r   r   r   r   r   r   r   r   inspect	signature
parameterskeysr   joinzip	TypeError__name__r   	Exceptionr   )r   kwargsparamsZarg_streZ
batch_sizer    r   r   	decorators   s4    
*


z-find_executable_batch_size.<locals>.decorator)	functoolspartialfind_executable_batch_size)r    r!   r5   r   r4   r   r8   S   s
    #r8   )Nr   )__doc__r6   r	   r(   r   Zimportsr   r   r   r0   boolr   callableintr8   r   r   r   r   <module>   s   $