Ë
    )täiæz  ã                   ó¼  — d Z ddlZddlZddlmZ ddlmZmZ ddlm	Z	m
Z
 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mZ d	dlmZmZmZ d	dlmZ  e«       r	ddlmc mZ  e«       rddl m!Z! d„ Z"d„ Z#d„ Z$d„ Z%d„ Z&e"ddœd„Z'dEd„Z(d„ Z)d„ Z*d„ Z+d„ Z,d„ Z-d„ Z.d„ Z/d„ Z0 G d „ d!e1«      Z2d"„ Z3d#„ Z4e3d$„ «       Z5d%efd&„Z6d%efd'„Z7dFd(„Z8dGd)„Z9ejt                  d	ejv                  dejx                  d*ejz                  d+ej|                  d,ej~                  d-ej€                  d.ej‚                  d/ej„                  d0ej†                  d1i
ZDeDj‹                  «       D � �ci c]  \  } }|| “Œ
 c}} ZFd2„ ZGdHd3ej�                  fd4„ZIe3dFd5eJfd6„«       ZKdFd5eJfd7„ZLdId8„ZMdFd9„ZN G d:„ d;eO«      ZPe4dJd<„«       ZQdFd=„ZRe3dKd>„«       ZSd?„ ZT G d@„ dA«      ZUdB„ ZVdC„ ZWedLdD„«       ZXyc c}} w )MzB
A set of basic tensor ops compatible with tpu, gpu, and multigpu
é    N)ÚMapping)ÚcontextmanagerÚnullcontext)Úupdate_wrapperÚwraps)ÚAnyé   )ÚAcceleratorStateÚPartialStateé   )Ú!TORCH_DISTRIBUTED_OPERATION_TYPES)ÚDistributedTypeÚTensorInformation)Úis_npu_availableÚis_torch_distributed_availableÚis_torch_xla_available)Úis_torch_version)ÚReduceOpc                 ó6   — t        | t        j                  «      S ©N)Ú
isinstanceÚtorchÚTensor©Útensors    új/Volumes/fast/ai/experiments/MLX_z-image/.venv/lib/python3.12/site-packages/accelerate/utils/operations.pyÚis_torch_tensorr   -   s   € Ü�fœeŸl™lÓ+Ð+ó    c           
      óv  — 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   ÚxpuÚFloatTensorÚ
ByteTensorÚ	IntTensorÚ
LongTensorÚ
HalfTensorÚDoubleTensorÚBFloat16Tensorr   s    r   Úis_torch_xpu_tensorr(   1   sm   € ÜØÜ�	‰	×ÑÜ�	‰	×ÑÜ�	‰	×ÑÜ�	‰	×ÑÜ�	‰	×ÑÜ�	‰	×ÑÜ�	‰	× Ñ ó	ð 	r   c                 ó"   — t        | t        «      S r   )r   r   ©Útensor_infos    r   Úis_tensor_informationr,   >   s   € Ü�kÔ#4Ó5Ð5r   c                 óZ   — t        | t        «      xr t        | d«      xr t        | d«      S )z’
    Checks if `data` is a `namedtuple` or not. Can have false positives, but only if a user is trying to mimic a
    `namedtuple` perfectly.
    Ú_asdictÚ_fields)r   ÚtupleÚhasattr©Údatas    r   Úis_namedtupler4   B   s*   € ô
 �dœEÓ"Ò\¤w¨t°YÓ'?Ò\ÄGÈDÐR[ÓD\Ð\r   c                 óh   — t        | «      r t        | «      t        |«      Ž S  t        | «      |«      S )zO
    Cast a generator to the same type as obj (list, tuple, or namedtuple)
    )r4   ÚtypeÚlist)ÚobjÚ	generators     r   Ú
honor_typer:   J   s2   € ô
 �SÔØŒt�C‹yœ$˜y›/Ð*Ð*àŒt�C‹y˜Ó#Ð#r   F©Ú	test_typeÚerror_on_other_typec                ó²  ‡ ‡‡‡‡— t        |t        t        f«      rt        |ˆˆˆ ˆˆfd„|D «       «      S t        |t        «      rD t        |«      |j                  «       D ��ci c]  \  }}|t        ‰ |g‰¢­‰‰dœ‰¤Ž“Œ c}}«      S  ‰|«      r ‰ |g‰¢­i ‰¤ŽS ‰r2t        dt        |«      › d‰ j                  › d‰j                  › d�«      ‚|S c c}}w )ad  
    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 (additional keyword arguments, *optional*):
            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   óD   •K  — | ]  }t        ‰|g‰¢­‰‰d œ‰¤Ž–— Œ y­w)r;   N©Úrecursively_apply)Ú.0ÚoÚargsr=   ÚfuncÚkwargsr<   s     €€€€€r   Ú	<genexpr>z$recursively_apply.<locals>.<genexpr>n   sB   øè ø€ ð ñ �Aô "Ø˜!ðØ"ñØ.7ÐM`ñØdjõñ ùs   ƒ r;   zUnsupported types (z) passed to `z?`. Only nested list/tuple/dicts of objects that are valid for `z` should be passed.)
r   r0   r7   r:   r   r6   ÚitemsrA   Ú	TypeErrorÚ__name__)rE   r3   r<   r=   rD   rF   ÚkÚvs   ` ````  r   rA   rA   U   s  ü€ ô, �$œ¤˜Ô&ÜØ÷ñ ó	ó
ð 	
ô 
�Dœ'Ô	"ØŒt�D‹zð
 !ŸJ™JœLô	ñ )‘D�A�qð Ô$Ø˜!ðØ"ñØ.7ÐM`ñØdjññ ð )ò	ó
ð 	
ñ 
�4ŒÙ�DÐ*˜4Ò* 6Ñ*Ð*Ù	ÜØ!¤$ t£* ¨]¸4¿=¹=¸/ð J+Ø+4×+=Ñ+=Ð*>Ð>QðSó
ð 	
ð €Kùós   Á#C
c                 óÀ  ‡‡‡— t        | «      st        | d«      r‰dk(  rdŠ	 | j                  ‰‰¬«      S t        | t        t        f«      rt        | ˆˆˆfd„| D «       «      S t        | t        «      r^t        ‰t        «      r‰gŠn‰€g Š t        | «      | j                  «       D ��ci c]  \  }}||‰v r|nt        |‰‰‰¬«      “Œ c}}«      S | S # t        $ r | j                  ‰«      cY S t        $ r,}t        «       rt        ‰t        «      rd‰› �Šn|‚Y d}~nd}~ww xY w	 | j                  ‰‰¬«      S # t        $ r | j                  ‰«      cY S w xY wc c}}w )	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.
    ÚtoÚnpuznpu:0)Únon_blockingznpu:Nc              3   ó<   •K  — | ]  }t        |‰‰‰¬ «      –— Œ y­w)©rP   Ú	skip_keysN)Úsend_to_device)rB   ÚtÚdevicerP   rS   s     €€€r   rG   z!send_to_device.<locals>.<genexpr>«   s$   øè ø€ ÐoÑhnÐcd”^ A v¸LÐT]×^Ð^Ñhnùs   ƒrR   )r   r1   rN   rI   ÚAssertionErrorr   r   Úintr0   r7   r:   r   Ústrr6   rH   rT   )r   rV   rP   rS   ÚerrorrK   rU   s    ```   r   rT   rT   ˆ   sl  ú€ ô �vÔ¤'¨&°$Ô"7à�UŠ?ØˆFð	Ø—9‘9˜V°,�9Ó?Ð?ô 
�FœU¤D˜MÔ	*ÜØÕoÑhnÓoó
ð 	
ô 
�FœGÔ	$Ü�i¤Ô%Ø"˜‰IØÐØˆIØŒt�F‹|ð #ŸL™LœNôá*‘D�A�qð ˜˜Y™‘1¬N¸1¸fÐS_ÐktÔ,uÑuØ*òó
ð 	
ð ˆøô= ò 	%Ø—9‘9˜VÓ$Ò$Üò 	ô  Ô!Ü˜f¤cÔ*Ø# F 8˜_‘Fà�ÿøð	úð	%Ø—9‘9˜V°,�9Ó?Ð?øÜò 	%Ø—9‘9˜VÓ$Ò$ð	%üós5   £C Â) E
ÃD#Ã/D#Ã7"DÄD#Ä'D: Ä:EÅEc                 ó    — 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                 óD   — t        | j                  | j                  ¬«      S )N)ÚshapeÚdtype)r   r]   r^   r   s    r   Ú_get_data_structurez/get_data_structure.<locals>._get_data_structureÈ   s   € Ü  v§|¡|¸6¿<¹<ÔHÐHr   r@   )r3   r_   s     r   Úget_data_structurer`   ¼   s   € òIô Ð0°$Ó7Ð7r   c                 ó    — d„ }t        || «      S )a:  
    Recursively gathers the shape of a nested list/tuple/dictionary of tensors as a list.

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

    Returns:
        The same data structure as `data` with lists of tensor shapes instead of tensors.
    c                 ó,   — t        | j                  «      S r   )r7   r]   r   s    r   Ú
_get_shapezget_shape.<locals>._get_shapeÚ   s   € Ü�F—L‘LÓ!Ð!r   r@   )r3   rc   s     r   Ú	get_shaperd   Î   s   € ò"ô ˜Z¨Ó.Ð.r   c                 ó,   — d„ }t        || t        ¬«      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                 óT   — t        j                  | j                  d| j                  iŽS ©Nr^   )r   Úemptyr]   r^   r*   s    r   Ú_initialize_tensorz.initialize_tensors.<locals>._initialize_tensorè   s"   € Ü�{‰{˜K×-Ñ-ÐG°[×5FÑ5FÑGÐGr   ©r<   )rA   r,   )Údata_structureri   s     r   Úinitialize_tensorsrl   à   s   € òHô Ð/°ÔK`ÔaÐar   c                 ó¸  — t        | t        t        t        f«      r&t	        | «      dk(  rt        dt        | «      › d�«      ‚t        | t        t        f«      rt        | d   «      S t        | t        «      r%| j                  «       D ]  }t        | |   «      c S  n2t        | t        j                  «      st        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   z&Cannot find the batch size from empty Ú.z0Can only find the batch size of tensors but got )r   r0   r7   r   ÚlenÚ
ValueErrorr6   Úfind_batch_sizeÚkeysr   r   rI   r]   )r3   rK   s     r   rq   rq   î   sµ   € ô �$œ¤¤gÐ.Ô/´S¸³YÀ!²^ÜÐAÄ$ÀtÃ*ÀÈQÐOÓPÐPä�$œ¤˜Ô&Ü˜t A™wÓ'Ð'Ü	�Dœ'Ô	"Ø—‘–ˆAÜ" 4¨¡7Ó+Ò+ñ ä˜œeŸl™lÔ+ÜÐJÌ4ÐPTË:È,ÐVWÐXÓYÐYØ�:‰:�a‰=Ðr   c                 óD   — 	 t        | «      S # t        t        f$ r Y yw xY w)a  
    Same as [`utils.operations.find_batch_size`] except will ignore if `ValueError` and `TypeErrors` are raised

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

    Returns:
        `int`: The batch size.
    N)rq   rp   rI   r2   s    r   Úignorant_find_batch_sizert     s,   € ðÜ˜tÓ$Ð$øÜœ	Ð"ò ØØðús   ‚
 �žc                 ó    — 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                 óÖ   — | j                  «       j                  «       } | j                  t        j                  k(  r| j                  t        j                  «      } | j                  «       S r   )ÚdetachÚcpur^   r   Úbfloat16rN   Úfloat32Útolistr   s    r   Ú_convert_to_listz!listify.<locals>._convert_to_list!  sF   € Ø—‘“×$Ñ$Ó&ˆØ�<‰<œ5Ÿ>™>Ò)ð —Y‘YœuŸ}™}Ó-ˆFØ�}‰}‹Ðr   r@   )r3   r|   s     r   Úlistifyr}     s   € òô Ð-¨tÓ4Ð4r   c                 óP   — d„ }t        || d¬«      }t        j                  «        |S )Nc                 ó°   — | j                   dk(  r| j                  «       d    } | j                  «       s| j                  «       } t	        j
                  | «      S )Nr   )ÚndimÚcloneÚis_contiguousÚ
contiguousÚxmÚ
all_gatherr   s    r   Ú_tpu_gather_onez$_tpu_gather.<locals>._tpu_gather_one.  sI   € Ø�;‰;˜!ÒØ—\‘\“^ DÑ)ˆFð ×#Ñ#Ô%Ø×&Ñ&Ó(ˆFÜ�}‰}˜VÓ$Ð$r   T©r=   )rA   r„   Ú	mark_step)r   r†   Úress      r   Ú_tpu_gatherrŠ   -  s%   € ò%ô ˜O¨VÈÔ
N€CÜ‡L�L„NØ€Jr   c                 óü   ‡‡— t        «       Št        j                  j                  Š‰j                  j
                  dk(  r*t        dd«      rt        j                  j                  «        ˆˆfd„}t        || d¬«      S )Nr    z<=z2.8c                 óˆ  •— | j                   dk(  r| j                  «       d    } | j                  «       s| j                  «       } ‰j                  �ƒ‰j                  dk7  rtt        j                  ‰j                  | j                  «       z  | j                  ‰j                  ¬«      } ‰|| «        |j                  dg| j                  «       dd  ¢­Ž S t        ‰j                  «      D �cg c]  }t        j                  | «      ‘Œ }}t
        j                  j!                  || «       t        j"                  |d¬«      S c c}w )Nr   Úgloo©r^   rV   éÿÿÿÿr   ©Údim)r€   r�   r‚   rƒ   Úbackendr   rh   Únum_processesÚnumelr^   rV   ÚviewÚsizeÚrangeÚ
empty_likeÚdistributedr…   Úcat)r   Úoutput_tensorsÚ_Ú	gather_opÚstates      €€r   Ú_gpu_gather_onez$_gpu_gather.<locals>._gpu_gather_oneD  s  ø€ Ø�;‰;˜!ÒØ—\‘\“^ DÑ)ˆFð ×#Ñ#Ô%Ø×&Ñ&Ó(ˆFà�=‰=Ð$¨¯©¸&Ò)@ô
 #Ÿ[™[Ø×#Ñ# f§l¡l£nÑ4Ø—l‘lØ—|‘|ôˆNñ
 �n fÔ-Ø&�>×&Ñ& rÐ>¨F¯K©K«M¸!¸"Ð,=Ò>Ð>ô
 AFÀe×FYÑFYÔ@ZÓ[Ñ@Z¸1œe×.Ñ.¨vÕ6Ð@ZˆNÐ[Ü×Ñ×(Ñ(¨¸Ô@Ü—9‘9˜^°Ô3Ð3ùò \s   Ã*D?Tr‡   )
r   r   r™   Úall_gather_into_tensorrV   r6   r   r    ÚsynchronizerA   )r   rŸ   r�   rž   s     @@r   Ú_gpu_gatherr¢   <  s_   ù€ Ü‹N€EÜ×!Ñ!×8Ñ8€Ið ‡|�|×Ñ˜EÒ!Ô&6°t¸UÔ&CÜ�	‰	×ÑÔõ4ô8 ˜_¨fÈ$ÔOÐOr   c                   ó   — e Zd ZdZy)ÚDistributedOperationExceptionz‰
    An exception class for distributed operations. Raised if the operation cannot be performed due to the shape of the
    tensors.
    N)rJ   Ú
__module__Ú__qualname__Ú__doc__© r   r   r¤   r¤   c  s   „ ñð
 	r   r¤   c                 ó.   ‡ — t        ‰ «      ˆ fd„«       }|S )zv
    Verifies that `tensor` is the same shape across all processes. Only ran if `PartialState().debug` is `True`.
    c                  ó0  •— t        «       j                  t        j                  k(  st        «       j                  s ‰
| i |¤ŽS ‰
j
                  › d‰
j                  › �}d|v r|d   }n| d   }t        «       j                  j                  t        |«      j                  k7  rgt        d|› d|j                  j                  › dt        «       j                  j                  › dt        «       j                  j                  › d|› d�«      ‚t        |«      }t        |g«      }|d   �f|j                  |d   «      t        |«      k(  }|sDd	j                  t!        |«      D ��cg c]  \  }}d
|› d|› �‘Œ c}}«      }	t        d|› d|	› �«      ‚ ‰
| i |¤ŽS c c}}w )Nrn   r   r   z%One or more of the tensors passed to z were not on the z+ while the `Accelerator` is configured for z. Please move it to the z before calling z
  - zProcess z: znCannot apply desired operation due to shape mismatches. All shapes across devices must be valid.

Operation: `z`
Input shapes:
  - )r   Údistributed_typer   ÚNOÚdebugr¥   rJ   rV   r6   Úfind_devicer¤   rd   Úgather_objectÚcountro   ÚjoinÚ	enumerate)rD   rF   Ú	operationr   ÚshapesÚoutputÚare_sameÚir]   Úprocess_shape_strÚfunctions             €r   Úwrapperz!verify_operation.<locals>.wrapperq  sÑ  ø€ ä‹>×*Ñ*¬o×.@Ñ.@Ò@ÌË×H\ÒH\Ù˜TÐ, VÑ,Ð,Ø×*Ñ*Ð+¨1¨X×->Ñ->Ð,?Ð@ˆ	Ø�vÑØ˜HÑ%‰Fà˜!‘WˆFÜ‹>× Ñ ×%Ñ%¬°VÓ)<×)AÑ)AÒAÜ/Ø7¸	°{ÐBSÐTZ×TaÑTa×TfÑTfÐSgð  hSô  T`ó  Tb÷  Tiñ  Ti÷  Tnñ  Tnð  Soð o)Ü)5«×)>Ñ)>×)CÑ)CÐ(DÐDTÐU^ÐT_Ð_`ðbóð ô ˜6Ó"ˆÜ ˜xÓ(ˆØ�!‰9Ð Ø—|‘| F¨1¡IÓ.´#°f³+Ñ=ˆHÙØ$,§M¡MÔ[dÐekÔ[lÔ2mÑ[lÉxÈqÐRW°X¸a¸SÀÀ5À'Ò3JÐ[lÒ2mÓ$nÐ!Ü3ð'à'0 kÐ1GÐHYÐGZð\óð ñ
 ˜Ð( Ñ(Ð(ùó 3ns   ÅF
©r   ©r¹   rº   s   ` r   Úverify_operationr½   l  s"   ø€ ô
 ˆ8ƒ_ó)ó ð)ð4 €Nr   c                 ó.   ‡ — t        ‰ «      ˆ fd„«       }|S )z‘
    Checks that `verify_operation` failed and if so reports a more helpful error chaining the existing
    `DistributedOperationException`.
    c                  óŽ   •— 	  ‰| i |¤ŽS # t         $ r0}‰j                  › d‰j                  › �}t        d|› d�«      |‚d }~ww xY w)Nrn   zError found while calling `z1`. Please see the earlier error for more details.)r¤   r¥   rJ   )rD   rF   Úer³   r¹   s       €r   rº   z"chained_operation.<locals>.wrapper•  sc   ø€ ð	Ù˜TÐ, VÑ,Ð,øÜ,ò 	Ø#×.Ñ.Ð/¨q°×1BÑ1BÐ0CÐDˆIÜ/Ø-¨i¨[Ð8iÐjóàðûð	ús   ƒ ‹	A”+?¿Ar»   r¼   s   ` r   Úchained_operationrÁ   �  s"   ø€ ô ˆ8ƒ_óó ðð €Nr   c                 ó°   — t        «       j                  t        j                  k(  rt	        | «      S t        «       j                  t
        v rt        | «      S | 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.
    )r   r«   r   ÚXLArŠ   r   r¢   r   s    r   ÚgatherrÄ   ¢  sF   € ô ƒ~×&Ñ&¬/×*=Ñ*=Ò=Ü˜6Ó"Ð"Ü	‹×	(Ñ	(Ô,MÑ	MÜ˜6Ó"Ð"àˆr   Úobjectc                 óÞ   — t        t        «       j                  «      D �cg c]  }d ‘Œ }}t        j                  j                  || «       |D ��cg c]  }|D ]  }|‘Œ Œ c}}S c c}w c c}}w r   )r—   r   r“   r   r™   Úall_gather_object)rÅ   rœ   Úoutput_objectsÚyÚxs        r   Ú_gpu_gather_objectrË   ¶  sc   € Ü$)¬,«.×*FÑ*FÔ$GÓHÑ$G˜q’dÐ$G€NÐHÜ	×Ñ×'Ñ'¨¸Ô?á%Ô1‘~�!«q¨!ŠA¨qˆA�~Ò1Ð1ùò Iùó 2s    	A$ÁA)c                 ó°   — t        «       j                  t        j                  k(  rt	        d«      ‚t        «       j                  t
        v rt        | «      S | 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 supported)r   r«   r   rÃ   ÚNotImplementedErrorr   rË   )rÅ   s    r   r¯   r¯   ½  sG   € ô ƒ~×&Ñ&¬/×*=Ñ*=Ò=Ü!Ð"JÓKÐKÜ	‹×	(Ñ	(Ô,MÑ	MÜ! &Ó)Ð)àˆr   c                 ó(   — dd„}t        || d|¬«      S )Nc                 óH   — t         j                  j                  | |¬«       | S )N©Úsrc)r   r™   Ú	broadcast)r   rÑ   s     r   Ú_gpu_broadcast_onez*_gpu_broadcast.<locals>._gpu_broadcast_oneÑ  s    € Ü×Ñ×#Ñ# F°Ð#Ô4Øˆr   T)r=   rÑ   ©r   r@   )r3   rÑ   rÓ   s      r   Ú_gpu_broadcastrÕ   Ð  s   € óô Ð/°È4ÐUXÔYÐYr   c                 óT  ‡‡— t        | t        t        f«      rt        | ˆfd„t	        | «      D «       «      S t        | t
        «      rC t        | «      | j                  «       D ��ci c]  \  }}|t        |‰› d|› �¬«      “Œ c}}«      S t        j                  ‰| ˆfd„«      S c c}}w )Nc              3   óH   •K  — | ]  \  }}t        |‰› d |› �¬«      –— Œ y­w)rœ   ©ÚnameN)Ú_tpu_broadcast)rB   r·   rU   rÙ   s      €r   rG   z!_tpu_broadcast.<locals>.<genexpr>Ú  s-   øè ø€ Ð"gÑUfÉTÈQÐPQ¤>°!¸T¸FÀ!ÀAÀ3¸-×#HÐ#HÑUfùs   ƒ"rœ   rØ   c                 ó   •— | ‰   S r   r¨   )rÊ   rÑ   s    €r   Ú<lambda>z _tpu_broadcast.<locals>.<lambda>Ý  s	   ø€ °!°C²&r   )r   r7   r0   r:   r²   r   r6   rH   rÚ   r„   Úmesh_reduce)r   rÑ   rÙ   rK   rL   s    ``  r   rÚ   rÚ   Ø  s•   ù€ Ü�&œ4¤˜-Ô(Ü˜&Ó"gÔU^Ð_eÔUfÓ"gÓhÐhÜ	�FœGÔ	$ØŒt�F‹|ÐRX×R^ÑR^ÔR`ÔaÑR`É$È!ÈQ˜Q¤¨q¸$¸¸qÀÀ°}Ô EÑEÐR`ÒaÓbÐbÜ�>‰>˜$ Ó(8Ó9Ð9ùó bs   Á%B$
é   é   é   é   é   é   é	   é
   c                 óž  — d}t        «       }t        j                  |t        j                  |j                  ¬«      }| �V| j
                  }t        | j                     }t        j                  t        |«      |gz   t        ¬«      |dt        |«      dz    t        |d¬«      }||j                  «          }t        |dd d	   «      }|dd }||fS )
ze
    Grabs the shape of `tensor` only available on one process and returns a tensor of its shape
    i   rŽ   N©r^   r   Úsum©Ú	reductionr�   r   )r   r   rh   rX   rV   r]   ÚTENSOR_TYPE_TO_INTr^   r   r7   ro   ÚreduceÚnonzero)r   Úmax_tensor_dimensionrž   Úbase_tensorr]   Útensor_dtyper^   s          r   Úgather_tensor_shaperñ   ð  sÃ   € ð
 !ÐÜ‹N€EÜ—+‘+Ð2¼%¿)¹)ÈEÏLÉLÔY€Kð
 ÐØ—‘ˆÜ)¨&¯,©,Ñ7ˆÜ(-¯©´T¸%³[ÀLÀ>Ñ5QÔY\Ô(]ˆÐ$”c˜%“j 1‘nÐ%ä˜°Ô6€KØ˜k×1Ñ1Ó3Ñ4€Kä�˜B˜CÐ  Ñ#Ó$€EØ˜c˜rÐ"€KØ˜ÐÐr   Úreturnc                 ó¾   — t        «       }t        | «      \  }}| €7t        j                  |t        |   ¬«      j                  |j                  «      } t        | d¬«      S )a�  
    Copies a tensor that only exists on a single device and broadcasts it to other devices. Differs from `broadcast` as
    each worker doesn't need to know its shape when used (and tensor can be `None`)

    Args:
        tensor (`torch.tensor`):
            The tensor that should be sent to all devices. Must only have it be defined on a single device, the rest
            should be `None`.
    rç   rè   ré   )r   rñ   r   ÚzerosÚTENSOR_INT_TO_DTYPErN   rV   rì   )r   rž   r]   r^   s       r   Úcopy_tensor_to_devicesrö   	  sP   € ô ‹N€EÜ& vÓ.�L€Eˆ5Ø€~Ü—‘˜UÔ*=¸eÑ*DÔE×HÑHÈÏÉÓVˆÜ�& EÔ*Ð*r   Úfrom_processc                 óº   — t        «       j                  t        j                  k(  rt	        | |d¬«      S t        «       j                  t
        v rt        | |¬«      S | 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Ð   )r   r«   r   rÃ   rÚ   r   rÕ   )r   r÷   s     r   rÒ   rÒ     sM   € ô ƒ~×&Ñ&¬/×*=Ñ*=Ò=Ü˜f¨,Ð=YÔZÐZÜ	‹×	(Ñ	(Ô,MÑ	MÜ˜f¨,Ô7Ð7àˆr   c                 ó,  ‡— t        «       j                  t        j                  k(  r2t	        | «      D ]"  \  }}t        j                  d|ˆfd„«      | |<   Œ$ | S t        «       j                  t        v r!t        j                  j                  | ‰¬«       | S )a–  
    Broadcast a list of picklable objects from 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 r   r¨   )rÊ   r÷   s    €r   rÜ   z'broadcast_object_list.<locals>.<lambda>?  s   ø€ ÐefÐgsÒetr   rÐ   )r   r«   r   rÃ   r²   r„   rÝ   r   r   r™   Úbroadcast_object_list)Úobject_listr÷   r·   r8   s    `  r   rû   rû   0  s�   ø€ ô ƒ~×&Ñ&¬/×*=Ñ*=Ò=Ü Ö,‰FˆAˆsÜŸ^™^Ð,TÐVYÓ[tÓuˆK˜ŠNð -ð Ðô 
‹×	(Ñ	(Ô,MÑ	MÜ×Ñ×/Ñ/°ÀÐ/ÔNØÐr   c                 ó"   — 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 r   r¨   )r   Útensor_slices     r   Ú_slice_tensorz$slice_tensors.<locals>._slice_tensorS  s   € Ø�lÑ#Ð#r   r@   )r3   rÿ   Úprocess_indexr“   r   s        r   Úslice_tensorsr  E  s   € ò$ô ˜]¨D°,Ó?Ð?r   c                 ób  ‡ ‡— t        ‰ d   t        t        f«      r.t        ‰ d   ˆ ˆfd„t	        t        ‰ d   «      «      D «       «      S t        ‰ d   t        «      rR t        ‰ d   «      ‰ d   j                  «       D ��ci c]!  }|t        ‰ D �cg c]  }||   ‘Œ	 c}‰¬«      “Œ# c}}«      S t        ‰ d   t        j                  «      rt        j                  ‰ ‰¬«      S t        ‰ t        t        f«      rt        ‰ «      dk(  r‰ d   S t        dt        ‰ d   «      › �«      ‚c c}w c c}}w )aù  
    Recursively concatenate the tensors in a nested list/tuple/dictionary of lists of tensors with the same shape.
    If there is only a single batch of data, it is returned as-is.

    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   ód   •K  — | ]"  }t        ‰D �cg c]  }||   ‘Œ	 c}‰¬ «      –— Œ$ yc c}w ­w)r�   N)Úconcatenate)rB   r·   Údr3   r‘   s      €€r   rG   zconcatenate.<locals>.<genexpr>h  s5   øè ø€ Ð#lÑXkÐST¤K¹tÓ0D¹t¸!°°1³¸tÑ0DÈ#×$NÐ$NÑXkùÒ0Dùs   ƒ0‘+
�0r�   r   z%Can only concatenate tensors but got )r   r0   r7   r:   r—   ro   r   r6   rr   r  r   r   rš   rI   )r3   r‘   rK   r  s   ``  r   r  r  Y  s  ù€ ô �$�q‘'œE¤4˜=Ô)Ü˜$˜q™'Ô#lÔX]Ô^aÐbfÐghÑbiÓ^jÔXkÓ#lÓmÐmÜ	�D˜‘GœWÔ	%ØŒt�D˜‘G‹}ÐUYÐZ[ÑU\×UaÑUaÔUcÔdÑUcÐPQ˜a¤¹DÓ-A¹D°q¨a°«d¸DÑ-AÀsÔ!KÑKÐUcÒdÓeÐeÜ	�D˜‘GœUŸ\™\Ô	*Ü�y‰y˜ 3Ô'Ð'Ü	�Dœ5¤$˜-Ô	(¬S°«Y¸!ª^Ø�A‰wˆäÐ?ÄÀTÈ!ÁWÃ¸ÐOÓPÐPùò .BùÓds   ÂD+
ÂD&ÂD+
Ä&D+
c                   ó   — e Zd Zy)ÚCannotPadNestedTensorWarningN)rJ   r¥   r¦   r¨   r   r   r  r  s  s   „ Ør   r  c                 ó,   — dd„}t        || 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.
    c                 óü  ‡‡	‡
— t        | dd«      rt        j                  dt        «       | S ‰t	        | j
                  «      k\  s‰t	        | j
                  «       k  r| S ‰dk  r‰t	        | j
                  «      z  Št        j                  | j
                  | j                  ¬«      d    }t        |«      j                  «       }t        ˆfd„|D «       «      Š	‰	| j
                  ‰   k(  r| S | j
                  Š
t        ‰
«      }‰	|‰<   | j                  t        |«      «      |z   }|r)t        ˆˆ	ˆ
fd„t        t	        |«      «      D «       «      }n't        ˆˆ
fd„t        t	        |«      «      D «       «      }| ||<   |S )	NÚ	is_nestedFzHCannot pad nested tensors without more information. Leaving unprocessed.r   )rV   c              3   ó(   •K  — | ]	  }|‰   –— Œ y ­wr   r¨   )rB   Úsr‘   s     €r   rG   zFpad_across_processes.<locals>._pad_across_processes.<locals>.<genexpr>™  s   øè ø€ Ð-¡u !�q˜•v¡uùs   ƒc              3   ób   •K  — | ]&  }|‰k(  rt        ‰‰‰   z
  ‰«      n
t        d «      –— Œ( y ­wr   ©Úslice)rB   r·   r‘   Úmax_sizeÚold_sizes     €€€r   rG   zFpad_across_processes.<locals>._pad_across_processes.<locals>.<genexpr>¢  s7   øè ø€ ð Ù`tÐ[\¸QÀ#ºX”�h ¨#¡Ñ.°Ô9Ì5ÐQUË;ÓVÑ`tùs   ƒ,/c              3   ó\   •K  — | ]#  }|‰k(  rt        d ‰‰   «      n
t        d«      –— Œ% y­w©r   Nr  ©rB   r·   r‘   r  s     €€r   rG   zFpad_across_processes.<locals>._pad_across_processes.<locals>.<genexpr>¦  s/   øè ø€ ÐoÑZnÐUV°q¸C²xœE ! X¨c¡]Ô3ÄUÈ4Ã[ÓPÑZnùó   ƒ),)ÚgetattrÚwarningsÚwarnr  ro   r]   r   r   rV   rÄ   rx   Úmaxr7   Ú	new_zerosr0   r—   )r   r‘   Ú	pad_indexÚ	pad_firstr–   ÚsizesÚnew_sizeÚ
new_tensorÚindicesr  r  s    `       @@r   Ú_pad_across_processesz3pad_across_processes.<locals>._pad_across_processesˆ  sK  ú€ Ü�6˜;¨Ô.Ü�M‰MØZÜ,ôð ˆMØ”#�f—l‘lÓ#Ò# s¬c°&·,±,Ó.?Ð-?Ò'?ØˆMà�Š7Ø”3�v—|‘|Ó$Ñ$ˆCô �|‰|˜FŸL™L°·±Ô?ÀÑEˆÜ�t“× Ñ Ó"ˆäÓ-¡uÓ-Ó-ˆØ�v—|‘| CÑ(Ò(ØˆMà—<‘<ˆÜ˜“>ˆØ ˆ�‰Ø×%Ñ%¤e¨H£oÓ6¸ÑBˆ
ÙÜõ Ü`eÔfiÐjrÓfsÔ`tóó ‰Gô ÔoÔZ_Ô`cÐdlÓ`mÔZnÓoÓoˆGØ$ˆ
�7ÑØÐr   T)r=   r‘   r  r  ©r   r   Fr@   )r   r‘   r  r  r"  s        r   Úpad_across_processesr$  w  s&   € ó" ôD Ø˜v¸4ÀSÐT]Ðirôð r   c                 ó,   — dd„}t        || d|||¬«      S )zþ
    Takes a `tensor` of arbitrary size and pads it so that it can work given `num_processes` needed dimensions.

    New tensors are just the last input repeated.

    E.g.:
      Tensor: ([3,4,4]) Num processes: 4 Expected result shape: ([4,4,4])

    c                 óF  ‡‡
— ||z  }|||z  z
  }||z  dk(  r||z
  }n|||z  z
  }|||z  cxkD  rdk  rn n||z
  }| j                   Š
t        ‰
«      }||z   |d<   | j                  t        |«      «      }t        ˆˆ
fd„t	        t        |«      «      D «       «      }	| ||	<   |S )Nr   r   c              3   ó\   •K  — | ]#  }|‰k(  rt        d ‰‰   «      n
t        d«      –— Œ% y­wr  r  r  s     €€r   rG   z@pad_input_tensors.<locals>._pad_input_tensors.<locals>.<genexpr>É  s/   øè ø€ ÐkÑVjÐQR°1¸²8œ˜a ¨#¡Ô/ÄÀtÃÓLÑVjùr  )r]   r7   r  r0   r—   ro   )r   Ú
batch_sizer“   r‘   Ú	remainderÚlast_inputsÚto_padr  r   r!  r  s      `      @r   Ú_pad_input_tensorsz-pad_input_tensors.<locals>._pad_input_tensorsº  sÀ   ù€ Ø -Ñ/ˆ	Ø  I°Ñ$=Ñ>ˆØ˜Ñ&¨!Ò+Ø" ZÑ/‰Fà" j°MÑ&AÑBˆFð ˜ &™Ô,¨1Õ,Ø  6Ñ)ˆFØ—<‘<ˆÜ˜“>ˆØ  6Ñ)ˆ�‰Ø×%Ñ%¤e¨H£oÓ6ˆ
ÜÔkÔV[Ô\_Ð`hÓ\iÔVjÓkÓkˆØ$ˆ
�7ÑØÐr   T)r=   r(  r“   r‘   rÔ   r@   )r   r(  r“   r‘   r,  s        r   Úpad_input_tensorsr-  ¯  s(   € óô& ØØØ ØØ#Øôð r   c                 ó*   — dd„}t        || d||¬«      S )aW  
    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"
        scale (`float`, *optional*):
            A default scaling value to be applied after the reduce, only valid on XLA.

    Returns:
        The same data structure as `data` with all the tensors reduced.
    c                 ó  — t        «       }| j                  «       }|j                  t        j                  k(  r|S |j                  t        j
                  k(  rOt        j                  «        t        j                  t        j                  |g|«       t        j                  «        nJ|j                  j                  t        v r.t        j                  j                  |t        j                  «       |dk(  r||j                   z  }|S )NÚmean)r   r�   r«   r   r¬   rÃ   r„   rˆ   Ú
all_reduceÚ
REDUCE_SUMÚvaluer   r   r™   r   ÚSUMr“   )r   rê   Úscalerž   Úcloned_tensors        r   Ú_reduce_across_processesz(reduce.<locals>._reduce_across_processesé  s¹   € Ü“ˆØŸ™›ˆØ×!Ñ!¤_×%7Ñ%7Ò7Ø Ð Ø×!Ñ!¤_×%8Ñ%8Ò8ô
 �L‰LŒNÜ�M‰Mœ"Ÿ-™-¨-¨¸%Ô@Ü�L‰L�NØ×#Ñ#×)Ñ)Ô-NÑNÜ×Ñ×(Ñ(¨¼¿¹ÔEØ˜ÒØ˜U×0Ñ0Ñ0ˆMØÐr   T)r=   rê   r5  ©r0  g      ð?r@   )r   rê   r5  r7  s       r   rì   rì   ×  s"   € ó$ô& Ø  &¸dÈiÐ_dôð r   c                 ó*   — d„ }d„ }t        || |¬«      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                 ó"   — | j                  «       S r   )Úfloatr   s    r   Ú_convert_to_fp32z)convert_to_fp32.<locals>._convert_to_fp32  s   € Ø�|‰|‹~Ðr   c                 ó�   — t        | «      xs t        | d«      xr, | j                  t        j                  t        j
                  fv S rg   )r   r1   r^   r   Úfloat16ry   r   s    r   Ú_is_fp16_bf16_tensorz-convert_to_fp32.<locals>._is_fp16_bf16_tensor  s@   € Ü Ó'ÒC¬7°6¸7Ó+Cò 
ÈÏÉÜ�M‰MÜ�N‰NðZ
ð J
ð 	
r   rj   r@   )r   r<  r?  s      r   Úconvert_to_fp32r@    s   € òò
ô Ð-¨vÐAUÔVÐVr   c                   ó"   — e Zd ZdZd„ Zd„ Zd„ Zy)ÚConvertOutputsToFp32ae  
    Decorator to apply to a function outputting 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                 ó*   — || _         t        | |«       y r   )Úmodel_forwardr   )ÚselfrD  s     r   Ú__init__zConvertOutputsToFp32.__init__&  s   € Ø*ˆÔÜ�t˜]Õ+r   c                 ó8   — t         | j                  |i |¤Ž«      S r   )r@  rD  )rE  rD   rF   s      r   Ú__call__zConvertOutputsToFp32.__call__*  s    € ÜÐ1˜t×1Ñ1°4ÐB¸6ÑBÓCÐCr   c                 ó,   — t        j                  d«      ‚)Nz‘Cannot pickle a prepared model with automatic mixed precision, please unwrap the model with `Accelerator.unwrap_model(model)` before pickling it.)ÚpickleÚPicklingError)rE  s    r   Ú__getstate__z!ConvertOutputsToFp32.__getstate__-  s   € Ü×"Ñ"ð `ó
ð 	
r   N)rJ   r¥   r¦   r§   rF  rH  rL  r¨   r   r   rB  rB    s   „ ñ
ò,òDó
r   rB  c                 ó6   ‡ — t        ‰ «      Š ˆ fd„}‰ |_        |S )Nc                  ó   •—  ‰| i |¤ŽS r   r¨   )rD   rF   rD  s     €r   Úforwardz(convert_outputs_to_fp32.<locals>.forward6  s   ø€ Ù˜dÐ- fÑ-Ð-r   )rB  Ú__wrapped__)rD  rO  s   ` r   Úconvert_outputs_to_fp32rQ  3  s!   ø€ Ü(¨Ó7€Mô.ð (€GÔà€Nr   c                 ó  — t        | t        «      r'| j                  «       D ]  }t        |«      }|€Œ|c S  yt        | t        t
        f«      r| D ]  }t        |«      }|€Œ|c S  yt        | t        j                  «      r| j                  S y)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   Úvaluesr®   r0   r7   r   r   rV   )r3   r8   rV   s      r   r®   r®   ?  s�   € ô �$œÔ Ø—;‘;–=ˆCÜ  Ó%ˆFØÑ!Ø’ñ !ô 
�Dœ5¤$˜-Ô	(ÛˆCÜ  Ó%ˆFØÑ!Ø’ñ ô 
�Dœ%Ÿ,™,Ô	'Ø�{‰{Ðð 
(r   c              #   óT  K  — t        «       j                  t        j                  k7  s6t        «       j                  �-t        «       j                  j                  «       st        «       }n#ddl}|j                  j                  | |||¬«      }|5  d–— ddd«       y# 1 sw Y   yxY w­w)zˆ
    Wrapper around `deepspeed.runtime.zero.GatheredParameters`, but if Zero-3 is not enabled, will be a no-op context
    manager.
    Nr   )Úmodifier_rankÚ
fwd_moduleÚenabled)
r
   r«   r   Ú	DEEPSPEEDÚdeepspeed_pluginÚis_zero3_init_enabledr   Ú	deepspeedÚzeroÚGatheredParameters)ÚparamsrU  rV  rW  Úgather_param_contextr[  s         r   r]  r]  T  s†   è ø€ ô Ó×*Ñ*¬o×.GÑ.GÒGÜÓ×+Ñ+Ð7Ü Ó"×3Ñ3×IÑIÔKä*›}Ñãà(Ÿ~™~×@Ñ@Ø -¸JÐPWð  Aó  
Ðò 
Û÷ 
×	Ñ	üs   ‚BB(ÂBÂ	B(ÂB%Â!B()FNrÔ   )r   zbroadcast tensorr   )NNr#  r8  )NNT)Yr§   rJ  r  Úcollections.abcr   Ú
contextlibr   r   Ú	functoolsr   r   Útypingr   r   rž   r
   r   Ú	constantsr   Údataclassesr   r   Úimportsr   r   r   Úversionsr   Útorch_xla.core.xla_modelÚcoreÚ	xla_modelr„   Útorch.distributedr   r   r(   r,   r4   r:   rA   rT   r`   rd   rl   rq   rt   r}   rŠ   r¢   Ú	Exceptionr¤   r½   rÁ   rÄ   rË   r¯   rÕ   rÚ   r;  ÚdoubleÚhalfry   Úuint8Úint8Úint16Úint32Úint64Úboolrë   rH   rõ   rñ   r   rö   rX   rÒ   rû   r  r  ÚUserWarningr  r$  r-  rì   r@  rB  rQ  r®   r]  )rK   rL   s   00r   Ú<module>rv     s?  ðñó Û Ý #ß 2ß +Ý ã ç 2Ý 8ß ;÷ñ õ
 'ñ Ôß)Ð)á!Ô#Ý*ò,ò
ò6ò]ò$ð 4CÐX]ô 0óf1òh8ò$/ò$bòò.ò"5ò.ò$PôN	 Iô 	ò òFð& ñó ðð&2˜só 2ð˜#ó ó&Zó:ð 
‡K�K�Ø	‡L�L�!Ø	‡J�J�Ø	‡N�N�AØ	‡K�K�Ø	‡J�J�Ø	‡K�K�Ø	‡K�K�Ø	‡K�K�Ø	‡J�J�ðÐ ð );×(@Ñ(@Ô(BÔCÑ(B¡  1�q˜!‘tÐ(BÒCÐ òñ2+¨5¯<©<ó +ð" ñ Cò ó ðñ*°Só ó*@ó(Qô4	 ;ô 	ð ò4ó ð4ón%ðP ò&ó ð&òRW÷0
ñ 
ò4	òð* òó ñùóQ Ds   ÅG