o
    ߗiP                  	   @   s`  U d dl Z 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mZ d dlZd dlmZ d dlmZ d dlmZm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"m#Z#m$Z$ d dl%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, d dl-m.Z.m/Z/m0Z0m1Z1 d dl2m3Z3 d dl4m5Z5 ddl6m7Z7 e8e9Z:ej;e<d< g dZ=G dd de*Z>G dd de'Z?G dd de?Z@	d6deeAe	f dedeBde&fddZCd ee& dee& fd!d"ZDdeeAe	f d#eBde)fd$d%ZE	d6d ee) d&eBdeee) ef fd'd(ZFde!defd)d*ZGd+ed,edeBfd-d.ZHd/ejId0edeBfd1d2ZJd3ee) dedeBfd4d5ZKdS )7    N)ChainMap)reduce)AnycastDictListOptionalTupleUnion)narrow_tensor_by_index)dedup_save_plans)FLATTEN_MAPPINGflatten_state_dict)_flatten_sharded_tensors)set_element)BytesStorageMetadataChunkStorageMetadataMetadataMetadataIndexSTATE_DICT_TYPESTORAGE_TYPESStorageMetaTensorStorageMetadata)LoadPlanLoadPlannerReadItemSavePlanSavePlanner	WriteItemWriteItemType)"_create_default_metadata_only_plan_create_read_items_create_write_items_init_state_dict)find_state_dict_object)DTensor   )_versionlogger)DefaultSavePlannerDefaultLoadPlannercreate_default_local_load_plancreate_default_global_load_plancreate_default_local_save_plancreate_default_global_save_planc                   @   s   e Zd ZU eed< 				d"dededee ded	df
d
dZ		d#dedee	 ded	dfddZ
d	efddZdee d	eee ef fddZded	efddZded	eejejf fddZded	efddZdedefd d!ZdS )$r)   mappingsTNFr   flatten_sharded_tensorsdedup_replicated_tensorsdedup_save_to_lowest_rankreturnc                 C   s2   || _ || _i | _|| _|d urtd d S d S )NzDefaultSavePlanner's `dedup_replicated_tensors` argument is being deprecated, and no longer has any effect. Please remove this argument from your call.)r   r0   r/   r2   r(   warning)selfr   r0   r1   r2    r6   j/home/ubuntu/transcripts/venv/lib/python3.10/site-packages/torch/distributed/checkpoint/default_planner.py__init__E   s   zDefaultSavePlanner.__init__
state_dictstorage_metais_coordinatorc                 C   s2   | j r
t |\}| _| jrt|}|| _|| _d S N)r   r/   r0   r   r9   r;   )r5   r9   r:   r;   r6   r6   r7   set_up_plannerW   s   
z!DefaultSavePlanner.set_up_plannerc                 C   s0   t | j| j}| jrtj|| jd}|| _| jS )Nplanner_data)r-   r9   r;   r   dataclassesreplacer/   plan)r5   rB   r6   r6   r7   create_local_pland   s
   z$DefaultSavePlanner.create_local_plan	all_plansc                 C   sp   t || j}t|\}}| jr#dd |D }tt| }tj||d}t||s,t	d|| _
|| _| j
| jfS )Nc                 S   s   g | ]}|j qS r6   r>   ).0pr6   r6   r7   
<listcomp>x   s    z9DefaultSavePlanner.create_global_plan.<locals>.<listcomp>r>   zFailed to validate global plan)r   r2   r.   r   dictr   r@   rA   _validate_global_plan
ValueErrorglobal_planmetadata)r5   rD   rK   rL   planner_data_dictmerged_mappingsr6   r6   r7   create_global_planl   s   
z%DefaultSavePlanner.create_global_plannew_planc                 C   s
   || _ |S r<   )rB   r5   rP   r6   r6   r7   finish_plan   s   zDefaultSavePlanner.finish_plan
write_itemc                 C      |  |j}| ||S r<   )lookup_objectindextransform_object)r5   rS   objectr6   r6   r7   resolve_data      zDefaultSavePlanner.resolve_datarV   c                 C      t | j|S zSExtension from the planner interface to make it easy to extend the default planner.r$   r9   r5   rV   r6   r6   r7   rU         z DefaultSavePlanner.lookup_objectrX   c                 C   s(   |j tjkrt }t|| |}|S r\   )typer   BYTE_IOioBytesIOtorchsave)r5   rS   rX   bytesr6   r6   r7   rW      s
   z#DefaultSavePlanner.transform_object)TTNFNF)__name__
__module____qualname__r   __annotations__boolr   r8   r   r   r=   r   rC   r   r	   r   rO   rR   r   r
   rd   Tensorrb   rc   rY   r   r   rU   rW   r6   r6   r6   r7   r)   B   sL   
 


r)   c                	   @   s  e Zd ZU dZeed< eed< 			d(dededed	d
fddZ	
	d)dede	e
 ded	d
fddZd	efddZdee d	ee fddZded	efddZdedejd	d
fddZdefddZded ejd	d
fd!d"Zd#ed	ejfd$d%Zded ejfd&d'Zd
S )*r*   ak  
    DefaultLoadPlanner that adds multiple features on top of LoadPlanner.

    In particular it adds the following:

    flatten_state_dict: Handle state_dict with nested dicts
    flatten_sharded_tensors: For FSDP in 2D parallel mode
    allow_partial_load: If False, will raise a runtime error if a key is present in state_dict, but not in the checkpoint.
    original_state_dictr/   TFr   r0   allow_partial_loadr3   Nc                 C   s"   || _ || _i | _i | _|| _d S r<   )r   r0   rn   r/   ro   )r5   r   r0   ro   r6   r6   r7   r8      s
   
zDefaultLoadPlanner.__init__r9   rL   r;   c                 C   sF   t | || _| jrt|}| jrt|\}| _|| _|| _|| _d S r<   )	r#   rn   r0   r   r   r/   r9   rL   r;   )r5   r9   rL   r;   r6   r6   r7   r=      s   
z!DefaultLoadPlanner.set_up_plannerc                 C   s   | j d usJ | jr=t| j }t| j j }|| }|r=dt_t| j\}}t| }||@ r:||| _| _	d t_t
| j| j | j S )N2_3)rL   r   setr9   keysstate_dict_metadatar'   _derived_versionrn   r/   r+   ro   )r5   current_keys	load_keysmissing_keysold_state_dictold_mappingsold_keysr6   r6   r7   rC      s"   z$DefaultLoadPlanner.create_local_planrK   c                 C   s   t |S r<   )r,   )r5   rK   r6   r6   r7   rO      s   z%DefaultLoadPlanner.create_global_planrP   c                 C   s   |S r<   r6   rQ   r6   r6   r7   rR         zDefaultLoadPlanner.finish_plan	read_itemvaluec                 C   sH   | j rt| j| j|jj tj|dd d S tj|dd| j|jj< d S )NF)weights_only)	r   r   rn   r/   
dest_indexfqnrd   loadr9   )r5   r|   r}   r6   r6   r7   
load_bytes   s   zDefaultLoadPlanner.load_bytesc                 C   rT   r<   )lookup_tensorr   transform_tensorr5   r|   tensorr6   r6   r7   resolve_tensor   rZ   z!DefaultLoadPlanner.resolve_tensorr   c                 C   s   d S r<   r6   r   r6   r6   r7   commit_tensor  r{   z DefaultLoadPlanner.commit_tensorrV   c                 C   r[   r\   r]   r^   r6   r6   r7   r     r_   z DefaultLoadPlanner.lookup_tensorc                 C   s   t ||j|jS r\   )r   dest_offsetslengthsr   r6   r6   r7   r   
  s   z#DefaultLoadPlanner.transform_tensor)TTFrg   )rh   ri   rj   __doc__r   rk   r   rl   r8   r   r   r=   r   rC   r   rO   rR   r   rb   rc   r   r   rd   rm   r   r   r   r   r6   r6   r6   r7   r*      sF   
 


'r*   c                	       s`   e Zd ZdZd fdd	Zdededefdd	Z		
dde	de
e deddf fddZ  ZS )_EmptyStateDictLoadPlannera  
    Extension of DefaultLoadPlanner, which rebuilds state_dict from the saved metadata.
    Useful for loading in state_dict without first initializing a model, such as
    when converting a DCP checkpoint into a Torch save file.

    . N.B. `state_dict` must be an empty dictionary when used with this LoadPlanner

    .. warning::
        Because the entire state dict is initialized, It's recommended to only utilize
        this LoadPlanner on a single rank or process to avoid OOM.

    Nc                    s   || _ t j|i | d S r<   )rr   superr8   )r5   rr   argskwargs	__class__r6   r7   r8     s   z#_EmptyStateDictLoadPlanner.__init__keyrL   r3   c                    s~    j d u rdS | j v r	 g }|j|}|D ]}|r*|d|d t|g q|| qt fdd|D r=dS dS )NT.c                 3   s    | ]}| j v V  qd S r<   )rr   )rE   unflattened_keyr5   r6   r7   	<genexpr>3  s    zA_EmptyStateDictLoadPlanner._should_include_key.<locals>.<genexpr>F)rr   r?   getappendjoinstrany)r5   r   rL   unflattened_keysr?   r   r6   r   r7   _should_include_key!  s   

z._EmptyStateDictLoadPlanner._should_include_keyFr9   r;   c                    s   |rJ |d us
J |j  D ]-\}}| ||sqt|tr)tj|j|jj	d}||j
v r8t||j
| | q|||< qt ||| d S )N)dtype)rs   itemsr   
isinstancer   rd   emptysize
propertiesr   r?   r   r   r=   )r5   r9   rL   r;   kvr   r6   r7   r=   8  s   


z)_EmptyStateDictLoadPlanner.set_up_plannerr<   rg   )rh   ri   rj   r   r8   r   r   rl   r   r   r   r=   __classcell__r6   r6   r   r7   r     s    r   Tr9   rL   strictr3   c                 C   s   g }	 |   D ]Z\}}||jvr|rtd| dq|j| }t|trDt|dd d urD|j| krDtd|j d|  d| t|trY|j	
 d urX|t|||7 }q|t|||7 }qt|S )Nz&Missing key in checkpoint state_dict: r   r   zSize mismatch between saved z and current: z for )r   rs   RuntimeErrorr   r   getattrr   rJ   r%   device_meshget_coordinater!   r   )r9   rL   r   requestsr   objmdr6   r6   r7   r+   P  s*   



r+   rD   c                 C   s   | S )z
    Create global load plan used by DefaultLoadPlanner.

    The default load behavior involved no global coordination and this function
    currently doesn't change the local plans.
    r6   )rD   r6   r6   r7   r,   z  s   	r,   r;   c                 C   sT   g }|   D ]\}}t|tr|j dur|t||7 }q|t||7 }qt|S )a  
    Create the ``SavePlan`` used by DefaultSavePlanner.

    On non-coordinator ranks, this function ignores tensors and non-tensor objects,
    only producing writes for ShardedTensor objects.

    On the coordinator rank, produce writes for all values.
    N)r   r   r%   r   r   r"   r   )r9   r;   r   r   r   r6   r6   r7   r-     s   
r-   rewrite_index_hintsc           
      C   s   i }g }| D ]}g }|j D ]q}|jtjks|jj|vsJ |jtjkr0t ||jj< || q|j	dus7J t
t||jjt|j	j|j	jg d}|}|ratj|jt|jd}	tj||	d}|| |j	jdusvJ d|jj d|j|j	j q|tj||d q|t|fS )a6  
    Create the global plan and metadata used by DefaultSavePlanner.

    Metadata is produced by concatenating the metadata of all ``WriteItem`` from the supplied plans.

    The only global planning change is to update index hints in all ``MetadataIndex`` objects if
    ``rewrite_index_hints`` is True.
    N)r   r   chunks)rV   zZ
                    Cannot create MD for tensor without bounds.
                    FQN: z
                )r   )r   r`   r   SHARDrV   r   ra   r   r   tensor_datar   r   
setdefaultr   r   r@   rA   lenr   chunkr   )
rD   r   r   	new_plansrB   	new_itemsitem	tensor_mdnew_item	new_indexr6   r6   r7   r.     sJ   

r.   c                 C   s   t | }t|g\}}|S )zTReturn the ``Metadata`` if DefaultSavePlanner was used to checkpoint ``state_dict``.)r    r.   )r9   rB   _r   r6   r6   r7   _create_default_local_metadata  s   r   box0box1c                 C   sd   t | j}t|D ]&}| j| |j| |j|  kr dS |j| | j| | j|  kr/ dS q	dS )z9Check if two boxes overlap. Tuples are (offset, lengths).FT)r   offsetsrangesizes)r   r   ndimsir6   r6   r7   _check_box_overlap  s   
r   outer_box_size	inner_boxc                 C   s`   t t| D ]'}|j| dk r dS |j| dk r dS |j| |j|  | | kr- dS qdS )Nr   FT)r   r   r   r   )r   r   r   r6   r6   r7   _check_box_bounds  s   r   rK   c           
   	   C   s   d}|j  D ]j\}}t|trqt|jdkrqd}t|jD ]:\}}t|j|s5t	
d||j| d}|ttj|jd7 }|j|d d  D ]}t||rYt	
d||| d}qHq ttj|jd}	||	krqt	
d||	| d}q|S )NTr   z~
                        key:%s has out of bounds chunk:
                        tensor-size:%s chunk: %s
                    Fr&   z$key:%s has overlapping chunks: %s %szq
                    key:%s invalid fill tensor-volume:
                    %s chunks-volume: %s
                )rs   r   r   r   r   r   	enumerater   r   r(   r4   r   operatormulr   r   )
rK   rL   all_goodr   r}   chunks_volume	chunk_idxchunk0chunk1tensor_volumer6   r6   r7   rI     sH   
	
	rI   )T)Lr@   rb   loggingr   collectionsr   	functoolsr   typingr   r   r   r   r   r	   r
   rd   torch.distributed._shard._utilsr   .torch.distributed.checkpoint._dedup_save_plansr   )torch.distributed.checkpoint._nested_dictr   r   2torch.distributed.checkpoint._sharded_tensor_utilsr   &torch.distributed.checkpoint._traverser   %torch.distributed.checkpoint.metadatar   r   r   r   r   r   r   r   $torch.distributed.checkpoint.plannerr   r   r   r   r   r   r   ,torch.distributed.checkpoint.planner_helpersr    r!   r"   r#   "torch.distributed.checkpoint.utilsr$   torch.distributed.tensorr%    r'   	getLoggerrh   r(   Loggerrk   __all__r)   r*   r   r   rl   r+   r,   r-   r.   r   r   Sizer   rI   r6   r6   r6   r7   <module>   s   
$($
	WvB

*



7
