
    ΑiR                     D    S SK r S SKrS SKrS SKrSSKJr   " S S5      rg)    N   )
get_loggerc                       \ rS rSrSrS rS rS rS rSS jr	S r
\S	 5       r\S
 5       r\S 5       r\S 5       r\S 5       r\S 5       r\S 5       rSrg)	Converter   z
Converter is a class object for auto parallel to convert tensors from
one parallel strategy to another one. Tensors will merge and slice value
with their strategy when strategies are different.
c                     U R                  U5      U l        U R                  U5      U l        U R	                  U5      U l        [        [        R                  5      U l	        g)a  
Args:
    tensors_dict(dict): tensors' value of all ranks that to be converted.
        key is tensor's name(str), value is all ranks' data(list(numpy.ndarray))
    pre_strategy(dict): tensors' distributed attribute of last training process.
        key is tensor's name(str), value is tensor's distributed attribute in last
        training process.
    cur_strategy(dict): tensors' distributed attribute of current rank.
        key is tensor's name(str), value is tensor's distributed attribute in current
        rank.
N)
_check_tensor_dict_tensors_dict_check_pre_strategy_pre_strategy_check_cur_strategy_cur_strategyr   loggingINFO_logger)selftensors_dictpre_strategycur_strategys       q/var/www/html/banglarbhumi/venv/lib/python3.13/site-packages/paddle/distributed/auto_parallel/static/converter.py__init__Converter.__init__    sM     "44\B!55lC!55lC!',,/    c                     U(       d  [        S5      e[        U[        5      (       d  [        S[	        U5       S35      eU$ )NzC'tensors_dict' is None, the tensors to be converted cannot be None.z6The type of 'tensors_dict' should be 'dict', but got ''.
ValueError
isinstancedict	TypeErrortype)r   r   s     r   r	   Converter._check_tensor_dict1   sN    >  ,--HlI[H\\^_  r   c                     U(       d  [        S5      e[        U[        5      (       d  [        S[	        U5       S35      eU$ )Nz='pre_strategy' is None, there are not tensors in pre process.z6The type of 'pre_strategy' should be 'dict', but got 'r   r   )r   r   s     r   r   Converter._check_pre_strategy=   sP    O  ,-- ./r3  r   c                     U(       d  [         R                  " S5        [        U[        5      (       d  [	        S[        U5       S35      eU$ )Nz<'cur_strategy' is None, there are not tensors in cur processz6The type of 'cur_strategy' should be 'dict', but got 'r   )warningswarnr   r   r    r!   )r   r   s     r   r   Converter._check_cur_strategyI   sO    MMN ,-- ./r3  r   c                    0 n/ n/ n/ nU R                   R                  S5        U R                   H  nX`R                  ;  a  UR	                  U5        M%  X`R
                  ;  a  UR	                  U5        MG  X`l        X`l        U R
                  U   nU R                  U   nU R                  U   n	 [        R                  XxU	5      X&'   M     U R                   H%  nX`R                  ;  d  M  UR	                  U5        M'     U(       d  U R                  X#U5      u  nnnOU/ / pn[        U5      [        U5      -
  n[        U5      [        U5      -
  nU(       a  [        R                  " SU S35        U(       a  [        R                  " SU S35        U(       a  [        R                  " SU S35        U$ ! [         a  n
[        SU SU
 35      eSn
A
ff = f)	a  
Convert tensors

Args:
    strict(bool): whether to strict convert tensor with tensor's name. If False, it will
    convert tensors by prefix matching. Otherwise, tensors will be converted with
    their name strictly.

Returns:
    converted tensors(dict)

Examples:
    .. code-block:: python

        >>> # doctest: +REQUIRES(env:DISTRIBUTED)
        >>> import numpy as np
        >>> from paddle.distributed.auto_parallel.static.converter import Converter
        >>> complete_tensors = np.arange(4).reshape([2, 2])
        >>> partial_tensors = np.split(complete_tensors, 2, axis=0)
        >>> name = "tmp_0"
        >>> tensors_dict = {name: partial_tensors}
        >>> strategy_1 = {
        ...     name: {
        ...         "process_shape": [2],
        ...         "process_group": [0, 1],
        ...         "dims_mapping": [0, -1]
        ...     }
        ... }
        >>> strategy_2 = {
        ...     name: {
        ...         "process_shape": [2],
        ...         "process_group": [0, 1],
        ...         "dims_mapping": [-1, -1]
        ...     }
        ... }
        >>> converter = Converter(tensors_dict, strategy_1, strategy_2)
        >>> result = converter.convert()
        >>> # the result's value is equal to `complete_tensors`
zStart to convert tensors.Fail to convert tensor ''. Nz	tensors [z*] are not found in last training strategy.z-] are not found in current training strategy.zf] are found in pre_strategy, but are not foundin checkpoint files, please check your checkpoint files.)r   infor   r   appendr
   	_pre_name	_cur_namer   merge_and_slicer   convert_with_prefix_matchsetr&   r'   )r   strictr   tensor_not_in_pretensor_not_in_curtensor_not_in_ckpttensor_nametensor_listpre_dist_attrcur_dist_attrerrtensor_match_with_pretensor_match_with_curs                r   convertConverter.convertU   s   P 56--K"4"44!((5"4"44"))+6(N(N,,[9K ..{;M ..{;M,5,E,E-) .*  --K"4"44!((5 . 
 ..1B	%%  2GL   12S9N5OO 12S9N5OOMM-..XY MM-..[\ MM./ 0K K
 Q   .{m3seD s   1F88
GGGc                    / n/ nU H  nUnUR                  S5      S:w  d  M  US UR                  S5       nU H  nXx;   d  M
  Xl        X`l        U R                  U   n	U R
                  U   n
U R                  U   n [        R                  XU5      X'   U R                  R                  SU SU S35        UR                  U5        UR                  U5          O   M     XU4$ ! [         a  n[        SU SU SU 35      eS nAff = f)	N_r*   z' by 'r+   ztensor [z] is matched with tensor [])findrfindr.   r/   r
   r   r   r   r0   r   r   r,   r-   )r   r   r4   r5   r<   r=   cur_nameprefix_namepre_namepre_tensor_listr9   r:   r;   s                r   r1   #Converter.convert_with_prefix_match   sE    !# ")H"K""3'2-)*BK,=,=c,BC 1H".)1)1*.*<*<X*F(,(:(:8(D(,(:(:8(D5>5N5N /6L2 ))&xj0J8*TUV .44X>-44X>+ !2, 5 *8 4III  * ",":8*F8*TWX[W\ ]# s   =C%%
D/DDc                    [        U [        5      (       d   e[        S U  5       5      (       d   eX:X  a8  [        R                  R                  5       nUS   R                  U5      nX   nU$ US   nUS   n[        U5      (       a4  [        [        U5      5      S:  d  SU;  a  [        R                  X5      nOU S   n[        U5      (       a3  [        [        U5      5      S:  d  SU;  a  [        R                  XR5      nU$ )z
Merge tensors with previous dist_attr and slice tensors with current dist_attr

Returns:
    tensor(numpy.narray): a tensor's value of current rank.
c              3   V   #    U  H  n[        U[        R                  5      v   M!     g 7f)N)r   npndarray).0ps     r   	<genexpr>,Converter.merge_and_slice.<locals>.<genexpr>   s     Bk:a,,ks   ')process_groupdims_mapping   rB   r   )r   listallpaddledistributedget_rankindexlenr2   r   merge_with_dist_attrslice_with_dist_attr)r8   r9   r:   rank_idr[   tensorpre_dims_mappingcur_dims_mappings           r   r0   Converter.merge_and_slice   s	    +t,,,,BkBBBBB)((113G!/288AE 'F, )  -^<,^<#$$C()*Q."<L2L #77
 %Q#$$C()*Q."<L2L #77Nr   c                    SSK Jn  US   nUS   nUS   nUR                  U S   R                  XC5      n/ n/ nU H[  n	UR	                  U	UUUU5      n
UR                  U	5      nX;  d  M0  UR                  U
5        [        R                  UX   U
U5        M]     [        U5      S:w  a  [        SU S35      eUS   S   nU$ )	z'Merge tensor with distributed attributerU   	ResharderrT   process_shaperS   r   z%Fail to merge tensor with dist_attr 'r   )reshardrf   compute_complete_shapeshapecompute_partition_indexr[   r-   r   merger\   r   )r8   	dist_attrrf   rT   rg   rS   complete_shapepartition_tensor_listmerged_partitionprocesspartition_indexr[   complete_tensors                r   r]   Converter.merge_with_dist_attr  s     	' 0!/2!/2"99N  -
 !#$G'??O "''0E6 ''8)&#"	 %$ $%*7	{"E  0215r   c                    US   n[        U5      S:X  a  U $ US   nUS   n[        R                  U R                  X#U5      n[        R	                  X[        U5      5      n[
        R                  R                  5       n[        R                  XpR                  X#U5      nU[        [        U5      5      ;  a  [        SU S35      eXh   n	U	$ )z'Slice tensor with distributed attributerT   r   rg   rS   z%Fail to slice tensor with dist_attr 'r   )r\   r   _get_split_indicesrj   splitrX   rY   rZ   _get_sliced_indexranger   )
r`   rm   rT   rg   rS   partition_index_listsliced_tensor_listr_   sliced_tensor_indexsliced_tensors
             r   r^   Converter.slice_with_dist_attr3  s     !0|!M!/2!/2(;;LL,} 
 '__#.B*C
 $$--/'99\\<
 eC0B,C&DD7	{"E  +?r   c                 >   SSK Jn  [        U 5      S:X  a<  Sn[        U S   S   5       H  u  pgUS   S:w  d  US   X6   :w  d  M  Sn  O   U(       a  gU (       d  U R	                  X45        gSnU[        U 5      :  a  UR                  X   S   U5      u  n	n
nU	S:w  ai  U
S:X  a  [        R                  " X   S   U4U	S9nO[        R                  " XU   S   4U	S9nU R                  U5        [        R                  U UUU5        gUS-  nU[        U 5      :  a  M  gg)	a  
Merge partial tensors to a complete.

Returns:
    None

Examples:
    .. code-block:: python

        >>> # doctest: +REQUIRES(env:DISTRIBUTED)
        >>> import numpy as np
        >>> import paddle
        >>> from paddle.distributed.auto_parallel.static.converter import Converter
        >>> partition_tensor_list = [(np.array([[[1.11, 1.12]]]), [[0,1],[0,1],[0,2]])]
        >>> tensor = np.array([[[1.13, 1.14]]])
        >>> partition_index = [[0,1],[0,1],[2,4]]
        >>> complete_shape = [3, 2]

        >>> Converter.merge(partition_tensor_list, tensor, partition_index, complete_shape)
        >>> print(partition_tensor_list)
        [(array([[[1.11, 1.12, 1.13, 1.14]]]), [[0, 1], [0, 1], [0, 4]])]
rU   re   Tr   FNrB   axis)rh   rf   r\   	enumerater-   compute_concat_inforM   concatenatepopr   rl   )ro   r`   rr   rn   rf   is_complete_dataidxitemiconcat_axisfirst_ordernew_partition
new_tensors                r   rl   Converter.mergeO  sP   0 	'$%*#&'<Q'?'BC	7a<47n.A#A',$ D  $!((&)BCAc/00
 11),Q/	! "$"a'%'^^25a8&A!,&

 &(^^#1%=a%@A!,&

 *--a0OO-"%&	 Q9 c/00r   c           	          / n[        U R                  5      U-
  n[        R                  " XU   US9nUS:X  a  U$ U H+  nUR	                  [
        R                  XaUS-
  5      5        M-     U$ )a  
Slice a complete tensor.

Returns:
    sliced_tensor_list(list): sliced tensors with 'partition_index_list'

Examples:
    .. code-block:: python

        >>> # doctest: +REQUIRES(env:DISTRIBUTED)
        >>> import numpy as np
        >>> from paddle.distributed.auto_parallel.static.converter import Converter
        >>> complete_tensor = np.array([[[1.11, 1.12, 1.13, 1.14, 1.15, 1.16]]])
        >>> rank = 2
        >>> complete_shape = [1, 1, 6]
        >>> dims_mapping = [-1, -1, 0]
        >>> process_shape = [3]
        >>> process_group = [0, 1, 2]

        >>> sliced_tensor_list = Converter.split(complete_tensor, [[], [], [2, 4]], 3)
        >>> print(sliced_tensor_list)
        [array([[[1.11, 1.12]]]), array([[[1.13, 1.14]]]), array([[[1.15, 1.16]]])]
r   rU   )r\   rj   rM   rw   extendr   )rs   rz   lengthr{   r   r}   r`   s          r   rw   Converter.split  sx    2  ?(()F2$7d
 Q;  #F%%fqjI $ "!r   c                 6   SSK Jn  / nU HS  nUR                  UU UUU5      nU(       a2  [        [	        U5      5       H  nXX   R                  Xx   5        M     MQ  UnMU     [        [        S UU 5      5      nU V	s/ s H  n	[        U	5      PM     nn	U$ s  sn	f )a  
Get split indices of every dimension.

Returns:
    split_indices_list(list): the split indices of every dimension of the tensor

Examples:
    .. code-block:: python

        >>> # doctest: +REQUIRES(env:DISTRIBUTED)
        >>> import numpy as np
        >>> from paddle.distributed.auto_parallel.static.utils import _get_split_indices
        >>> complete_tensor = np.array([[[1.11, 1.12, 1.13, 1.14, 1.15, 1.16]]])
        >>> complete_shape = [1, 1, 6]
        >>> dims_mapping = [-1, -1, 0]
        >>> process_shape = [3]
        >>> process_group = [0, 1, 2]

        >>> index = _get_split_indices(complete_shape, dims_mapping, process_shape, process_group)
        >>> print(index)
        [[], [], [2, 4]]
rU   re   c                 :    [        [        U 5      U1-
  S1-
  5      $ )Nr   )rV   r2   )xys     r   <lambda>.Converter._get_split_indices.<locals>.<lambda>  s    T#a&A3,!"45r   )	rh   rf   rk   ry   r\   r   rV   mapsorted)
rn   rT   rg   rS   rf   split_indices_listrq   rr   dimr   s
             r   rv   Converter._get_split_indices  s    4 	'$G'??O " _!56C&+22?3GH 7 &5" % "5"
 2DD1CAfQi1CD!! Es   =Bc                     SSK Jn  UR                  XX#U5      nSn[        U5       H>  u  pX(   S:X  a  U	n
O	XX(      -  n
U
S:X  a  Xh   S   nOXh   S   S-   U
-  nXyU
-  -  U-   nM@     U$ )a(  
Get sliced_tensor's index of current rank in all sliced tensors list.

Returns:
    sliced_tensor_index(int): the index of sliced tensor in sliced_tensor_list

Examples:
    .. code-block:: python

        >>> # doctest: +REQUIRES(env:DISTRIBUTED)
        >>> import numpy as np
        >>> from paddle.distributed.auto_parallel.static.converter import Converter
        >>> complete_tensor = np.array([[[1.11, 1.12, 1.13, 1.14, 1.15, 1.16]]])
        >>> rank = 2
        >>> complete_shape = [1, 1, 6]
        >>> dims_mapping = [-1, -1, 0]
        >>> process_shape = [3]
        >>> process_group = [0, 1, 2]

        >>> index = Converter._get_sliced_index(rank, complete_shape, dims_mapping,
        ...                                 process_shape, process_group)
        >>> print(index)
        2
rU   re   r   rB   )rh   rf   rk   r   )r_   rn   rT   rg   rS   rf   rr   sliced_indexr   rj   slice_shaper[   s               r   rx   Converter._get_sliced_index  s    8 	'#;;\-
 !.1HA"$##\_'EEa'*1-(+A.2{B'K+?@5HL 2 r   )r/   r   r   r.   r   r
   N)T)__name__
__module____qualname____firstlineno____doc__r   r	   r   r   r>   r1   staticmethodr0   r]   r^   rl   rw   rv   rx   __static_attributes__ r   r   r   r      s    0"


hT#JJ $ $L % %N  6 B BH #" #"J 1" 1"f + +r   r   )r   r&   numpyrM   rX   utils.log_utilsr   r   r   r   r   <module>r      s"        )A Ar   