Ë
    P/æjò­  ã            
       ó>  — U d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZm	Z	m
Z
mZmZmZ d dlZd dlmZ d dlmZ ddgZ e«       s:d dlZ G d	„ d
«      Zd„ Zeej.                  d   _        eej.                  d   _        yd dlmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%  e jL                  e'«      Z(er	 d dl)m*Z*  G d„ dejZ                  «      Z. e.«       Z/e.e0d<   dde1fd„Z2 G d„ d«      Zddœde1dee3df   de
ee1df      defd„Zy# e+$ r e(jY                  d«       Y Œgw xY w)é    N)Úreduce)Úchain)ÚDictÚListÚOptionalÚTupleÚTYPE_CHECKINGÚUnion)Úis_available)Únot_noneÚinit_device_meshÚ
DeviceMeshc                   ó   — e Zd Zy)Ú_DeviceMeshStubN)Ú__name__Ú
__module__Ú__qualname__© ó    ú`/root/repos/pocs/video-evals/.venv/lib/python3.12/site-packages/torch/distributed/device_mesh.pyr   r      s   „ Ør   r   c                   ó   — y ©Nr   r   r   r   Ú_init_device_mesh_stubr      s   € Ør   ztorch.distributed.device_mesh)Ú_find_pg_by_ranks_and_tagÚ_get_default_groupÚ_get_group_tagÚget_backendÚget_process_group_ranksÚget_rankÚget_world_sizeÚinit_process_groupÚis_initializedÚ	new_groupÚProcessGroup)Ú	ArrayLikezCDeviceMesh requires numpy >= 1.21 to be installed for type checkingc            	       ó>  — e Zd Zdd„Zdd„Zdddeedf   d	eeedf      ddfd
„Z		 dddde
e   ddfd„Zdd„Zddde
e   fd„Zededefd„«       Zededefd„«       Zdddedefd„Z	 ddedede
ej&                     ddfd„Zdeeedf      fd„Zdddeded   fd„Zy)Ú_MeshEnvÚreturnNc                 óJ   — g | _         i | _        i | _        i | _        i | _        y r   )Ú
mesh_stackÚchild_to_root_mappingÚmesh_dim_group_optionsÚroot_to_flatten_mappingÚflatten_name_to_root_dims©Úselfs    r   Ú__init__z_MeshEnv.__init__A   s7   € Ø02ˆDŒOØGIˆDÔ&ð ð Ô'ð UWˆDÔ(ð ð Õ*r   r   c                 óf   — t        | j                  «      dk(  rt        d«      ‚| j                  d   S )Nr   z#No device mesh is currently active!éÿÿÿÿ)Úlenr*   ÚRuntimeErrorr/   s    r   Úget_current_meshz_MeshEnv.get_current_meshM   s.   € Ü�4—?‘?Ó# qÒ(Ü"Ð#HÓIÐIØ—?‘? 2Ñ&Ð&r   Údevice_meshÚsubmesh_dim_names.Úsubmesh_dimsc                 ó¶  ‡— |D �cg c]=  }t        |«      dkD  rt        ˆfd„|«      n‰j                  j                  |d   «      ‘Œ? }}‰j                  }g }g }d}	t	        ||«      D ]Á  \  }
}t        |
«      dkD  rv|j                  |
d   |	z
  |
d   |	z
  ¬«      }|j                  |
d   |	z
  «       |	t        |
«      dz
  z  }	|j                  | j                  ‰   |   j                  d   «       ŒŠ|j                  |
d   |	z
  «       |j                  ‰j                  |
d      «       ŒÃ t        t        |j                  «      «      }|D ]  }|j                  |«       Œ   |j                  g |¢|¢­Ž j                  dg|¢­Ž }‰j                  «       }|D ]"  }t!        ‰j"                  ||d¬«      }||v sŒ!|}Œ$ |_        ‰| j$                  |<   |S c c}w )Né   c                 ór   •— ‰j                   j                  | «      ‰j                   j                  |«      z  S r   )ÚmeshÚsize)ÚxÚyr7   s     €r   ú<lambda>z*_MeshEnv.create_sub_mesh.<locals>.<lambda>^   s/   ø€  ×!1Ñ!1×!6Ñ!6°qÓ!9¸K×<LÑ<L×<QÑ<QÐRSÓ<TÑ!T€ r   r   r3   )Ú	start_dimÚend_dimF©Úmesh_dim_namesÚ_init_backend)r4   r   r=   r>   ÚzipÚflattenÚappendr-   Ú_dim_group_infosÚlistÚrangeÚndimÚremoveÚpermuteÚreshaper   r   Údevice_typer+   )r0   r7   r8   r9   Úmesh_dimÚslice_dim_sizeÚmesh_tensorÚslice_dim_idxÚslice_dim_group_infoÚnum_dims_flattenÚmesh_dim_indicesÚmesh_dim_nameÚmesh_dims_remained_idxÚidxÚpg_ranks_by_dimÚcur_rankÚmesh_ndÚsubmeshÚres_submeshs    `                 r   Úcreate_sub_meshz_MeshEnv.create_sub_meshR   s\  ø€ ð" !-öð ô �x“= 1Ò$ô	 ÛTØôð
 !×%Ñ%×*Ñ*¨8°A©;Ó7ñ8ðˆNð ð &×*Ñ*ˆKàˆMØ#%Ð ð  !ÐÜ36°|ÐEVÓ3Wò Ñ/Ð  -ô Ð'Ó(¨1Ò,à"-×"5Ñ"5Ø"2°1Ñ"5Ð8HÑ"HØ 0°Ñ 4Ð7GÑ Gð #6ó #�Kð "×(Ñ(Ð)9¸!Ñ)<Ð?OÑ)OÔPØ$¬Ð,<Ó(=ÀÑ(AÑAÐ$Ø(×/Ñ/Ø×4Ñ4°[ÑAØ)ñç*Ñ*¨1ñ.õð "×(Ñ(Ð)9¸!Ñ)<Ð?OÑ)OÔPØ(×/Ñ/Ø#×4Ñ4Ð5EÀaÑ5HÑIõð+ô4 &*¬%°×0@Ñ0@Ó*AÓ%BÐ"Ø$ò 3�Ø&×-Ñ-¨cÕ2ð3ðÐ1˜k×1Ñ1ð Ø'ðØ*7òç‰g�bð+à)ò+ˆOð #×+Ñ+Ó-ˆHØ*ò *�Ü$Ø×+Ñ+ØØ#4Ø"'ô	�ð ˜wÒ&Ø")‘Kð*ð ,@ˆKÔ(Ø6AˆD×&Ñ& {Ñ3àÐùòIs   †AGrY   c                 óÆ  — t         j                  |«      }t        |j                  «      D �cg c]&  }t        |j                  «      j	                  |«      ‘Œ( }}|s5dj                  |D �cg c]  }t        |j                  «      |   ‘Œ c}«      }| j                  j                  |i «       t        g t        t        |j                  «      «      ¢| j                  |   j                  «       ¢­Ž }||v rt        |› d|› d�d|› d�«      ‚|| j                  v r#|| j                  |   v r| j                  |   |   S t        j                  |j                  j!                  «       «      }t        t#        |j                  j$                  «      «      }	|D ]  }
|	j'                  |
«       Œ  |j                  j(                  g |	¢|¢­Ž j+                  d|«      }|j-                  «       }|D ]"  }t/        |j0                  ||f¬«      }||v sŒ!|}Œ$ || j2                  <   || j                  j                  |i «      |<   t5        |«      | j                  |   |<   |S c c}w c c}w )NÚ_z# already exists for submesh of the ú. z5The mesh_dim_names of submesh and flattened mesh are z-. Please specify another valid mesh_dim_name.r3   ©rE   )Ú_mesh_resourcesÚget_root_meshr   rE   ÚindexÚjoinr.   Ú
setdefaultr   rK   Úkeysr5   r-   ÚmathÚprodr=   r>   rL   rM   rN   rO   rP   r   r   rQ   r+   Útuple)r0   r7   rY   Ú	root_meshÚflattened_mesh_dim_nameÚflatten_dims_in_rootÚdimÚinvalid_dim_namesÚflattened_mesh_dim_sizeÚremained_dims_in_rootÚflatten_dim_in_rootr\   r]   r^   Úflattened_meshÚres_flattened_meshs                   r   Úcreate_flatten_meshz_MeshEnv.create_flatten_mesh¢   sš  € ô (×5Ñ5°kÓBˆIô 08¸×8RÑ8RÓ/Sö$à+ô ˜×1Ñ1Ó2×8Ñ8Ð9PÕQð$Ð ð $ñ
 !Ø #§¡ð $8öàô ! ×!9Ñ!9Ó:¸3Ó?òó!�ð ×*Ñ*×5Ñ5°iÀÔDÜ %ð !Ü”h˜y×7Ñ7Ó8Ó9ð!à×/Ñ/°	Ñ:×?Ñ?ÓAò!Ðð Ð 1Ñ1Ü"Ø$�oÐ%HÈÈÐSUÐVØKÐL]ÐK^ð _Bð Cóð ð ˜T×9Ñ9Ñ9Ø! T×%AÑ%AÀ)Ñ%LÑLà×3Ñ3°IÑ>¸}ÑMÐMä&*§i¡i°×0@Ñ0@×0EÑ0EÓ0GÓ&HÐ#ä$(¬¨y¯~©~×/BÑ/BÓ)CÓ$DÐ!Ø';ò BÐ#Ø%×,Ñ,Ð-@ÕAðBð 5˜iŸn™n×4Ñ4ð Ø&ðØ)=òç‰g�bÐ1Ó2ð ð !×)Ñ)Ó+ˆHØ*ò 8�ä!+Ø×)Ñ)ØØ$1Ð#3ô"�ð
 ˜wÒ&Ø)7Ñ&ð8ð >GˆD×&Ñ&Ð'9Ñ:ØTfˆD×(Ñ(×3Ñ3°I¸rÓBÀ=ÑQÜGLÐMaÓGbˆD×*Ñ*¨9Ñ5°mÑDà%Ð%ùòw$ùòs   ­+IÁ+Ic                 óF   — | j                   j                  |d «      }|s|S |S r   )r+   Úget)r0   r7   ro   s      r   rg   z_MeshEnv.get_root_meshä   s)   € ð ×2Ñ2×6Ñ6°{ÀDÓIˆIÙ&/�;Ð>°YÐ>r   c                 óž   — | j                  |«      }|j                  }|r.|r,t        |«      dk(  sJ d«       ‚|d   }| j                  ||«      S y)zÆ
            Returns the index of the mesh dim in the root mesh.
            The device_mesh passed in needs to be sliced out from the root mesh
            or submesh of the root mesh.
            r;   z"The submesh can only be a 1D mesh.r   N)rg   rE   r4   Úget_mesh_dim_by_name)r0   r7   ro   Úchild_mesh_dim_namesÚchild_mesh_dim_names        r   Úget_root_mesh_dimz_MeshEnv.get_root_mesh_dimë   sf   € ð ×*Ñ*¨;Ó7ˆIØ#.×#=Ñ#=Ð ÙÑ1äÐ,Ó-°Ò2ð8à7ó8Ø2à&:¸1Ñ&=Ð#Ø×0Ñ0°Ð<OÓPÐPØr   rQ   c                 ó4   — t        | «      j                  «       S r   )Ú_get_device_handleÚdevice_count©rQ   s    r   Únum_devices_per_hostz_MeshEnv.num_devices_per_hostû   s   € ä% kÓ2×?Ñ?ÓAÐAr   c                 óB   — t        «       t        j                  | «      z  S r   )r    r'   r…   r„   s    r   Ú	num_hostsz_MeshEnv.num_hostsÿ   s   € ô "Ó#¤x×'DÑ'DÀ[Ó'QÑQÐQr   c                 óþ   — |j                   �t        |j                   «      dk(  rt        d«      ‚||j                   vrt        d|› d�d|j                   › �«      ‚t        |j                   j	                  |«      «      S )Nr   zNo `mesh_dim_names` found.zMesh dimension 'z' does not exist.z.Available mesh dimensions are: mesh_dim_names=)rE   r4   ÚKeyErrorr   rh   )r0   r7   rY   s      r   r}   z_MeshEnv.get_mesh_dim_by_name  sŒ   € ð ×*Ñ*Ð2Ü�{×1Ñ1Ó2°aÒ7äØ0óð ð  K×$>Ñ$>Ñ>ÜØ& } oÐ5FÐGØDÀ[×E_ÑE_ÐD`Ðaóð ô ˜K×6Ñ6×<Ñ<¸]ÓKÓLÐLr   rr   ÚbackendÚ
pg_optionsc                 ó&   — ||f| j                   |<   y r   )r,   )r0   rr   rŠ   r‹   s       r   Ú_set_mesh_dim_group_optionsz$_MeshEnv._set_mesh_dim_group_options  s   € ð 18¸Ð/DˆD×'Ñ'¨Ò,r   c                 óð  ‡	— || j                  |«      k7  rt        d«      ‚| j                  j                  |i «       | j                  |   }g |j                  ¢|¢Š	t        ˆ	fd„|D «       «      st        d|› d‰	› d�«      ‚d}g }|D ]k  }||v r||   }|d   }|j                  |«       n-|j                  j                  |«      }|j                  |f«       ||k  rt        d|› d�d|› d	�d
«      ‚|}Œm |S )z¸
            Validate whether the mesh_dim_names is valid for slicing the given device_mesh.
            If valid, return dim indexes of the slice mesh in the device mesh.
            z'Cannot create a submesh from a submesh.c              3   ó&   •K  — | ]  }|‰v –— Œ
 y ­wr   r   )Ú.0rY   Úvalid_mesh_dim_namess     €r   ú	<genexpr>z0_MeshEnv._get_slice_mesh_dims.<locals>.<genexpr>1  s   øè ø€ ò à!ð Ð!5Ô5ñùs   ƒzInvalid mesh_dim_names z% specified. Valid mesh_dim_names are ú.r3   z specified. z!Found mesh dim indices to slice: rd   z.Mesh dim indices should be in ascending order.)	rg   r5   r.   rj   rE   Úallr‰   rI   rh   )
r0   r7   rE   r.   Úcurr_idxÚslice_mesh_dimsrY   Úmesh_indicesÚnext_idxr‘   s
            @r   Ú_get_slice_mesh_dimsz_MeshEnv._get_slice_mesh_dims  s[  ø€ ð ˜d×0Ñ0°Ó=Ò=Ü"Ð#LÓMÐMð ×*Ñ*×5Ñ5°kÀ2ÔFØ(,×(FÑ(FÀ{Ñ(SÐ%ð$Ø×+Ñ+ð$à*ð$Ð ô
 ó à%3ôô ô Ø-¨nÐ-=ð >0Ø0DÐ/EÀQðHóð ð ˆHØ ˆOØ!/ò $�Ø Ð$=Ñ=Ø#<¸]Ñ#K�Lð  ,¨BÑ/�HØ#×*Ñ*¨<Õ8à*×9Ñ9×?Ñ?ÀÓN�HØ#×*Ñ*¨H¨;Ô7Ø˜xÒ'Ü"Ø1°.Ð1AÀÐNØ;¸OÐ;LÈBÐOØHóð ð
 $‘ð!$ð$ #Ð"r   c                 ór  — | j                  ||«      }|j                  j                  d|«      j                  d|j                  j	                  |«      «      }|j                  «       }g }|D ]H  }t        |j                  ||fd¬«      }||v r|j                  |   gng |_        |j                  |«       ŒJ |S )z`
            Return all the submeshes of a given mesh dimension of the device mesh.
            r3   FrD   )
r}   r=   ÚswapdimsrP   r>   r   r   rQ   rJ   rI   )	r0   r7   rY   rR   r\   r]   Úres_submeshesÚmesh_1dr_   s	            r   Ú_get_all_submeshesz_MeshEnv._get_all_submeshesR  sÒ   € ð ×0Ñ0°¸mÓLˆHØ)×.Ñ.×7Ñ7¸¸HÓE×MÑMØ�K×$Ñ$×)Ñ)¨(Ó3óˆOð #×+Ñ+Ó-ˆHØˆMØ*ò .�Ü$Ø×+Ñ+ØØ$1Ð#3Ø"'ô	�ð   7Ñ*ð !×1Ñ1°(Ñ;Ñ<àð Ô(ð
 ×$Ñ$ WÕ-ð.ð !Ð r   ©r(   N©r(   r   r   )r7   r   r(   r   )r   r   r   r1   r6   r   Ústrr   Úintra   r   ry   rg   r€   Ústaticmethodr…   r‡   r}   r$   ÚOptionsr�   r™   rž   r   r   r   r'   r'   @   s…  „ ó
	ó	'ð
N	à%ðN	ð  % S¨# X™ðN	ð ˜u S¨# X™Ñ/ð	N	ð
 óN	ðb MQñ@	&Ø+ð@	&Ø<DÀS¹Mð@	&àó@	&óD	?ð	°ð 	À(È3Á-ó 	ð  
ð	B¨cð 	B°cò 	Bó 
ð	Bð 
ð	R 3ð 	R¨3ò 	Ró 
ð	Rð
	MØ+ð	MØ<?ð	Màó	Mð* :>ñ		Eàð	Eð ð	Eð ! ×!5Ñ!5Ñ6ð		Eð
 ó	Eð2	#à�%˜˜S˜‘/Ñ"ó2	#ðh	!Ø+ð	!Ø<?ð	!à�,Ñô	!r   r'   rf   rQ   c                 ó$   — t        t        | d«      S )a:  
        Get the module corresponding to the device_type which is cuda or cuda-like device.
        For example, when the device_type is cuda, the module `torch.cuda` is returned.
        Return None when there is no corresponding module for device_type, otherwise
        return the corresponding module.
        N)ÚgetattrÚtorchr„   s    r   r‚   r‚   q  s   € ô ”u˜k¨4Ó0Ð0r   c                   ó\  — e Zd ZU dZeed<   ej                  ed<   ee	edf      ed<   dddœdede
ej                  d	f   dee	edf      d
eddf
d„Zd„ Zd„ Zd$d„Zd%d„Zdefd„Zd„ Zdedefd„Zde
ee	edf   f   dd fd„Zd&dee
eef      defd„Zdee   fd„Ze	 d&ddœde
eee   f   dedee
ej                  d	f      dee	edf      dd f
d„«       Zd&dee   defd„Zedefd„«       Zede	edf   fd„«       Z defd„Z!d&dee
eef      defd „Z"deee      fd!„Z#d&d"ee   dd fd#„Z$y)'r   aÈ  
        DeviceMesh represents a mesh of devices, where layout of devices could be
        represented as a n-d dimension array, and each value of the n-d dimensional
        array is the global id of the default process group ranks.

        DeviceMesh could be used to describe the layout of devices across the cluster,
        and serves as a proxy for communication among the device lists within the cluster.

        DeviceMesh can be used as a context manager.

        .. note::
            DeviceMesh follows SPMD programming model, which means the same PyTorch Python program
            is running on all processes/ranks in the cluster. Therefore, users need to make sure the
            `mesh` array (which describes the layout of devices) should be identical across all ranks.
            Inconsistent `mesh` will lead to silent hang.

        Args:
            device_type (str): The device type of the mesh. Currently supports: "cpu", "cuda/cuda-like".
            mesh (ndarray): A multi-dimensional array or an integer tensor describing the layout
                of devices, where the IDs are global IDs of the default process group.

        Returns:
            DeviceMesh: A :class:`DeviceMesh` object representing the device layout.

        The following program runs on each process/rank in an SPMD manner. In this example, we have 2
        hosts with 4 GPUs each.
        A reduction over the first dimension of mesh will reduce across
        columns (0, 4), .. and (3, 7), a reduction over the second dimension
        of mesh reduces across rows (0, 1, 2, 3) and (4, 5, 6, 7).

        Example::
            >>> # xdoctest: +SKIP("no rank")
            >>> from torch.distributed.device_mesh import DeviceMesh
            >>>
            >>> # Initialize device mesh as (2, 4) to represent the topology
            >>> # of cross-host(dim 0), and within-host (dim 1).
            >>> mesh = DeviceMesh(device_type="cuda", mesh=[[0, 1, 2, 3],[4, 5, 6, 7]])
        rQ   r=   .rE   NTrD   r%   rF   r(   c                óœ  — || _         t        |t        j                  «      r'|j                  j
                  dk7  rt        d|› �«      ‚t        |t        j                  «      r.|j                  «       j                  t        j                  ¬«      n%t        j                  |dt        j                  ¬«      | _        |rt        |«      nd | _        t        | j                  j                  «       j                  «       «      | _        d | _        |dk7  r»|r | j%                  «        | j'                  «        t)        «       r&t+        «       dk(  rt-        j.                  «       | _        | j                  t1        «       k(  j3                  «       }|j5                  d«      dv sJ ‚|j5                  d«      dkD  r|d   j                  «       nd | _        y y )	NÚcpuz!`mesh` must be a CPU tensor, got ©Údtype©Údevicer¬   ÚxlaÚthreadedr   )r   r;   )rQ   Ú
isinstancer§   ÚTensorr®   ÚtypeÚ
ValueErrorÚdetachÚtor¢   Útensorr=   rn   rE   rH   ÚtolistÚ_flatten_mesh_listÚ
_thread_idÚ_get_or_create_default_groupÚ_init_process_groupsr"   r   Ú	threadingÚ	get_identr   Únonzeror>   Ú_coordinate_on_dim)r0   rQ   r=   rE   rF   Úrank_coordss         r   r1   zDeviceMesh.__init__¦  sq  € ð  +ˆDÔÜ˜$¤§¡Ô-°$·+±+×2BÑ2BÀeÒ2KÜ Ð#DÀTÀFÐ!KÓLÐLô ˜d¤E§L¡LÔ1ð —‘“× Ñ ¤u§y¡yÐ Ô1ä—\‘\ $¨u¼E¿I¹IÔFð ŒIñ
 <J¤%¨Ô"7ÈtˆDÔô ',¨D¯I©I×,=Ñ,=Ó,?×,FÑ,FÓ,HÓ&IˆDÔ#Ø"ˆDŒOð ˜eÒ#ñ !Ø×5Ñ5Ô7Ø×-Ñ-Ô/ä!Ô#¬«¸Ò(CÜ&/×&9Ñ&9Ó&;�D”Oð  $Ÿy™y¬H«JÑ6×?Ñ?ÓA�Ø"×'Ñ'¨Ó*¨fÑ4Ð4Ð4à/:×/?Ñ/?ÀÓ/BÀQÒ/F�K ‘N×)Ñ)Ô+ÈDð Õ'ð $r   c           	      óÆ  — t        «       }|s
t        «        t        «       }| j                  j	                  «       |kD  r*t        d|› d| j                  j	                  «       › d�«      ‚t        | j                  «      }|sZ|rX|j                  «       }||kD  r'||z  dk7  rt        d|› d|› d| j                  › d�«      ‚|j                  t        «       |z  «       t        «       S )	Nz2Mesh should not be bigger than default world size z, but found z ranks!r   z8DeviceMesh only support homogeneous hardware, but found z ranks and ú z	 devices!)r"   r!   r    r=   Únumelr5   r‚   rQ   rƒ   Ú
set_devicer   r   )r0   Údefault_initializedÚ
world_sizeÚdevice_handler…   s        r   r»   z'DeviceMesh._get_or_create_default_groupÐ  sô   € Ü"0Ó"2ÐÙ&Ü"Ô$ä'Ó)ˆJØ�y‰y�‰Ó  :Ò-Ü"ØHÈÈÐT`Ðae×ajÑaj×apÑapÓarÐ`sÐszÐ{óð ô /¨t×/?Ñ/?Ó@ˆMá&©=ð (5×'AÑ'AÓ'CÐ$àÐ!5Ò5Ø"Ð%9Ñ9¸QÒ>ä&ØRØ%˜, kÐ2FÐ1GÀqÈ×IYÑIYÐHZÐZcðeóð ð ×(Ñ(¬«Ð6JÑ)JÔKä%Ó'Ð'r   c           	      ó  — g }| j                   j                  dk(  rµ| j                   j                  «       t        «       k(  r�t	        «       }t        t        t        «       «      «      }t        j                  j                  «       rt        |«      dk(  rt        d|¬«      n|}|j                  t        |«      ||j                  f«       || _        y t        | j                   j                  «      D �]  }| j                   j                  d|«      j!                  d| j                   j#                  |«      «      }|D ]¿  }|j%                  «       }|t&        j(                  v rt&        j(                  |   \  }	}
nd\  }	}
t        ||	|
¬«      }| j+                  «       |v sŒbt-        |«      |kD  r t/        d| j+                  «       › d	|› d
�«      ‚|j                  t        t1        |«      «      ||j                  f«       ŒÁ �Œ || _        y )Nr;   Úgloozcpu:gloo,cuda:nccl)rŠ   Úranksr3   )NN)rË   rŠ   r‹   zFEach device mesh dimension should get only one process group, but got z in ú!)r=   rM   rÄ   r    r   rK   rL   r§   Úcudar   r   r#   rI   r   Ú
group_namer›   rP   r>   r¸   rf   r,   r   r4   r5   r   rJ   )r0   Údim_group_infosÚdefault_grouprË   Ú	dim_grouprr   r\   Údim_meshÚsubgroup_ranksrŠ   r‹   s              r   r¼   zDeviceMesh._init_process_groupsí  sû  € ð ACˆOà�y‰y�~‰~ Ò" t§y¡y§¡Ó'8¼NÓ<LÒ'Lô !3Ó 4�ÜœU¤>Ó#3Ó4Ó5�ô —z‘z×.Ñ.Ô0Ü# MÓ2°fÒ<ô Ð&:À%ÕHð 'ð	 ð  ×&Ñ&ä& yÓ1ØØ!×,Ñ,ðôðj %4ˆDÕ!ôY ! §¡§¡Ó0ó +�Cð '+§i¡i×&8Ñ&8¸¸SÓ&A×&IÑ&IØ˜DŸI™IŸN™N¨3Ó/ó'�Oð
 %4ò #˜Ø)1¯©Ó):˜ð ¤/×"HÑ"HÑHô !0× FÑ FÀsÑ KñØ 'Ù *ð 3=Ñ/˜G Zô
 %.Ø"0Ø$+Ø'1ô%˜	ð  Ÿ=™=›?¨nÒ<Ü" ?Ó3°cÒ9Ü&2Ø&lÐmq×mzÑmzÓm|Ðl}ð ~*Ø*8Ð)9¸ð%<ó'"ð !"ð ,×2Ñ2ä$2´8¸IÓ3FÓ$GØ$2Ø$-×$8Ñ$8ð!"õò;#ð+ðX %4ˆDÕ!r   c                 óD   — t         j                  j                  | «       | S r   )rf   r*   rI   r/   s    r   Ú	__enter__zDeviceMesh.__enter__8  s   € ä×&Ñ&×-Ñ-¨dÔ3ØˆKr   c                 ó@   — t         j                  j                  «        y r   )rf   r*   Úpop)r0   Úexc_typeÚ	exc_valueÚexc_tracebacks       r   Ú__exit__zDeviceMesh.__exit__>  s   € ä×&Ñ&×*Ñ*Õ,r   c                 óè   — | j                   s-d| j                  › d| j                  j                  «       › d�}|S d| j                  › d| j                  j                  «       › d| j                   › d�}|S )NzDeviceMesh('z', ú)z, mesh_dim_names=)rE   rQ   r=   r¸   )r0   Údevice_mesh_reprs     r   Ú__repr__zDeviceMesh.__repr__B  s‰   € ð ×*Ò*ð ˜t×/Ñ/Ð0°°D·I±I×4DÑ4DÓ4FÐ3GÀqÐIð ð
 $Ð#ð $ D×$4Ñ$4Ð#5°S¸¿¹×9IÑ9IÓ9KÐ8LÐL]Ð^b×^qÑ^qÐ]rÐrsÐtð ð
 $Ð#r   c                 óø   — t        | dd «      | _        | j                  sQt        | j                  | j                  j
                  | j                  | j                  | j                  f«      | _        | j                  S )NÚ_hash)	r¦   rá   Úhashr¹   r=   ÚshaperQ   rE   rº   r/   s    r   Ú__hash__zDeviceMesh.__hash__J  sc   € ä   w°Ó5ˆDŒJØ—:’:Ü!à×/Ñ/ØŸ	™	Ÿ™Ø×(Ñ(Ø×+Ñ+ØŸ™ðó�”
ð —:‘:Ðr   Úotherc                 ó†  — t        |t        «      syt        | «      t        |«      k(  ry| j                  |j                  k(  xr~ | j                  j
                  |j                  j
                  k(  xrO | j                  |j                  k(  xr4 | j                  |j                  k(  xr | j                  |j                  k(  S )NFT)	r±   r   Úidr¹   r=   rã   rQ   rE   rº   )r0   rå   s     r   Ú__eq__zDeviceMesh.__eq__Y  s©   € Ü˜e¤ZÔ0ØÜ�$‹xœ2˜e›9Ò$Øð ×+Ñ+¨u×/GÑ/GÑGò <ØŸ	™	Ÿ™¨5¯:©:×+;Ñ+;Ñ;ò<à×(Ñ(¨E×,=Ñ,=Ñ=ò<ð ×+Ñ+¨u×/CÑ/CÑCò<ð Ÿ™¨5×+;Ñ+;Ñ;ðr   c                 óÚ   — | j                   st        d«      ‚t        |t        «      r|fn|}|| j                   k(  r| S t        j                  | |«      }t        j                  | ||«      }|S )aU
  
            Slice the current DeviceMesh based on the mesh_dim_names given to create a submesh.
            The submesh created consists of the dimensions and the communicators indicated by
            ``mesh_dim_names``

            Args:
                mesh_dim_names (Union[str, Tuple[str]]): the name or the tuple of names of the
                mesh dimension of the DeviceMesh to create the submesh for.
            Returns:
                A :class:`DeviceMesh` object

            The following program runs on each process/rank in an SPMD manner in a world size of 8.
            In the first example:
                Calling mesh_2d["tp"] on rank 0, 1, 2, 3 returns a 1D submesh of DeviceMesh:([0, 1, 2, 3]).
                Calling mesh_2d["tp"] on rank 4, 5, 6, 7 returns a 1D submesh of  DeviceMesh:([4, 5, 6, 7]).
                Calling mesh_2d["dp"] on rank 0, 4 returns a 1D submesh of  DeviceMesh:([0, 4]).
                Calling mesh_2d["dp"] on rank 1, 5 returns a 1D submesh of  DeviceMesh:([1, 5]).
                Calling mesh_2d["dp"] on rank 2, 6 returns a 1D submesh of  DeviceMesh:([2, 6]).
                Calling mesh_2d["dp"] on rank 3, 7 returns a 1D submesh of  DeviceMesh:([3, 7]).

            In the second example:
                Calling mesh_3d["dp", "cp"] on rank 0, 1, 4, 5 returns a 2D submesh of DeviceMesh:([[0, 1], [4, 5]]).
                Calling mesh_3d["dp", "cp"] on rank 2, 3, 6, 7 returns a 2D submesh of DeviceMesh:([[2, 3], [6, 7]]).
                Calling mesh_3d["cp", "dp"] on rank 0, 1, 4, 5 returns a 2D submesh of DeviceMesh:([[0, 4], [1, 5]]).
                Calling mesh_3d["cp", "dp"] on rank 2, 3, 6, 7 returns a 2D submesh of DeviceMesh:([[2, 6], [3, 7]]).

            Example::
                >>> # xdoctest: +SKIP("no rank")
                >>> from torch.distributed.device_mesh import DeviceMesh
                >>>
                >>> # Initialize a 2D device mesh as (2, 4) to represent the topology
                >>> # of cross-host(dim 0), and within-host (dim 1).
                >>> mesh_2d = init_device_mesh(device_type="cuda", (2,4), mesh_dim_names=("dp", "tp"))
                >>> tp_mesh = mesh_2d["tp"]
                >>> dp_mesh = mesh_2d["dp"]
                >>>
                >>> # Initialize a 3D mesh.
                >>> mesh_3d = init_device_mesh(device_type="cuda", (2,2,2), mesh_dim_names=("dp", "pp", "cp"))
                >>> # The order of the mesh_dim_names provided deteremines the order of dimensions in the submesh.
                >>> dp_cp_mesh = mesh_3d["dp", "cp"]
                >>> cp_dp_mesh = mesh_3d["cp", "dp"]
            z1Cannot slice a DeviceMesh without mesh_dim_names!)rE   r5   r±   r¡   rf   r™   ra   )r0   rE   r–   r_   s       r   Ú__getitem__zDeviceMesh.__getitem__g  s|   € ðZ ×&Ò&Ü"Ð#VÓWÐWô &0°ÄÔ%D�Ñ!È.ð ð  ×!4Ñ!4Ò4Ø�ä"1×"FÑ"FØ˜.ó#�ô *×9Ñ9Ø˜.¨/ó�ð �r   rR   c                 ó˜  — t        | d«      st        d«      ‚| j                  j                  dkD  r'|€%t        d| j                  j                  › d�dd«      ‚| j                  j                  dk(  r#|€!t	        t        | j                  d	   dd
 Ž «      S t        j                  | «      }t        j                  j                  |d«      }|r8||j                  «       v r&||   j                  d	   dd
 }t	        t        |Ž «      S t        |t        «      rt        j                  | |«      n|}t	        t        | j                  |   dd
 Ž «      S )aÂ  
            Returns the single ProcessGroup specified by mesh_dim, or, if mesh_dim is not specified and the
            DeviceMesh is 1-dimensional, returns the only ProcessGroup in the mesh.

            Args:
                mesh_dim (str/int, optional): it can be the name of the mesh dimension or the index
                of the mesh dimension. Default is None.

            Returns:
                A :class:`ProcessGroup` object.
            rJ   z*DeviceMesh process groups not initialized!r;   NúFound the DeviceMesh have ú dimensionsúJOptional kwarg `mesh_dim` needs to be specified when device_mesh.ndim > 1.zmIf you want to get the list of all the ProcessGroups in the DeviceMesh,please use `get_all_groups()` instead.r   é   )Úhasattrr5   r=   rM   r   r   rJ   rf   rg   r-   r{   rk   r±   r¡   r}   )r0   rR   ro   r-   rÏ   s        r   Ú	get_groupzDeviceMesh.get_group¦  s\  € ô ˜4Ð!3Ô4Ü"Ð#OÓPÐPà�y‰y�~‰~ Ò! hÐ&6Ü"Ø0°·±·±Ð0@ÀÐLØ`ð=óð ð �y‰y�~‰~ Ò" xÐ'7ÜÜ-¨t×/DÑ/DÀQÑ/GÈÈÐ/KÐLóð ô (×5Ñ5°dÓ;ˆIÜ&5×&MÑ&M×&QÑ&QØ˜4ó'Ð#ñ '¨8Ð7N×7SÑ7SÓ7UÑ+UØ"9¸(Ñ"C×"TÑ"TÐUVÑ"WÐXZÐYZÐ"[�ÜÔ 9¸?Ð KÓLÐLô " (¬CÔ0ô $×8Ñ8¸¸xÔHà!ð ô
  Ü-¨t×/DÑ/DÀXÑ/NÈrÐPQÐ/RÐSóð r   c                 ó„   — t        | j                  j                  «      D �cg c]  }| j                  |«      ‘Œ c}S c c}w )z 
            Returns a list of ProcessGroups for all mesh dimensions.

            Returns:
                A list of :class:`ProcessGroup` object.
            )rL   r=   rM   rñ   )r0   Úis     r   Úget_all_groupszDeviceMesh.get_all_groupsÔ  s.   € ô 05°T·Y±Y·^±^Ó/DÖE¨!�D—N‘N 1Õ%ÒEÐEùÒEs   ¢=re   Úgroupc                óÔ  — t        | t        «      r®t        | «      }t        |t        j                  «      r|j                  «       |k7  s|�||k7  rt        dt        |«      › d|› �«      ‚t        j                  |dt        j                  ¬«      }t        |||d¬«      }t        | «      || j                  fg|_        |S t        | «      }t        |«      dk(  rt        d«      ‚|€t        d	«      ‚t        |t        j                  «      r/|j!                  «       j#                  t        j                  d¬
«      n%t        j                  |dt        j                  ¬«      }|j$                  t        |«      k7  r)t        d|j                  «       › dt        |«      › d�«      ‚t        |||d¬«      }|D � cg c]#  } t        | «      t        | «      | j                  f‘Œ% c} |_        |S c c} w )aM  
            Constructs a :class:`DeviceMesh` with ``device_type`` from an
            existing :class:`ProcessGroup`.

            The constructed device mesh has number of dimensions equal to the
            number of groups passed. If more than one group is passed, then the
            ``mesh`` argument is required.
            zInvalid mesh z for ProcessGroup with ranks rª   r­   FrD   r   z.Expects at least one ProcessGroup to be passedz0Must pass mesh if passing multiple ProcessGroups)r¬   r®   zEExpects mesh with ndim equal to number of ProcessGroups but got mesh z and z ProcessGroups)r±   r$   r   r§   r²   r¸   r´   r¡   r·   r¢   r   r   rÎ   rJ   rK   r4   rµ   r¶   rM   )rõ   rQ   r=   rE   Úgroup_ranksr7   Úgroupss          r   Ú
from_groupzDeviceMesh.from_groupÝ  sÒ  € ô  ˜%¤Ô.Ü5°eÓ<�ä˜t¤U§\¡\Ô2°t·{±{³}ÈÒ7SØÐ&¨4°;Ò+>Ü$Ø'¬¨D«	 {Ð2OÐP[È}Ð]óð ô —|‘| K¸ÄUÇYÁYÔO�Ü(ØØØ#1Ø"'ô	�ô $ EÓ*¨K¸×9IÑ9IÐJð0�Ô,ð #Ð"Ü˜%“[ˆFÜ�6‹{˜aÒÜ Ð!QÓRÐRØˆ|Ü Ð!SÓTÐTô ˜d¤E§L¡LÔ1ð —‘“× Ñ ¤u§y¡y¸Ð Ô?ä—\‘\ $¨u¼E¿I¹IÔFð ð
 �y‰yœC ›KÒ'Ü ðØ ŸK™K›M˜?¨%´°F³¨}¸NðLóð ô %Ø˜T°.ÐPUôˆKð $ö,ð ô	 # 5Ó)Ü+¨EÓ2Ø×$Ñ$òò,ˆKÔ(ð Ðùò,s   Æ3(G%c                 óp   — |€| j                   j                  «       S | j                   j                  |«      S r   )r=   rÄ   r>   )r0   rR   s     r   r>   zDeviceMesh.size  s*   € Ø(0Ð(8�4—9‘9—?‘?Ó$ÐV¸d¿i¹i¿n¹nÈXÓ>VÐVr   c                 ó.   — | j                   j                  S r   )r=   rM   r/   s    r   rM   zDeviceMesh.ndim  s   € à—9‘9—>‘>Ð!r   c                 ó@   — t        | j                  j                  «      S r   )rn   r=   rã   r/   s    r   rã   zDeviceMesh.shape#  s   € ä˜Ÿ™Ÿ™Ó)Ð)r   c                 ó   — t        «       S )z:
            Returns the current global rank.
            )r   r/   s    r   r   zDeviceMesh.get_rank'  s   € ô “:Ðr   c                 óþ   — | j                   dkD  r&|€$t        d| j                  j                   › d�d«      ‚|€d}t        | j	                  |«      «      }t        |t        «      sJ d«       ‚t        t        |«      «      S )a{  
            Returns the local rank of the given mesh_dim of the DeviceMesh.

            Args:
                mesh_dim (str/int, optional): it can be the name of the mesh dimension or the index
                of the mesh dimension. Default is None.

            Returns:
                An integer denotes the local rank.

            The following program runs on each process/rank in an SPMD manner. In this example, we have 2
            hosts with 4 GPUs each.
            Calling mesh_2d.get_local_rank(mesh_dim=0) on rank 0, 1, 2, 3 would return 0.
            Calling mesh_2d.get_local_rank(mesh_dim=0) on rank 4, 5, 6, 7 would return 1.
            Calling mesh_2d.get_local_rank(mesh_dim=1) on rank 0, 4 would return 0.
            Calling mesh_2d.get_local_rank(mesh_dim=1) on rank 1, 5 would return 1.
            Calling mesh_2d.get_local_rank(mesh_dim=1) on rank 2, 6 would return 2.
            Calling mesh_2d.get_local_rank(mesh_dim=1) on rank 3, 7 would return 3.

            Example::
                >>> # xdoctest: +SKIP("no rank")
                >>> from torch.distributed.device_mesh import DeviceMesh
                >>>
                >>> # Initialize device mesh as (2, 4) to represent the topology
                >>> # of cross-host(dim 0), and within-host (dim 1).
                >>> mesh = DeviceMesh(device_type="cuda", mesh=[[0, 1, 2, 3],[4, 5, 6, 7]])
            r;   rì   rí   rî   r   z1We expect ProcessGroup before calling `get_rank`!)rM   r5   r=   r   rñ   r±   r$   r   )r0   rR   Úmesh_dim_groups      r   Úget_local_rankzDeviceMesh.get_local_rank-  sŒ   € ð8 �y‰y˜1Š} Ð!1Ü"Ø0°·±·±Ð0@ÀÐLØ`óð ð Ð!Ø�ä% d§n¡n°XÓ&>Ó?ˆNÜØ¤ôð CàBóCð ô œH ^Ó4Ó5Ð5r   c                 ó6   — | j                   r| j                   S dS )z©
            Return the relative indices of this rank relative to all
            dimensions of the mesh. If this rank is not part of the mesh, return None.
            N)rÀ   r/   s    r   Úget_coordinatezDeviceMesh.get_coordinateW  s   € ð
 /3×.EÒ.E�4×*Ñ*ÐOÈ4ÐOr   rY   c                 ó\   — | j                   st        d«      ‚t        j                  | |«      S )a\  
            Returns a 1D DeviceMesh by flattening the current DeviceMesh.

            If no mesh_dim_name is provided, the default is a string concatentaing the mesh_dim_names of the
            given submesh with each mesh_dim_name separated by "_". For example, if we have a 3D mesh
            DeviceMesh([[[0, 1], [2, 3]], [[4, 5], [6, 7]]], mesh_dim_names=("dp", "cp", "tp")), calling
            mesh_3d["dp", "cp"]._flatten() will create a 1D submesh DeviceMesh([0, 1, 2, 3], mesh_dim_names=("dp_cp",))
            on rank 0, 1, 2, 3 and a 1D submesh DeviceMesh([4, 5, 6, 7], mesh_dim_names=("dp_cp",)) on rank 4, 5, 6, 7.

            After the flattened dimension is created, to access the flattened dimesnion in mesh_3d, one can use the
            existing slicing method to obtain the flattened mesh through calling mesh_3d["dp_cp"].
            z3Cannot flatten a DeviceMesh without mesh_dim_names!)rE   r5   rf   ry   )r0   rY   s     r   Ú_flattenzDeviceMesh._flatten^  s2   € ð ×&Ò&Ü"ØIóð ô #×6Ñ6°t¸]ÓKÐKr   r    rŸ   r   )%r   r   r   Ú__doc__r¡   Ú__annotations__r§   r²   r   r   r
   Úboolr1   r»   r¼   rÕ   rÛ   rß   rä   Úobjectrè   rê   r¢   r$   rñ   r   rô   r£   rù   r>   ÚpropertyrM   rã   r   r   r  r  r   r   r   r   r   z  sV  … ñ%	ðN ÓØ�l‰lÓØ   s¨C x¡Ñ1Ó1ð 9=Ø"&ò(	àð(	ð ˜Ÿ™ kÐ1Ñ2ð(	ð
 % U¨3°¨8¡_Ñ5ð(	ð  ð(	ð ó(	òT	(ò:I	4óV	ó	-ð	$˜có 	$ò	ð	 ð 	¨4ó 	ð=	Ø"'¨¨U°3¸°8©_Ð(<Ñ"=ð=	àó=	ñ~,	 h¨u°S¸#°X©Ñ&?ð ,	È<ó ,	ð\	F D¨Ñ$6ó 	Fð 
ð @Dð<	ð
 9=ò<	Ø˜ t¨LÑ'9Ð9Ñ:ð<	àð<	ð ˜5 §¡¨{Ð!:Ñ;Ñ<ð<	ð
 % U¨3°¨8¡_Ñ5ð<	ð ò<	ó 
ð<	ñ|	W ¨#¡ð 	W¸#ó 	Wð 
ð	"˜#ò 	"ó 
ð	"ð 
ð	*˜5  c ™?ò 	*ó 
ð	*ð	˜có 	ñ(	6¨8°E¸#¸s¸(±OÑ+Dð (	6ÐPSó (	6ðT	P H¨T°#©YÑ$7ó 	Pñ	L¨(°3©-ð 	LÀ<ô 	Lr   re   Ú
mesh_shape.rE   r(   c          	      ó"  — |�kt        t        |«      «      t        |«      k7  rt        dd|› �«      ‚t        |«      t        |«      k7  r%t        ddt        |«      › dt        |«      › d�«      ‚| r | j                  «       st        d| › d	�d
«      ‚t	        j
                  d«      5  t	        j                  t        j                  |«      t        j                  ¬«      j                  |«      }ddd«       t        | |¬«      }|S # 1 sw Y   ŒxY w)a¤  
        Initializes a `DeviceMesh` based on `device_type`, `mesh_shape`, and `mesh_dim_names` parameters.

        This creates a DeviceMesh with an n-dimensional array layout, where `n` is the length of `mesh_shape`.
        If `mesh_dim_names` is provided, each dimension is labeled as `mesh_dim_names[i]`.

        .. note::
            `init_device_mesh` follows SPMD programming model, meaning the same PyTorch Python program
            runs on all processes/ranks in the cluster. Ensure `mesh_shape` (the dimensions of the nD array
            describing device layout) is identical across all ranks. Inconsistent `mesh_shape` may lead to hanging.

        .. note::
            If no process group is found, init_device_mesh will initialize distributed process group/groups
            required for distributed communications behind the scene.

        Args:
            device_type (str): The device type of the mesh. Currently supports: "cpu", "cuda/cuda-like".
                Passing in a device type with a GPU index, such as "cuda:0", is not allowed.
            mesh_shape (Tuple[int]): A tuple defining the dimensions of the multi-dimensional array
                describing the layout of devices.
            mesh_dim_names (Tuple[str], optional): A tuple of mesh dimension names to assign to each dimension
                of the multi-dimensional array describing the layout of devices. Its length must match the length
                of `mesh_shape`. Each string in `mesh_dim_names` must be unique.

        Returns:
            DeviceMesh: A :class:`DeviceMesh` object representing the device layout.

        Example::
            >>> # xdoctest: +SKIP("no rank")
            >>> from torch.distributed.device_mesh import init_device_mesh
            >>>
            >>> mesh_1d = init_device_mesh("cuda", mesh_shape=(8,))
            >>> mesh_2d = init_device_mesh("cuda", mesh_shape=(2, 8), mesh_dim_names=("dp", "tp"))

        Nz"Each mesh_dim_name must be unique.z/Found repeated mesh_dim_name in mesh_dim_names z6mesh_shape and mesh_dim_names should have same length!zFound len(mesh_dim_names): z and len(mesh_shape):r“   z4Device type with GPU index is not supported but got rd   zUIf you maintained a 'torch.device' object, it's recommended to pass in 'device.type'.rª   r«   )rQ   r=   rE   )r4   Úsetr5   Úisalphar§   r®   Úarangerl   rm   r¢   Úviewr   )rQ   r
  rE   r=   r7   s        r   r   r   r  s  € ðR Ð%Ü”3�~Ó&Ó'¬3¨~Ó+>Ò>Ü"Ø8ØEÀnÐEUÐVóð ô
 �:‹¤# nÓ"5Ò5Ü"ØLØ1´#°nÓ2EÐ1FÐF[Ô\_Ð`jÓ\kÐ[lÐlmÐnóð ñ ˜{×2Ñ2Ô4ÜØFÀ{ÀmÐSUÐVØgóð ô �\‰\˜%Ó ñ 	YÜ—<‘<¤§	¡	¨*Ó 5¼U¿Y¹YÔG×LÑLÈZÓXˆD÷	Yä Ø#ØØ)ô
ˆð Ð÷	Yð 	Yús   Â%ADÄD)rÍ   )4Úloggingrl   r½   Ú	functoolsr   Ú	itertoolsr   Útypingr   r   r   r   r	   r
   r§   Útorch.distributedr   Útorch.utils._typing_utilsr   Ú__all__Úsysr   r   Úmodulesr   r   Ú"torch.distributed.distributed_c10dr   r   r   r   r   r   r    r!   r"   r#   r$   Ú	getLoggerr   ÚloggerÚnumpy.typingr%   ÚImportErrorÚwarningÚlocalr'   rf   r  r¡   r‚   r¢   r   r   r   ú<module>r      sR  ðô Û Û Ý Ý ß D× Dã Ý *Ý .ð ˜|Ð
,€ñ „~Û÷ñ òð ?N€C‡K�KÐ/Ñ0Ô;ð 0ð ‡K�KØ'ñå÷÷ ÷ ñ ð ˆW×Ñ˜xÓ(€Fñ ð	Ý.ôm!�9—?‘?ô m!ñ^	 !)£
€O�XÓ*ñ1¨ó 1÷vLñ vLðx 59ò	GØðGà˜#˜s˜(‘OðGð !  s¨C x¡Ñ1ð	Gð
 
ôGøðo ò 	Ø�N‰NØUöð	ús   Â.D ÄDÄD