a
    dU                     @   s  d Z ddlZddlmZ ddlmZmZ ddlZddlm	Z	 ddl
mZ dd	lmZmZ dd
lmZmZ eddrddlm  mZ e rddlmZ dd Zdd Zdd Zdd Zdd ZeddddZdKddZdd Zdd  Z d!d" Z!d#d$ Z"d%d& Z#d'd( Z$e$Z%d)d* Z&ed+d,d-Z'e'Z(ed+d.d/Z)dLd0d1Z*dMd3d4Z+dNe,d5d6d7Z-dOe,d5d8d9Z.d:d; Z/dPd<d=Z0dQd>d?Z1dRdAdBZ2dCdD Z3G dEdF dFZ4dGdH Z5dIdJ Z6dS )SzB
A set of basic tensor ops compatible with tpu, gpu, and multigpu
    N)update_wrapper)AnyMapping   )PartialState   )CUDA_DISTRIBUTED_TYPES)DistributedTypeTensorInformation)is_torch_distributed_availableis_tpu_availableF)Zcheck_device)ReduceOpc                 C   s   t | tjS N)
isinstancetorchTensortensor r   d/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/accelerate/utils/operations.pyis_torch_tensor'   s    r   c              	   C   s2   t | tjjtjjtjjtjjtjjtjjtjj	S r   )
r   r   ZxpuZFloatTensorZ
ByteTensorZ	IntTensorZ
LongTensorZ
HalfTensorZDoubleTensorZBFloat16Tensorr   r   r   r   is_torch_xpu_tensor+   s    r   c                 C   s
   t | tS r   )r   r
   Ztensor_infor   r   r   is_tensor_information8   s    r   c                 C   sV   t | }|j}t|dks&|d tkr*dS t|dd}t|tsDdS tdd |D S )z
    Checks if `x` is a `namedtuple` or not. Can have false positives, but only if a user is trying to mimic a
    `namedtuple` perfectly.
    r   r   F_fieldsNc                 s   s   | ]}t |tV  qd S r   )r   str).0memberr   r   r   	<genexpr>H       z is_namedtuple.<locals>.<genexpr>)type	__bases__lentuplegetattrr   all)dataZ	data_typebasesfieldsr   r   r   is_namedtuple<   s    
r)   c                 C   s(   t | rt| t| S t| |S dS )zO
    Cast a generator to the same type as obj (list, tuple, or namedtuple)
    N)r)   r    list)obj	generatorr   r   r   
honor_typeK   s    r-   	test_typeerror_on_other_typec                   s   t |ttfr.t| fdd|D S t |tr^t| fdd| D S |r||g R i S rtdt| dj dj d|S )	a9  
    Recursively apply a function on a data structure that is a nested list/tuple/dictionary of a given base type.

    Args:
        func (`callable`):
            The function to recursively apply.
        data (nested list/tuple/dictionary of `main_type`):
            The data on which to apply `func`
        *args:
            Positional arguments that will be passed to `func` when applied on the unpacked data.
        main_type (`type`, *optional*, defaults to `torch.Tensor`):
            The base type of the objects to which apply `func`.
        error_on_other_type (`bool`, *optional*, defaults to `False`):
            Whether to return an error or not if after unpacking `data`, we get on an object that is not of type
            `main_type`. If `False`, the function will leave objects of types different than `main_type` unchanged.
        **kwargs:
            Keyword arguments that will be passed to `func` when applied on the unpacked data.

    Returns:
        The same data structure as `data` with `func` applied to every object of type `main_type`.
    c                 3   s,   | ]$}t |g R d V  qdS )r.   Nrecursively_apply)r   oargsr0   funckwargsr/   r   r   r   o   s   z$recursively_apply.<locals>.<genexpr>c                    s0   i | ](\}}|t |g R d qS )r.   r1   r   kvr4   r   r   
<dictcomp>x   s   z%recursively_apply.<locals>.<dictcomp>zUnsupported types (z) passed to `z?`. Only nested list/tuple/dicts of objects that are valid for `z` should be passed.)	r   r#   r*   r-   r   r    items	TypeError__name__)r6   r&   r/   r0   r5   r7   r   r4   r   r2   V   s,    	
r2   c                    s   t | ttfr*t|  fdd| D S t | trtt trFgndu rRg t|  fdd|  D S t| drz| j	 dW S  t
y   | 	  Y S 0 n| S dS )a  
    Recursively sends the elements in a nested list/tuple/dictionary of tensors to a given device.

    Args:
        tensor (nested list/tuple/dictionary of `torch.Tensor`):
            The data to send to a given device.
        device (`torch.device`):
            The device to send the data to.

    Returns:
        The same data structure as `tensor` with all tensors sent to the proper device.
    c                 3   s   | ]}t | d V  qdS )non_blocking	skip_keysNsend_to_device)r   tdevicer@   rA   r   r   r      r   z!send_to_device.<locals>.<genexpr>Nc              	      s.   i | ]&\}}||v r|nt | d qS )r?   rB   )r   r9   rD   rE   r   r   r;      s   z"send_to_device.<locals>.<dictcomp>to)r@   )r   r#   r*   r-   r   r   r    r<   hasattrrG   r=   )r   rF   r@   rA   r   rE   r   rC      s(    


rC   c                 C   s   dd }t || S )aK  
    Recursively gathers the information needed to rebuild a nested list/tuple/dictionary of tensors.

    Args:
        data (nested list/tuple/dictionary of `torch.Tensor`):
            The data to send to analyze.

    Returns:
        The same data structure as `data` with [`~utils.TensorInformation`] instead of tensors.
    c                 S   s   t | j| jdS )N)shapedtype)r
   rI   rJ   r   r   r   r   _get_data_structure   s    z/get_data_structure.<locals>._get_data_structurer1   )r&   rK   r   r   r   get_data_structure   s    rL   c                 C   s   dd }t || tdS )z
    Recursively initializes tensors from a nested list/tuple/dictionary of [`~utils.TensorInformation`].

    Returns:
        The same data structure as `data` with tensors instead of [`~utils.TensorInformation`].
    c                 S   s   t j| jd| jiS NrJ   )r   emptyrI   rJ   r   r   r   r   _initialize_tensor   s    z.initialize_tensors.<locals>._initialize_tensorr/   )r2   r   )Zdata_structurerO   r   r   r   initialize_tensors   s    rQ   c                 C   sl   t | ttfrt| d S t | trB|  D ]}t| |   S n t | tjsbtdt	|  d| j
d S )a  
    Recursively finds the batch size in a nested list/tuple/dictionary of lists of tensors.

    Args:
        data (nested list/tuple/dictionary of `torch.Tensor`): The data from which to find the batch size.

    Returns:
        `int`: The batch size.
    r   z0Can only find the batch size of tensors but got .)r   r#   r*   find_batch_sizer   keysr   r   r=   r    rI   )r&   r9   r   r   r   rS      s    

rS   c                 C   s   dd }t || S )aS  
    Recursively finds tensors in a nested list/tuple/dictionary and converts them to a list of numbers.

    Args:
        data (nested list/tuple/dictionary of `torch.Tensor`): The data from which to convert to regular numbers.

    Returns:
        The same data structure as `data` with lists of numbers instead of `torch.Tensor`.
    c                 S   s,   |    } | jtjkr$| tj} |  S r   )detachcpurJ   r   bfloat16rG   float32tolistr   r   r   r   _convert_to_list   s    z!listify.<locals>._convert_to_listr1   )r&   rZ   r   r   r   listify   s    	r[   c                 C   s"   dd }t || dd}t  |S )Nc                 S   s    | j dkr|  d  } t| S )Nr   )ndimclonexm
all_gatherr   r   r   r   _tpu_gather_one   s    
z$_tpu_gather.<locals>._tpu_gather_oneTr0   )r2   r^   Z	mark_step)r   r`   resr   r   r   _tpu_gather   s    rc   c                 C   s   dd }t || ddS )Nc                    sN    j dkr  d    fddttj D }tj|  tj|ddS )Nr   c                    s   g | ]}t  qS r   )r   Z
empty_liker   _r   r   r   
<listcomp>	  r   z8_gpu_gather.<locals>._gpu_gather_one.<locals>.<listcomp>dim)r\   r]   ranger   distributedZget_world_sizer_   cat)r   Zoutput_tensorsr   r   r   _gpu_gather_one  s
    
z$_gpu_gather.<locals>._gpu_gather_oneTra   r1   )r   rl   r   r   r   _gpu_gather  s    rm   c                 C   st   t  jtjkrt| S t  jtv r*t| S t  jtjv r@t| S t  jtjv rVt| S t  jtj	krlt
| S | S dS )a4  
    Recursively gather tensor in a nested list/tuple/dictionary of tensors from all devices.

    Args:
        tensor (nested list/tuple/dictionary of `torch.Tensor`):
            The data to gather.

    Returns:
        The same data structure as `tensor` with all tensors sent to the proper device.
    N)r   distributed_typer	   TPUrc   r   rm   	MULTI_NPU	MULTI_XPU	MULTI_CPU_cpu_gatherr   r   r   r   gather  s    rt   objectc                 C   s2   dd t t jD }tj||  dd |D S )Nc                 S   s   g | ]}d qS r   r   rd   r   r   r   rf   -  r   z&_gpu_gather_object.<locals>.<listcomp>c                 S   s   g | ]}|D ]}|qqS r   r   )r   yxr   r   r   rf   0  r   )ri   r   num_processesr   rj   Zall_gather_object)rv   Zoutput_objectsr   r   r   _gpu_gather_object,  s    rz   c                 C   sv   t  jtjkrtdnZt  jtv r,t| S t  jtjv rBt| S t  jtjv rXt| S t  jtj	krnt
| S | S dS )a5  
    Recursively gather object in a nested list/tuple/dictionary of objects from all devices.

    Args:
        object (nested list/tuple/dictionary of picklable object):
            The data to gather.

    Returns:
        The same data structure as `object` with all the objects sent to every device.
    z&gather objects in TPU is not supportedN)r   rn   r	   ro   NotImplementedErrorr   rz   rp   rq   rr   _cpu_gather_objectru   r   r   r   gather_object6  s    
r}   c                 C   s   ddd}t || d|dS )Nr   c                 S   s   t jj| |d | S )Nsrc)r   rj   	broadcast)r   r   r   r   r   _gpu_broadcast_oneP  s    z*_gpu_broadcast.<locals>._gpu_broadcast_oneT)r0   r   )r   r1   )r&   r   r   r   r   r   _gpu_broadcastO  s    
r   broadcast tensorc                    sh   t | ttfr*t|  fddt| D S t | trRt|  fdd|  D S t	 | fddS )Nc                 3   s(   | ] \}}t |  d | dV  qdS )re   nameN_tpu_broadcast)r   irD   r   r   r   r   Y  r   z!_tpu_broadcast.<locals>.<genexpr>c                    s(   i | ] \}}|t |  d | dqS )re   r   r   r8   r   r   r   r;   [  r   z"_tpu_broadcast.<locals>.<dictcomp>c                    s   |   S r   r   rx   r~   r   r   <lambda>\  r   z _tpu_broadcast.<locals>.<lambda>)
r   r*   r#   r-   	enumerater   r    r<   r^   mesh_reduce)r   r   r   r   )r   r   r   r   W  s
    
r   from_processc                 C   s   t  jtjkrt| |ddS t  jtv r4t| |dS t  jtjv rJtt	S t  jtj
v rdt| |dS t  jtjkr~t| |dS | S dS )a  
    Recursively broadcast tensor in a nested list/tuple/dictionary of tensors to all devices.

    Args:
        tensor (nested list/tuple/dictionary of `torch.Tensor`):
            The data to gather.
        from_process (`int`, *optional*, defaults to 0):
            The process from which to send the data

    Returns:
        The same data structure as `tensor` with all tensors broadcasted to the proper device.
    zaccelerate.utils.broadcast)r   r   r~   N)r   rn   r	   ro   r   r   r   rp   rz   rv   rq   rr   )r   r   r   r   r   r   _  s    r   c                    s   t  jtjkr<t| D ]"\}}td| fdd| |< qn|t  jtv rZtj	j
|  d n^t  jtjv rztj	j
|  d n>t  jtjv rtj	j
|  d nt  jtjkrtj	j
|  d | S )a  
    Broadcast a list of picklable objects form one process to the others.

    Args:
        object_list (list of picklable objects):
            The list of objects to broadcast. This list will be modified inplace.
        from_process (`int`, *optional*, defaults to 0):
            The process from which to send the data.

    Returns:
        The same list containing the objects from process 0.
    z&accelerate.utils.broadcast_object_listc                    s   |   S r   r   r   r   r   r   r     r   z'broadcast_object_list.<locals>.<lambda>r~   )r   rn   r	   ro   r   r^   r   r   r   rj   broadcast_object_listrp   rq   rr   )Zobject_listr   r   r+   r   r   r   r   z  s    r   c                 C   s   dd }t || |S )aN  
    Recursively takes a slice in a nested list/tuple/dictionary of tensors.

    Args:
        data (nested list/tuple/dictionary of `torch.Tensor`):
            The data to slice.
        tensor_slice (`slice`):
            The slice to take.

    Returns:
        The same data structure as `data` with all the tensors slices.
    c                 S   s   | | S r   r   )r   tensor_slicer   r   r   _slice_tensor  s    z$slice_tensors.<locals>._slice_tensorr1   )r&   r   r   r   r   r   slice_tensors  s    r   c                    s   t  d ttfr<t d  fddtt d D S t  d trrt d  fdd d  D S t  d t	j
stdt d  t	j dS )a  
    Recursively concatenate the tensors in a nested list/tuple/dictionary of lists of tensors with the same shape.

    Args:
        data (nested list/tuple/dictionary of lists of tensors `torch.Tensor`):
            The data to concatenate.
        dim (`int`, *optional*, defaults to 0):
            The dimension on which to concatenate.

    Returns:
        The same data structure as `data` with all the tensors concatenated.
    r   c                 3   s(   | ]  t  fd dD dV  qdS )c                    s   g | ]}|  qS r   r   r   dr   r   r   rf     r   z)concatenate.<locals>.<genexpr>.<listcomp>rg   Nconcatenater   r&   rh   r   r   r     r   zconcatenate.<locals>.<genexpr>c                    s(   i | ]   t  fd dD dqS )c                    s   g | ]}|  qS r   r   r   r9   r   r   rf     r   z*concatenate.<locals>.<dictcomp>.<listcomp>rg   r   r   r   r   r   r;     r   zconcatenate.<locals>.<dictcomp>z%Can only concatenate tensors but got rg   )r   r#   r*   r-   ri   r"   r   r    rT   r   r   r=   rk   r   r   r   r   r     s    *(r   c                 C   s   ddd}t || d|||dS )a3  
    Recursively pad the tensors in a nested list/tuple/dictionary of tensors from all devices to the same size so they
    can safely be gathered.

    Args:
        tensor (nested list/tuple/dictionary of `torch.Tensor`):
            The data to gather.
        dim (`int`, *optional*, defaults to 0):
            The dimension on which to pad.
        pad_index (`int`, *optional*, defaults to 0):
            The value with which to pad.
        pad_first (`bool`, *optional*, defaults to `False`):
            Whether to pad at the beginning or the end.
    r   Fc           	         s    t | jkr| S tj| j| jdd  }t| }t fdd|D | j  kr\| S | jt}| < | 	t
|| }|rt
 fddtt |D }n t
 fddtt |D }| ||< |S )N)rF   c                 3   s   | ]}|  V  qd S r   r   )r   srg   r   r   r     r   zFpad_across_processes.<locals>._pad_across_processes.<locals>.<genexpr>c                 3   s0   | ](}| kr t    nt d V  qd S r   slicer   r   rh   max_sizeold_sizer   r   r     s   c                 3   s,   | ]$}| krt d   nt dV  qdS )r   Nr   r   )rh   r   r   r   r     r   )r"   rI   r   r   rF   rt   rV   maxr*   Z	new_zerosr#   ri   )	r   rh   	pad_index	pad_firstsizesizesZnew_sizeZ
new_tensorindicesr   r   r   _pad_across_processes  s$    

 z3pad_across_processes.<locals>._pad_across_processesT)r0   rh   r   r   )r   r   Fr1   )r   rh   r   r   r   r   r   r   pad_across_processes  s    
r   meanc                 C   s   ddd}t || d|dS )a  
    Recursively reduce the tensors in a nested list/tuple/dictionary of lists of tensors across all processes by the
    mean of a given operation.

    Args:
        tensor (nested list/tuple/dictionary of `torch.Tensor`):
            The data to reduce.
        reduction (`str`, *optional*, defaults to `"mean"`):
            A reduction method. Can be of "mean", "sum", or "none"

    Returns:
        The same data structure as `data` with all the tensors reduced.
    r   c                 S   s   t  }|  }|jtjkr|S |jtjkr8td| nz|jjt	v rVt
j|tj n\|jjtjv rvt
j|tj n<|jjtjv rt
j|tj n|jtjkrt
j|tj |dkr||j }|S )Nsumr   )r   r]   rn   r	   NOro   r^   Z
all_reducevaluer   r   rj   r   ZSUMrp   rq   rr   ry   )r   	reductionstateZcloned_tensorr   r   r   _reduce_across_processes  s"    
z(reduce.<locals>._reduce_across_processesT)r0   r   )r   r1   )r   r   r   r   r   r   reduce  s    
r   c                 C   s   dd }dd }t || |dS )av  
    Recursively converts the elements nested list/tuple/dictionary of tensors in FP16/BF16 precision to FP32.

    Args:
        tensor (nested list/tuple/dictionary of `torch.Tensor`):
            The data to convert from FP16/BF16 to FP32.

    Returns:
        The same data structure as `tensor` with all tensors that were in FP16/BF16 precision converted to FP32.
    c                 S   s   |   S r   )floatr   r   r   r   _convert_to_fp32  s    z)convert_to_fp32.<locals>._convert_to_fp32c                 S   s   t | do| jtjtjfv S rM   )rH   rJ   r   float16rW   r   r   r   r   _is_fp16_bf16_tensor!  s    z-convert_to_fp32.<locals>._is_fp16_bf16_tensorrP   r1   )r   r   r   r   r   r   convert_to_fp32  s    r   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )	ConvertOutputsToFp32ad  
    Decorator to apply to a function outputing tensors (like a model forward pass) that ensures the outputs in FP16
    precision will be convert back to FP32.

    Args:
        model_forward (`Callable`):
            The function which outputs we want to treat.

    Returns:
        The same function as `model_forward` but with converted outputs.
    c                 C   s   || _ t| | d S r   )model_forwardr   )selfr   r   r   r   __init__4  s    zConvertOutputsToFp32.__init__c                 O   s   t | j|i |S r   )r   r   )r   r5   r7   r   r   r   __call__8  s    zConvertOutputsToFp32.__call__c                 C   s   t dd S )NzCannot pickle a prepared model with automatic mixed precision, please unwrap the model with `Accelerator.unwrap_model(model)` before pickling it.)picklePicklingError)r   r   r   r   __getstate__;  s    z!ConvertOutputsToFp32.__getstate__N)r>   
__module____qualname____doc__r   r   r   r   r   r   r   r   '  s   r   c                    s   t    fdd} |_|S )Nc                     s    | i |S r   r   )r5   r7   r   r   r   forwardD  s    z(convert_outputs_to_fp32.<locals>.forward)r   __wrapped__)r   r   r   r   r   convert_outputs_to_fp32A  s    r   c                 C   sz   t | tr2|  D ]}t|}|dur|  S qnDt | ttfrd| D ]}t|}|durD|  S qDnt | tjrv| jS dS )z
    Finds the device on which a nested dict/list/tuple of tensors lies (assuming they are all on the same device).

    Args:
        (nested list/tuple/dictionary of `torch.Tensor`): The data we want to know the device of.
    N)	r   r   valuesfind_devicer#   r*   r   r   rF   )r&   r+   rF   r   r   r   r   M  s    
r   )FN)r   )r   r   )r   )r   )r   )r   r   F)r   )7r   r   	functoolsr   typingr   r   r   r   r   	constantsr   Zdataclassesr	   r
   Zimportsr   r   Ztorch_xla.core.xla_modelcoreZ	xla_modelr^   Ztorch.distributedr   r   r   r   r)   r-   r2   rC   rL   rQ   rS   r[   rc   rm   rs   rt   rz   r|   r}   r   r   intr   r   r   r   r   r   r   r   r   r   r   r   r   r   <module>   sT   
3
%



.
%