o
    "j                     @   sB   d dl Z d dlZd dlZd dlmZ d dlmZ G dd dZdS )    N)StrategyGroupBasec                   @   sN   e Zd ZdZi dfddZdd Zdd Zd	d
 Zdd Zdd Z	dd Z
dS )OrthogonalStrategya  
    A hybrid of multiple distributed strategies. Strategies need to be orthogonal, means the ranks are organized like
    a square if there are two strategies, a cube if there aree three strategies, etc.

    Args:
        list_of_strategy(list): Stategy in the list should be represented as tuple, format as (strategy_name, degree, strategy_class).
        fused_strategy_dict(dict, optional): Exist strategies can be fused to new strategy. Use the name of new strategy as key, a list of
            strategy names you want to fuse as value.

    Returns:
        The instance of strategy.

    Examples:
        .. code-block:: python

            >>> # doctest: +REQUIRES(env: DISTRIBUTED)
            >>> import paddle
            >>> import paddle.distributed as dist
            >>> from paddle.distributed.fleet.base.strategy_group import DPGroup, MPGroup, PPGroup
            >>> from paddle.distributed.fleet.base.orthogonal_strategy import OrthogonalStrategy

            >>> dist.init_parallel_env()
            >>> strategy = OrthogonalStrategy([("dp", 2, DPGroup), ("mp", 2, MPGroup), ("pp", 2, PPGroup)], fused_strategy_dict={"check": ["mp", "pp"]})

    Nc           
         s   | _ | _|d ur|nttt  _i  _i  _dd |D  _	dd |D  _
td j	 _   dd  j
D } fddtj| D }tt| j _t|D ]\}}|d }|d  j|<  |}	|d	 |	 j|< qXi  _   d S )
Nc                 S      g | ]}|d  qS )r    .0strategyr   r   r/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/distributed/fleet/base/orthogonal_strategy.py
<listcomp>>   s    z/OrthogonalStrategy.__init__.<locals>.<listcomp>c                 S   r   )   r   r   r   r   r	   r
   A       Z
Coordinatec                 S   s   g | ]}t |qS r   )range)r   degreer   r   r	   r
   G   r   c                    s   g | ]} j | qS r   )_coordinate)r   coordselfr   r	   r
   H   s    
r   r      )Z_list_of_strategy_fused_strategy_dictlistr   distZget_world_size_strategy_rank_list_name_to_group_dict_name_to_degree_dict_list_of_strategy_name_list_of_degreecollections
namedtupler   _check_valid_strategy	itertoolsproductdictzip_coord_to_rank_dict	enumerate_calc_rank_list_name_to_fused_group_dict_create_fused_group)
r   Zlist_of_strategyZfused_strategy_dictZstrategy_rank_listrangesZlist_of_coordidxr   Zstrategy_name	rank_listr   r   r	   __init__2   s@   


zOrthogonalStrategy.__init__c                 C   s$   || j v sJ d| d| j| S )z
        Get strategy group with specific name.

        Args:
            name: The name of strategy group

        Returns:
            An instance of specific strategy group.
        Strategy group  is not created.)r   r   r   namer   r   r	   strategy_group[      

z!OrthogonalStrategy.strategy_groupc                 C   s$   || j v sJ d| d| j | S )z
        Get fused strategy group with specific name.

        Args:
            name: The name of fused strategy group

        Returns:
            (StrategyGroupBase): An instance of strategy group.
        zFused strategy group r-   )r&   r.   r   r   r	   fused_strategy_groupj   r1   z'OrthogonalStrategy.fused_strategy_groupc                 C   s(   || j v sJ d| d| j| jjS )z
        Get local rank in strategy group with specific name.

        Args:
            name: The name of strategy group

        Returns:
            (Integer): Local rank in specific strategy.
        r,   r-   )r   r   grouprankr.   r   r   r	   rank_in_strategyy   s   
z#OrthogonalStrategy.rank_in_strategyc                 C   s   t | jt t| jksJ d| j tdd | j}|t | jks/J dt | j|| j	 D ]}|D ]}|| jv sGJ d| dq8q4d S )NzDefined duplicated strategies: c                 S   s   | | S Nr   )xyr   r   r	   <lambda>   s    z:OrthogonalStrategy._check_valid_strategy.<locals>.<lambda>z=There are total {} ranks, but need {} ranks in this strategy.zCan not fuse strategy z without defined previous.)
lenr   set	functoolsreducer   r   formatr   values)r   Znum_of_ranksfused_strategyr   r   r   r	   r      s,   




z(OrthogonalStrategy._check_valid_strategyc              
   C   s  | j D ]}| j | }tt| j|}g }|D ]}|t| j|  qg }|D ]}|t| j|  q)g }tj	| D ]?}i }	g }
t
|D ]
\}}||	|| < qGtj	| D ]}t
|D ]
\}}||	|| < q]|
| j| jdi |	  qW||
 q=t|| j|< qd S )Nr   )r   r   r;   r   
differenceappendr   r   r   r    r$   r#   r   r   r&   )r   r/   r@   Znon_fused_strategyZnon_fused_rangesr   Zfused_rangesr*   Znon_fused_ranksZ
coord_dictranksiZnon_fused_rankZfused_ranksZ
fused_rankr   r   r	   r'      s8   

z&OrthogonalStrategy._create_fused_groupc           
      C   s   g }t | jD ]\}}||krq|t| qg }tj| D ](}g }t| j| D ]}t|}	|	|| || j| j	|	   q*|| q|S r6   )
r$   r   rB   r   r   r    r   insertr#   r   )
r   Zstrategy_axisr(   r)   r   r*   r   rC   valZ
coord_listr   r   r	   r%      s    z"OrthogonalStrategy._calc_rank_list)__name__
__module____qualname____doc__r+   r0   r2   r5   r   r'   r%   r   r   r   r	   r      s    
)r   )	r   r<   r   Zpaddle.distributeddistributedr   Z,paddle.distributed.fleet.base.strategy_groupr   r   r   r   r   r	   <module>   s   