
    IЦi              
       l   % S SK r S SKrS SKrS SKJr  S SKJr  S SKJrJ	r	J
r
JrJrJr  S SKrS SKJr  S SKJr  SS/r\" 5       (       d:  S SKr " S	 S
5      rS r\\R.                  S   l        \\R.                  S   l        gS SKJr  S SKJrJrJ r J!r!J"r"J#r#J$r$J%r%J&r&J'r'J(r(J)r)  \ RT                  " \+5      r,\(       a   S SK-J.r.   " S S\Rb                  5      r2\2" 5       r3\2\4S'   SS\54S jjr6 " S S5      rSS.S\5S\\7S4   S\
\\5S4      S\4S jjrg! \/ a    \,Ra                  S5         Nlf = f)    N)reduce)chain)DictListOptionalTupleTYPE_CHECKINGUnion)is_available)not_noneinit_device_mesh
DeviceMeshc                       \ rS rSrSrg)_DeviceMeshStub    N)__name__
__module____qualname____firstlineno____static_attributes__r       \/var/www/html/ai-image-ml/venv/lib/python3.13/site-packages/torch/distributed/device_mesh.pyr   r      s    r   r   c                      g Nr   r   r   r   _init_device_mesh_stubr      s    r   ztorch.distributed.device_mesh)Backend)_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split_group)	ArrayLikezCDeviceMesh requires numpy >= 1.21 to be installed for type checkingc            	       b   \ rS rSrSS jrSS jrSSS\\S	4   S
\\\	S	4      SS4S jr
 SSSS\\   SS4S jjrSS jrSSS\\	   4S jr\S\S\	4S j5       r\S\S\	4S j5       rSSS\S\	4S jr SS\	S\S\\R(                     SS4S jjrS\\\	S	4      4S jrSSS\S\S   4S jrSrg)_MeshEnvB   returnNc                 J    / U l         0 U l        0 U l        0 U l        0 U l        g r   )
mesh_stackchild_to_root_mappingmesh_dim_group_optionsroot_to_flatten_mappingflatten_name_to_root_dimsselfs    r   __init___MeshEnv.__init__C   s7    02DOGID&  ' UWD(  *r   r   c                 h    [        U R                  5      S:X  a  [        S5      eU R                  S   $ )Nr   z#No device mesh is currently active!)lenr0   RuntimeErrorr5   s    r   get_current_mesh_MeshEnv.get_current_meshO   s.    4??#q("#HII??2&&r   device_meshsubmesh_dim_names.submesh_dimsc                 n  ^ U Vs/ s H  n[        U4S jUS5      PM     nnTR                  n/ n/ nSn	[        X25       H  u  p[        U
5      S:  at  UR	                  U
S   U	-
  U
S   U	-
  S9nUR                  U
S   U	-
  5        U	[        U
5      S-
  -  n	UR                  U R                  T   U   R                  S   5        M  UR                  U
S   U	-
  5        UR                  TR                  U
S      5        M     [        [        UR                  5      5      nU H  nUR                  U5        M     UR                  " / UQUQ76 R                  " S/UQ76 nTR                  5       nU H#  n[        TR                   UUSS9nUU;   d  M!  UnM%     UWl        TU R"                  U'   U$ s  snf )Nc                 @   > U TR                   R                  U5      -  $ r   )meshsize)xyr?   s     r   <lambda>*_MeshEnv.create_sub_mesh.<locals>.<lambda>`   s    [%5%5%:%:1%=!=r      r   r:   )	start_dimend_dimFmesh_dim_names_init_backend)r   rD   zipr;   flattenappendr3   _dim_group_infoslistrangendimremovepermutereshaper#   r   device_typer1   )r6   r?   r@   rA   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_mesh_MeshEnv.create_sub_meshT   s%     !- !-H =
 !-   &**KM#%   !36|3W/  '(1,"-"5"5"21"58H"H 0 47G G #6 #K "(()9!)<?O)OP$,<(=(AA$(//44[A)**1. "(()9!)<?O)OP(//#445Ea5HI+ 4X4 &*%0@0@*A%B"$&--c2 % *11 '*7g+)+O #++-H*$++#4"'	 w&")K + ,@K(6AD&&{3Gs   F2rb   c                    [         R                  U5      n[        UR                  5       Vs/ s H'  n[        UR                  5      R	                  U5      PM)     nnU(       d8  SR                  U Vs/ s H  n[        UR                  5      U   PM     sn5      nU R                  R                  U0 5        [        / [        [        UR                  5      5      QU R                  U   R                  5       Q76 nX';   a  [        U SU S3SU S35      eX0R                  ;   a$  X R                  U   ;   a  U R                  U   U   $ [        R                  " UR                  R!                  5       5      n[        [#        UR                  R$                  5      5      n	U H  n
U	R'                  U
5        M     UR                  R(                  " / U	QUQ76 R+                  SU5      nUR-                  5       nU H"  n[/        UR0                  UU4S9nX;   d  M   UnM$     X0R2                  W'   XR                  R                  U0 5      U'   [5        U5      U R                  U   U'   U$ s  snf s  snf )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.r:   rN   )_mesh_resourcesget_root_meshr   rN   indexjoinr4   
setdefaultr   rT   keysr<   r3   mathprodrD   rE   rU   rV   rW   rX   rY   r#   r   rZ   r1   tuple)r6   r?   rb   	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_rootre   rf   rg   flattened_meshres_flattened_meshs                   r   create_flatten_mesh_MeshEnv.create_flatten_mesh   s    (55kBI 088R8R/S$/S+ 112889PQ/S ! $
 ! # $8#7C !!9!9:3?#7! **55iD % !hy7789!//	:??A! 1"$o%HSUVKL]K^ _B C  999!%A%A)%LL33I>}MM&*ii0@0@0E0E0G&H#$(y~~/B/B)C$D!';#%,,-@A (< (nn44 &)=gb12  !))+H*!+))$1#3"
 &)7& + >G&&'9:Tf((33IrB=QGLMaGbD**95mD%%w$s   .I)3"I.c                 P    U R                   R                  US 5      nU(       d  U$ U$ r   )r1   get)r6   r?   ry   s      r   rq   _MeshEnv.get_root_mesh   s)     2266{DII&/;>Y>r   c                     U R                  U5      nUR                  nU(       a3  U(       a,  [        U5      S:X  d   S5       eUS   nU R                  X$5      $ g)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.
rJ   z"The submesh can only be a 1D mesh.r   N)rq   rN   r;   get_mesh_dim_by_name)r6   r?   ry   child_mesh_dim_nameschild_mesh_dim_names        r   get_root_mesh_dim_MeshEnv.get_root_mesh_dim   sc     **;7I#.#=#= 1,-28782&:1&=#00PPr   rZ   c                 4    [        U 5      R                  5       $ r   )_get_device_handledevice_countrZ   s    r   num_devices_per_host_MeshEnv.num_devices_per_host   s    %k2??AAr   c                 B    [        5       [        R                  U 5      -  $ r   )r$   r,   r   r   s    r   	num_hosts_MeshEnv.num_hosts   s     "#x'D'D['QQQr   c                    UR                   b  [        UR                   5      S:X  a  [        S5      eX!R                   ;  a  [        SU S3SUR                    35      e[        UR                   R	                  U5      5      $ )Nr   zNo `mesh_dim_names` found.zMesh dimension 'z' does not exist.z.Available mesh dimensions are: mesh_dim_names=)rN   r;   KeyErrorr   rr   )r6   r?   rb   s      r   r   _MeshEnv.get_mesh_dim_by_name  s     **2{112a70  $>$>>&}o5FGD[E_E_D`a  K66<<]KLLr   r|   backend
pg_optionsc                 $    X#4U R                   U'   g r   )r2   )r6   r|   r   r   s       r   _set_mesh_dim_group_options$_MeshEnv._set_mesh_dim_group_options  s     18/DD'',r   c                    ^	 XR                  U5      :w  a  [        S5      eU R                  R                  U0 5        U R                  U   n/ UR                  QUQm	[        U	4S jU 5       5      (       d  [        SU ST	 S35      eSn/ nU Hl  nXc;   a  X6   nUS   nUR                  U5        O-UR                  R                  U5      nUR                  U45        X::  a  [        SU S3SU S	3S
5      eUnMn     U$ )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   .   >#    U  H
  nUT;   v   M     g 7fr   r   ).0rb   valid_mesh_dim_namess     r   	<genexpr>0_MeshEnv._get_slice_mesh_dims.<locals>.<genexpr>2  s      %3M !55%3s   zInvalid mesh_dim_names z% specified. Valid mesh_dim_names are .r:   z specified. z!Found mesh dim indices to slice: rn   z.Mesh dim indices should be in ascending order.)	rq   r<   r4   rt   rN   allr   rR   rr   )
r6   r?   rN   r4   curr_idxslice_mesh_dimsrb   mesh_indicesnext_idxr   s
            @r   _get_slice_mesh_dims_MeshEnv._get_slice_mesh_dims  sR    00=="#LMM **55k2F(,(F(F{(S%$++$*$ 
  %3   -n-= >00D/EQH  H O!/ =#<#KL  ,B/H#**<8*99??NH#**H;7'"1.1AN;O;LBOH 
 $! "0$ #"r   c                 p   U R                  X5      nUR                  R                  SU5      R                  SUR                  R	                  U5      5      nUR                  5       n/ nU HG  n[        UR                  UU4SS9nXW;   a  UR                  U   /O/ Ul        UR                  U5        MI     U$ )zH
Return all the submeshes of a given mesh dimension of the device mesh.
r:   FrM   )
r   rD   swapdimsrY   rE   r#   r   rZ   rS   rR   )	r6   r?   rb   r[   re   rf   res_submeshesmesh_1drh   s	            r   _get_all_submeshes_MeshEnv._get_all_submeshesS  s     00LH)..77HEMMK$$))(3O #++-HM*$++$1#3"'	  * !11(;< (
 $$W- + ! r   )r1   r4   r2   r0   r3   r.   Nr.   r   r   )r?   r   r.   r   )r   r   r   r   r7   r=   r   strr   intrj   r   r   rq   r   staticmethodr   r   r   C10dBackendOptionsr   r   r   r   r   r   r   r,   r,   B   s   
		'
M	%M	  %S#XM	 uS#X/	M	
 M	` MQ@	&+@	&<DSM@	&@	&D	?	 	(3- 	  
	Bc 	Bc 	B 
	B 
	R3 	R3 	R 
	R
	M+	M<?	M	M* 9=		E	E 	E !!4!45		E
 	E2	#%S/"2	#h	!+	!<?	!,	!r   r,   rp   rZ   c                 $    [        [        U S5      $ )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   r  s     uk400r   c                      \ rS rSr% Sr\\S'   \R                  \S'   \	\
\S4      \S'   SSS	.S\S\\R                  S
4   S\	\
\S4      S\SS4
S jjrS rS rS&S jrS'S jrS\4S jrS rS\S\4S jrS\\\
\S4   4   SS 4S jrS(S\	\\\4      S\4S jjrS\\   4S jr\ S(SS.S\\\\   4   S\S\	\\R                  S
4      S\	\
\S4      SS 4
S jjj5       rS(S\	\   S\4S jjr\S\4S j5       r \S\
\S4   4S j5       r!S\4S  jr"S(S\	\\\4      S\4S! jjr#S\	\\      4S" jr$S(S#\	\   SS 4S$ jjr%S%r&g))r   i{  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]])
rZ   rD   .rN   NTrM   r*   rO   r.   c                   Xl         [        U[        R                  5      (       a(  UR                  R
                  S:w  a  [        SU 35      e[        U[        R                  5      (       a+  UR                  5       R                  [        R                  S9O#[        R                  " US[        R                  S9U l        U(       a  [        U5      OS U l        [        U R                  R                  5       R                  5       5      U l        S U l        US:w  a  U(       a   U R%                  5         U R'                  5         [)        5       (       a(  [+        5       S:X  a  [,        R.                  " 5       U l        U R                  [1        5       :H  R3                  5       nUR5                  S5      S;   d   eUR5                  S5      S:  a  US   R                  5       OS U l        g g )	Ncpuz!`mesh` must be a CPU tensor, got dtypedevicer   xlathreadedr   )r   rJ   )rZ   
isinstancer   Tensorr   type
ValueErrordetachtor   tensorrD   rx   rN   rQ   tolist_flatten_mesh_list
_thread_id_get_or_create_default_group_init_process_groupsr&   r!   	threading	get_identr#   nonzerorE   _coordinate_on_dim)r6   rZ   rD   rN   rO   rank_coordss         r   r7   DeviceMesh.__init__  sx     +$--$++2B2Be2K #DTF!KLL dELL11   uyy 1\\$uEIIF I
 <J%"7tD ',DII,=,=,?,F,F,H&ID#"DO e# !557--/!##(C&/&9&9&;DO  $yyHJ6??A"''*f444/:/?/?/BQ/FKN))+D ' $r   c           	         [        5       nU(       d
  [        5         [        5       nU R                  R	                  5       U:  a*  [        SU SU R                  R	                  5        S35      e[        U R                  5      nU(       d_  U(       aX  UR                  5       nX$:  a'  X$-  S:w  a  [        SU SU SU R                   S35      eUR                  [        5       U-  5        [        5       $ )	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$   rD   numelr<   r   rZ   r   
set_devicer#   r   )r6   default_initialized
world_sizedevice_handler   s        r   r   'DeviceMesh._get_or_create_default_group  s    "0"2&"$')Jyy :-"HT`aeajajapapar`ssz{  /t/?/?@M&= (5'A'A'C$5"9Q>&R%,k2F1GqIYIYHZZce  ((6J)JK%''r   c           	         / n[        5       nU R                  R                  S:X  a  U R                  R                  5       [	        5       :X  a  [        [        [	        5       5      5      n[        R                  R                  5       (       a  [        U5      S:X  a  [        SUSS9OUnUR                  [        U5      UUR                  45        GO[        U R                  R                  5       GHj  nU R                  R                  SU5      R!                  SU R                  R#                  U5      5      nU[$        R&                  ;   a  [$        R&                  U   u  nnOSu  pxU R(                  (       a  SU R(                  U    3OS	U 3n	S n[+        US
S 5      =n
 b  [-        UUUR/                  5       U	S9nU H  nUR/                  5       nU
c  [        UUUU	S9nU R1                  5       U;   d  M8  [3        U5      U:  a   [5        SU R1                  5        SU S35      eUR                  [        [7        U5      5      UUR                  45        M     GMm     Xl        g )NrJ   gloozcpu:gloo,cuda:ncclmesh_default)r   ranks
group_descr:   )NNmesh_	mesh_dim_bound_device_id)	parent_pgr   split_ranksr   )r   r   r   r   zFEach device mesh dimension should get only one process group, but got z in !)r   rD   rV   r   r$   rT   rU   r   cudar   r!   r'   rR   r    
group_namer   rY   rE   rp   r2   rN   r   r)   r   r#   r;   r<   r   rS   )r6   dim_group_infosdefault_groupr   	dim_groupr|   re   r   r   r   r   dim_meshsubgroup_rankss                r   r   DeviceMesh._init_process_groups  so    ACO.0Myy~~"tyy'8N<L'L U>#345 zz..00#M2f<  4##1 '   &&&y1!,, !0C '+ii&8&8S&A&I&IDIINN3/'O oDDD ,BB3G#& /9+  ..   3 3C 89:(.  !%I+2)+<d,  "	"
 %0&3'1(7(>(>(@'1	%	 %4)1):
 +2(1&4(/+5+5	)I  ==?n<"?3c9&2&lmqmzmzm|l} ~**8)9%<'" !" ,22$28I3F$G$2$-$8$8!"+ %4k 1b %4!r   c                 D    [         R                  R                  U 5        U $ r   )rp   r0   rR   r5   s    r   	__enter__DeviceMesh.__enter__b  s    &&--d3Kr   c                 @    [         R                  R                  5         g r   )rp   r0   pop)r6   exc_type	exc_valueexc_tracebacks       r   __exit__DeviceMesh.__exit__h  s    &&**,r   c                     U R                   (       d-  SU R                   SU R                  R                  5        S3nU$ SU R                   SU R                  R                  5        SU R                    S3nU$ )NzDeviceMesh('z', )z, mesh_dim_names=)rN   rZ   rD   r   )r6   device_mesh_reprs     r   __repr__DeviceMesh.__repr__l  s     ** t//0DII4D4D4F3GqI 
 $# $D$4$4#5S9I9I9K8LL]^b^q^q]rrst 
 $#r   c                    [        U SS 5      U l        U R                  (       dQ  [        U R                  U R                  R
                  U R                  U R                  U R                  45      U l        U R                  $ )N_hash)	r   r  hashr   rD   shaperZ   rN   r   r5   s    r   __hash__DeviceMesh.__hash__t  sc     w5DJ::!//		((++
 ::r   otherc                    [        U[        5      (       d  g[        U 5      [        U5      :X  a  gU R                  UR                  :H  =(       a    U R                  R
                  UR                  R
                  :H  =(       aY    U R                  UR                  :H  =(       a9    U R                  UR                  :H  =(       a    U R                  UR                  :H  $ )NFT)	r   r   idr   rD   r  rZ   rN   r   )r6   r  s     r   __eq__DeviceMesh.__eq__  s    eZ00$x2e9$ ++u/G/GG <		5::+;+;;<((E,=,==< ++u/C/CC< 5+;+;;r   c                 p   U R                   (       d  [        S5      e[        U[        5      (       a  U4OUnXR                   :X  a  U $ [        R                  X5      n[        R                  R                  R                  5          [        R                  XU5      nSSS5        U$ ! , (       d  f       W$ = f)a  
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!N)rN   r<   r   r   rp   r   r   _subclassesfake_tensorunset_fake_temporarilyrj   )r6   rN   r   rh   s       r   __getitem__DeviceMesh.__getitem__  s    Z &&"#VWW &0%D%D!.  !4!44"1"F"F# &&22IIK-==oG L 	 LK s   B&&
B5r[   c                    [        U S5      (       d  [        S5      eU R                  R                  S:  a(  Uc%  [        SU R                  R                   S3SS5      eU R                  R                  S:X  a$  Uc!  [	        [        U R                  S	   SS
 6 5      $ [        R                  U 5      n[        R                  R                  US5      nU(       a8  XR                  5       ;   a%  X1   R                  S	   SS
 n[	        [        U6 5      $ [        U[        5      (       a  [        R                  X5      OUn[	        [        U R                  U   SS
 6 5      $ )ab  
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.
rS   z*DeviceMesh process groups not initialized!rJ   NFound the DeviceMesh have  dimensionsJOptional 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      )hasattrr<   rD   rV   r   r   rS   rp   rq   r3   r   ru   r   r   r   )r6   r[   ry   r3   r   s        r   	get_groupDeviceMesh.get_group  s[    4!344"#OPPyy~~!h&6"00@L`=  yy~~"x'7-t/D/DQ/G/KL  (55d;I&5&M&M&Q&Q4'# '87S7S7U+U"9"C"T"TUV"WXZYZ"[ 9? KLL "(C00 $88H! 
  -t/D/DX/NrPQ/RS r   c                     [        U R                  R                  5       Vs/ s H  oR                  U5      PM     sn$ s  snf )zp
Returns a list of ProcessGroups for all mesh dimensions.

Returns:
    A list of :class:`ProcessGroup` object.
)rU   rD   rV   r  )r6   is     r   get_all_groupsDeviceMesh.get_all_groups  s2     05TYY^^/DE/D!NN1%/DEEEs   ?ro   groupc                "   [        U [        5      (       a  [        U 5      n[        U[        R                  5      (       a  UR                  5       U:w  d'  Ub>  [        U[        R                  5      (       d  X$:w  a  [        S[        U5       SU 35      e[        R                  " US[        R                  S9n[        UUUSS9n[        U 5      X@R                  4/Ul        U$ [        U 5      n[        U5      S:X  a  [        S5      eUc  [        S	5      e[        U[        R                  5      (       a,  UR!                  5       R#                  [        R                  SS
9O#[        R                  " US[        R                  S9nUR$                  [        U5      :w  a)  [        SUR                  5        S[        U5       S35      e[        XUSS9nU V s/ s H$  n [        U 5      [        U 5      U R                  4PM&     sn Ul        U$ s  sn f )a  
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   FrM   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   rS   rT   r;   r   r   rV   )r  rZ   rD   rN   group_ranksr?   groupss          r   
from_groupDeviceMesh.from_group  s     %..5e<tU\\22t{{}7S$&tU\\::+$'D	{2OP[}]  ||KUYYO(#1"'	 $E*K9I9IJ0, #"%[F6{a !QRR| !STT dELL11   uyy ?\\$uEIIF 
 yyCK'  KKM?%F}NL  %.PUK $, $E	 #5)+E2$$
 $,K( ,s   +Hc                 r    Uc  U R                   R                  5       $ U R                   R                  U5      $ r   )rD   r   rE   )r6   r[   s     r   rE   DeviceMesh.sizeT  s*    (0(8499??$VdiinnX>VVr   c                 .    U R                   R                  $ r   )rD   rV   r5   s    r   rV   DeviceMesh.ndimW  s    99>>!r   c                 @    [        U R                  R                  5      $ r   )rx   rD   r  r5   s    r   r  DeviceMesh.shape[  s    ))r   c                     [        5       $ )z"
Returns the current global rank.
)r#   r5   s    r   r#   DeviceMesh.get_rank_  s     :r   c                    U R                   S:  a'  Uc$  [        SU R                  R                    S3S5      eUc  Sn[        U R	                  U5      5      n[        U[        5      (       d   S5       e[        [        U5      5      $ )as  
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]])
rJ   r  r  r  r   z1We expect ProcessGroup before calling `get_rank`!)rV   r<   rD   r   r  r   r(   r#   )r6   r[   mesh_dim_groups      r   get_local_rankDeviceMesh.get_local_ranke  s    8 yy1}!1"00@L`  !%dnnX&>?N  CBC  H^455r   c                 @    U R                   (       a  U R                   $ 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   r5   s    r   get_coordinateDeviceMesh.get_coordinate  s    
 /3.E.E4**O4Or   rb   c                 d    U R                   (       d  [        S5      e[        R                  X5      $ )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!)rN   r<   rp   r   )r6   rb   s     r   _flattenDeviceMesh._flatten  s0     &&"I  #66tKKr   )r   rS   r   r  r   rZ   rD   rN   r   r   r   )'r   r   r   r   __doc__r   __annotations__r   r   r   r   r
   boolr7   r   r   r   r   r   r  objectr  r  r   r(   r  r   r  r   r#  rE   propertyrV   r  r#   r/  r2  r5  r   r   r   r   r   r   {  sg   %	N ll sCx11 9="&(	(	 k12(	
 %U38_5(	  (	 (	T	(:r	4h		-	$c 	$		 	4 	G	"'U38_(<"=G	G	R,	huS#X&? ,	< ,	\	FD$6 	F 
 @D@	
 9=@	tL'99:@	@	 5{!:;<@	
 %U38_5@	 @	 
@	D	W# 	W# 	W 
	"# 	" 
	" 
	*5c? 	* 
	*	c 	(	68E#s(O+D (	6PS (	6T	PHT#Y$7 	P	L(3- 	L< 	L 	Lr   ro   
mesh_shape.rN   r.   c          	      @   Ubm  [        [        U5      5      [        U5      :w  a  [        SSU 35      e[        U5      [        U5      :w  a%  [        SS[        U5       S[        U5       S35      eU (       a%  U R                  5       (       d  [        SU  S	3S
5      e[        R
                  " S5         [        R                  " [        R                  " U5      [        R                  S9R                  U5      nSSS5        [        U WUS9nU$ ! , (       d  f       N= f)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   z0Device type with index is not supported but got rn   zUIf you maintained a 'torch.device' object, it's recommended to pass in 'device.type'.r   r   )rZ   rD   rN   )r;   setr<   isalphar   r   arangerv   rw   r   viewr   )rZ   r<  rN   rD   r?   s        r   r   r     s   R %3~&'3~+>>"8EnEUV 
 :#n"55"L1#n2E1FF[\_`j\k[llmn  {2244B;-rRg  \\% <<		* 5UYYGLLZXD ! #)
  ! s   3AD
D)r   )8loggingrv   r   	functoolsr   	itertoolsr   typingr   r   r   r   r	   r
   r   torch.distributedr   torch.utils._typing_utilsr   __all__sysr   r   modulesr   r   torch._C._distributed_c10dr   r   "torch.distributed.distributed_c10dr   r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   	getLoggerr   loggernumpy.typingr*   ImportErrorwarninglocalr,   rp   r8  r   r   r   r   r   r   <module>rS     sX        D D  * . |
, ~~  ?NCKK/0; 0 KK' B    x(F 	.l!9?? l!\	 !)
OX*1 1mL mLf 59	GG#s(OG !sCx1	G
 
G[  	NNU	s    D D32D3