
    x-jR                     L    d dl Z d dlZd dlZd dlZddlmZ  G d d          ZdS )    N   )
get_loggerc                       e Zd ZdZd Zd Zd Zd ZddZd Z	e
d	             Ze
d
             Ze
d             Ze
d             Ze
d             Ze
d             Ze
d             ZdS )	Converterz
    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                     |                      |          | _        |                     |          | _        |                     |          | _        t          t          j                  | _	        dS )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.11/site-packages/paddle/distributed/auto_parallel/static/converter.py__init__zConverter.__init__    s[     "44\BB!55lCC!55lCC!',//    c                     |st          d          t          |t                    s t          dt	          |           d          |S )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   zConverter._check_tensor_dict1   se     	>   ,-- 	_lI[I[___   r   c                     |st          d          t          |t                    s t          dt	          |           d          |S )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
   zConverter._check_pre_strategy=   sl     	O   ,-- 	3 ..3 3 3   r   c                     |st          j        d           t          |t                    s t	          dt          |           d          |S )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   zConverter._check_cur_strategyI   sn     	MN   ,-- 	3 ..3 3 3   r   Tc                    i }g }g }g }| j                             d           | j        D ]}|| j        vr|                    |           !|| j        vr|                    |           @|| _        || _        | j        |         }| j        |         }| j        |         }		 t          	                    |||	          ||<   # t          $ r}
t          d| d|
           d}
~
ww xY w| j        D ] }|| j        vr|                    |           !|s|                     |||          \  }}}n|g g }}}t          |          t          |          z
  }t          |          t          |          z
  }|rt          j        d| d           |rt          j        d| d           |rt          j        d| d           |S )	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   convertzConverter.convertU   s   P 5666- 	 	K$"444!((555$"444"))+666(DN(DN,[9K .{;M .{;M,5,E,E- -[))     D{DDsDD  
  - 	6 	6K$"444!((555 	
 ../1B 	%%%  2G/L   122S9N5O5OO 122S9N5O5OO 	MY-YYY    	M\-\\\    	MK. K K K  
 s    C  
C$
CC$c                 @   g }g }|D ]}|}|                     d          dk    r|d |                    d                   }|D ]}||v r|| _        || _        | j        |         }	| j        |         }
| j        |         }	 t                              |	|
|          ||<   n*# t          $ r}t          d| d| d|           d }~ww xY w| j
                            d| d| d           |                    |           |                    |            n	 |||fS )	N_r%   z' by 'r&   ztensor [z] is matched with tensor [])findrfindr)   r*   r	   r   r   r   r+   r   r   r'   r(   )r   r   r/   r0   r7   r8   cur_nameprefix_namepre_namepre_tensor_listr4   r5   r6   s                r   r,   z#Converter.convert_with_prefix_match   s    !# ") 	 	H"K""3''2--)*BK,=,=c,B,B*BC 1  H"h..)1)1*.*<X*F(,(:8(D(,(:8(D5>5N5N /6 6L22  *   ", ]8 ] ]8 ] ]X[ ] ]# #  ))VxVV8VVV   .44X>>>-44X>>>) /* 24IIIs    B  
C*CCc                 d   t          | t                    sJ t          d | D                       sJ ||k    rBt          j                                        }|d                             |          }| |         }n|d         }|d         }t          |          r@t          t          |                    dk    sd|vrt          
                    | |          }n| d         }t          |          r?t          t          |                    dk    sd|vrt                              ||          }|S )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   J   K   | ]}t          |t          j                  V  d S )N)r   npndarray).0ps     r   	<genexpr>z,Converter.merge_and_slice.<locals>.<genexpr>   s.      BB:a,,BBBBBBr   process_groupdims_mapping   r<   r   )r   listallpaddledistributedget_rankindexlenr-   r   merge_with_dist_attrslice_with_dist_attr)r3   r4   r5   rank_idrS   tensorpre_dims_mappingcur_dims_mappings           r   r+   zConverter.merge_and_slice   sL    +t,,,,,BBkBBBBBBBBM))(1133G!/288AAE 'FF,^<,^<#$$ 	(C())**Q.."<L2L2L #77 
 %Q#$$ OC())**Q.."<L2L2L #77NNr   c                    ddl m} |d         }|d         }|d         }|                    | d         j        ||          }g }g }|D ]l}	|                    |	||||          }
|                    |	          }|
|vr8|                    |
           t                              || |         |
|           mt          |          dk    rt          d| d          |d         d         }|S )	z'Merge tensor with distributed attributerM   	ResharderrL   process_shaperK   r   z%Fail to merge tensor with dist_attr 'r   )reshardr]   compute_complete_shapeshapecompute_partition_indexrS   r(   r   mergerT   r   )r3   	dist_attrr]   rL   r^   rK   complete_shapepartition_tensor_listmerged_partitionprocesspartition_indexrS   complete_tensors                r   rU   zConverter.merge_with_dist_attr  sB    	'&&&&& 0!/2!/2"99N -
 
 !#$ 	 	G'?? O "''00E&666 ''888)&#"	   $%%**E	EEE   0215r   c                    |d         }t          |          dk    r| S |d         }|d         }t                              | j        |||          }t                              | |t          |                    }t
          j                                        }t                              || j        |||          }|t          t          |                    vrt          d| d          ||         }	|	S )z'Slice tensor with distributed attributerL   r   r^   rK   z%Fail to slice tensor with dist_attr 'r   )rT   r   _get_split_indicesra   splitrP   rQ   rR   _get_sliced_indexranger   )
rX   rd   rL   r^   rK   partition_index_listsliced_tensor_listrW   sliced_tensor_indexsliced_tensors
             r   rV   zConverter.slice_with_dist_attr3  s    !0|!!M!/2!/2(;;L,} 
  
 '__(#.B*C*C
 
 $--//'99V\<
 
 eC0B,C,C&D&DDDE	EEE   ++>?r   c                    ddl m} t          |           dk    rId}t          | d         d                   D ]'\  }}|d         dk    s|d         ||         k    rd} n(|rdS | s|                     ||f           dS d}|t          |           k     r|                    | |         d         |          \  }	}
}|	dk    r|
dk    r%t          j        | |         d         |f|	          }n$t          j        || |         d         f|	          }|                     |           t          
                    | |||           dS |dz  }|t          |           k     dS dS )	aU  
        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]])]
        rM   r\   Tr   FNr<   axis)r_   r]   rT   	enumerater(   compute_concat_inforF   concatenatepopr   rc   )rf   rX   ri   re   r]   is_complete_dataidxitemiconcat_axisfirst_ordernew_partition
new_tensors                r   rc   zConverter.mergeO  s   0 	'&&&&&$%%**#&'<Q'?'BCC  	T7a<<47nS.A#A#A',$E $B   $  	!((&/)BCCCCCAc/0000
 11)!,Q/ 	! "$$"a''%'^215a8&A!,& & &


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

 *--a000OO-"%&	   EQ9 c/00000000r   c           	          g }t          | j                  |z
  }t          j        | ||         |          }|dk    r|S |D ]4}|                    t
                              |||dz
                       5|S )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]]])]
        ru   rM   )rT   ra   rF   rm   extendr   )rj   rp   lengthrq   rv   rs   rX   s          r   rm   zConverter.split  s    2  ?())F21$7d
 
 
 Q;;  # 	 	F%%(<fqjII    "!r   c                 2   ddl m} g }|D ]`}|                    || |||          }|rAt          t	          |                    D ]#}||                             ||                    $^|}at          t          d ||                     }d |D             }|S )aV  
        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]]
        rM   r\   c                 J    t          t          |           |hz
  dhz
            S )Nr   )rN   r-   )xys     r   <lambda>z.Converter._get_split_indices.<locals>.<lambda>  s!    T#a&&A3,!"455 r   c                 ,    g | ]}t          |          S  )sorted)rH   r   s     r   
<listcomp>z0Converter._get_split_indices.<locals>.<listcomp>  s    DDDAfQiiDDDr   )r_   r]   rb   ro   rT   r   rN   map)	re   rL   r^   rK   r]   split_indices_listrh   ri   dims	            r   rl   zConverter._get_split_indices  s    4 	'&&&&&$ 	5 	5G'?? O " 5 _!5!566 I IC&s+22?33GHHHHI &5""!55" 
 
 ED1CDDD!!r   c                    ddl m} |                    | ||||          }d}t          |          D ]Y\  }}	||         dk    r|	}
n|	|||                  z  }
|
dk    r||         d         }n||         d         dz   |
z  }||	|
z  z  |z   }Z|S )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
        rM   r\   r   r<   )r_   r]   rb   rw   )rW   re   rL   r^   rK   r]   ri   sliced_indexr~   ra   slice_shaperS   s               r   rn   zConverter._get_sliced_index  s    8 	'&&&&&#;;^\=-
 
 !.11 		I 		IHAuA"$$##}\!_'EEa'*1-(+A.2{B'5K+?@5HLLr   N)T)__name__
__module____qualname____doc__r   r   r
   r   r9   r,   staticmethodr+   rU   rV   rc   rm   rl   rn   r   r   r   r   r      sK        0 0 0"
 
 

 
 

 
 
h h h hT#J #J #JJ $ $ \$L % % \%N   \6 B B \BH #" #" \#"J 1" 1" \1"f + + \+ + +r   r   )r   r"   numpyrF   rP   utils.log_utilsr   r   r   r   r   <module>r      s|           ) ) ) ) ) )A A A A A A A A A Ar   