o
    i eb                     @   s  d Z ddlZddlZddlZ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 ddlmZ ddlmZ ddlmZ dd	lmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ da e! Z"dZ#dZ$dd Z%G dd dZ&dS )z>Utilities for saving/loading Trackable objects asynchronously.    N)logging)checkpoint_context)device_util)ShardedVariable)context)def_function)executor)device)ops)UninitializedVariable)Variable)metrics)object_identityasync_checkpoint!_create_copy_for_async_checkpointc                 C   s   || k rdS t ||  d S )a  Calculate the duration between start and end time.

  Args:
    start_time_seconds: The start time in seconds.
    end_time_seconds: The end time in seconds.

  Returns:
    The duration between the start and the end time. Return 0 if
    end_time_seconds < start_time_seconds.
  r   i@B )round)start_time_secondsend_time_seconds r   c/var/www/myenv/lib/python3.10/site-packages/tensorflow/python/checkpoint/async_checkpoint_helper.py_get_duration_microseconds5   s   r   c                   @   s   e Zd ZdZd+ddZejdd Zejdd Zd	d
 Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd Zdd Zdd Zedd Zd+dd Zd,d!d"Zd+d#d$Zd+d%d&Zd+d'd(Zd)d* ZdS )-AsyncCheckpointHelperz"Helper class for async checkpoint.Nc                 K   s  |rt |tjr| n|}||d< |  |du rtd|| _|| _d| _|   d| _	d| _
d| _d| _d| _d| _t pAd| _t| j| _d| _d| _d| _tjdd| _t| j d| _t tdu rvt aW d   dS W d   dS 1 sw   Y  dS )a  Initialize AsyncCheckpoint.

    Args:
      checkpointer_impl: The Checkpoint class to power the AsyncCheckpoint.
      root: The root object to checkpoint. `root` may be a trackable object or
        `WeakRef` of a trackable object.
      **kwargs: The keyword arguments representing the checkpointed variables.

    Raises:
      AttributeError: when checkpointer_impl is None.
    rootNz;checkpointer_impl cannot be None for AsyncCheckpointHelper.FzCPU:0   )maxsize) 
isinstanceweakrefref_maybe_initialize_trackableAttributeError_checkpointer_impl_checkpoint_items_checkpointcheckpointer_checkpoint_options_initialized_async_write_done_callback_original_nodes_object_map_tpu_embedding_objectsr   current_default_devicecanonicalize_save_file_prefix_use_checkpoint_save_async_save_threadqueueQueue_queueatexitregister_join_async_save_thread_async_error"_END_TIME_OF_LAST_ASYNC_WRITE_LOCK_END_TIME_OF_LAST_ASYNC_WRITEtime)selfcheckpointer_implr   kwargstrackable_rootr   r   r   __init__I   s@   	
"zAsyncCheckpointHelper.__init__c              	   C   sh   | j  D ],\}}t|tst|trqt|j ||	  W d   n1 s,w   Y  qdS )zCopy the checkpointed variables from the host CPU to the accelerator.

    TODO(chienchunh): Get the concrete function before firstly called to avoid
                      hangining the accelerators idle during function tracing.
    N)
r(   itemsr   r   hasattr_TPU_EMBEDDING_ATTRr
   r	   assign
read_value)r:   accelerator_varcpu_varr   r   r   _copy_from_cpu   s   z$AsyncCheckpointHelper._copy_from_cpuc              	   C   s|   | j  D ],\}}t|tst|trqt|j ||	  W d   n1 s,w   Y  q| j
D ]}|  q5dS )zCopy the checkpointed variables from the accelerator to the host CPU.

    TODO(chienchunh): Get the concrete function before firstly called to avoid
                      hangining the accelerators idle during function tracing.
    N)r(   r?   r   r   r@   rA   r
   r	   rB   rC   r)   _retrieve_variables)r:   rD   rE   tpu_embeddingr   r   r   _copy_to_cpu   s   

z"AsyncCheckpointHelper._copy_to_cpuc                 C   s   |r@|  }| j| t|ttfr| | t|tr"| 	| |j
dd D ]}||v r1q*|| || q*|sdS dS )a  Create the copied nodes and variables while traversing the nodes.

    This method performs a BFS to traverse the nodes while avoiding duplicated
    visits. Throughout the process, self._mapping, self._original_nodes, and
    self._var_pairs are populated.

    Args:
      to_traverse: A deque that stores the nodes to be traversed.
      visited: A list of nodes that have been visited.
    
checkpoint)	save_typeN)popleftr'   appendr   r   r   _copy_trackabler@   rA   _handle_tpu_embedding_trackable_childrenvaluesadd)r:   to_traversevisitedcurrent_trackablechildr   r   r   _traverse_variables   s"   



z)AsyncCheckpointHelper._traverse_variablesc                 C   s$   | j du r| jdi | j| _ | j S )z3Gets or creates the underlying Checkpoint instance.Nr   )r"   r    r!   r:   r   r   r   r#      s   
z"AsyncCheckpointHelper.checkpointerc           
      C   s`  | j rdS g | _t | _g | _tg }t }| j	
 D ]#}t|ttfr-| | n
t|tr7| | || || q| || | jD ]=}dt|v r| }|D ].}| jD ](}t|tsfq^z|||}W n ttfyy   Y q^w t|ttfr| | q^qYqK|  j }	td|	 | j|  j_t j!| j"dd| _#| j#$  d| _ dS )z/Initialize the async checkpoint internal state.Nget_slot_namesz0Initializing async checkpoint's save_counter: %dT)targetdaemon)%r%   r'   r   ObjectIdentityDictionaryr(   r)   collectionsdequeObjectIdentitySetr!   rQ   r   r   r   rN   r@   rA   rO   rM   rR   rW   dirrY   get_slotr   KeyErrorr#   save_counternumpyr   info_saver	threadingThread_async_saver/   start)
r:   rS   rT   vrU   
slot_names	slot_nameoriginal_variableoriginal_slot_variablerc   r   r   r   _ensure_initialized   sX   










z)AsyncCheckpointHelper._ensure_initializedc                 C   s*   | j r| j }d| _ tdt| |dS )zMExpose the most recent error from the async saving thread to the caller.
    NzJPropagating the most recent error from the async thread before joining: %s)r6   r   errorstr)r:   er   r   r   _check_async_thread_error  s   z/AsyncCheckpointHelper._check_async_thread_errorc                 C   sz   z7z| j jddd td | jdur| j  W n tjy)   td Y nw W | 	  dS W | 	  dS | 	  w )a  Join the async save thread.

    The steps for terminating the async save thread:
    1). Put will succeed when the last async save event is done. Putting a false
        triggers the async save thread's while loop to end. We use put instead
        of sync because sync does not have a timeout argument.
    2). Join the async save thread. (The thread may finish before joining.)
    Fi,  )timeoutzJoining the async save thread.NzrTimeout waiting for the async save thread; terminating the thread instead. The last checkpoint may be incomeplete.)
r2   putr   re   r/   joinr0   Fullrq   rt   rX   r   r   r   r5     s   	


z-AsyncCheckpointHelper._join_async_save_threadc                 C   s  t tjddd | j rtd| j t		 }zdzGt
| j7 t # | jr7|  | j| j n|  j| j| j| jd W d   n1 sNw   Y  W d   n1 s]w   Y  W n tyx } z	|| _W Y d}~nd}~ww W | j  n| j  w t		 }tjtt||d t tjttt|d |aW d   n1 sw   Y  | j sW d   n1 sw   Y  td dS )z2The thread function for the async checkpoint save.F)enable_asyncenable_streaming_enqueuez0Starting async checkpoint save on the device: %s)optionswrite_done_callbackN	api_labelmicrosecondsz3Async save thread reached the end of the execution.)r   executor_scoper   new_executorr2   getr   re   r+   r9   r
   r	   r   async_metrics_contextr.   r#   saver-   r$   _writer&   	Exceptionr6   	task_doner   AddAsyncCheckpointWriteDuration_ASYNC_CHECKPOINTr   r7   AddTrainingTimeSavedr8   )r:   async_save_start_timers   async_save_end_timer   r   r   ri   -  sj   


5z!AsyncCheckpointHelper._async_savec                 C   sl   t j|jjddd }t| t|j|j	|j
|jd}W d   n1 s*w   Y  || j|< dS )zvCreate a new instance for the input trackable.

    Args:
      original_var: Input Variable object to be copied.
    CPUr   )device_typedevice_index)	trainableshapedtypenameN)pydev
DeviceSpecfrom_stringr	   replace	to_stringr
   r   r   r   r   _shared_namer(   )r:   original_var	op_devicenew_varr   r   r   _copy_for_variablef  s   z(AsyncCheckpointHelper._copy_for_variablec                 C   sB   g }|j D ]}| | || j|  qt||jd| j|< dS )zCreate a new instance for the input ShardedVariable.

    Args:
      original_var: Input ShardedVariable object to be copied.
    )r   N)
_variablesr   rM   r(   r   r   )r:   r   copied_varsrk   r   r   r   _copy_for_sharded_variablev  s   

z0AsyncCheckpointHelper._copy_for_sharded_variablec                 C   s8   t |tr| | dS t |tr| | dS td)zCreate a new instance for the input trackable.

    Args:
      original_trackable: The trackable instance to be copied.

    Raises:
      AttributeError: if the input trackable is not Variable or ShardedVariable.
    z/Only Variable or ShardedVariable can be copied.N)r   r   r   r   r   r   )r:   original_trackabler   r   r   rN     s
   
	
z%AsyncCheckpointHelper._copy_trackablec                 C   sp   t |tr
t|jstdt| |j|j|jr|jd nd|jd}|| j	|< || j
vr6| j
| dS dS )zHandle TPUEmbedding.

    Args:
      tpu_embedding: TPUEmbedding object to be handled.

    Raises:
      AttributeError: if the input trackable is not TPUEmbedding type.
    z#Expecting TPUEmbedding type; got %sr   N)feature_config	optimizer#pipeline_execution_with_tensor_core)r@   rA   callabler   r   type_feature_config_table_config$_pipeline_execution_with_tensor_corer(   r)   rM   )r:   rH   new_embeddingr   r   r   rO     s&   	


z+AsyncCheckpointHelper._handle_tpu_embeddingc                 C   s
   |   jS )a  An integer variable numbering the checkpoint events.

    This is maintained by the underlying tf.train.Checkpoing object employed by
    AsyncCheckpoint class. The number starts at 0 and gets incremented for each
    checkpoint event.

    Returns:
      The save counter variable.
    )r#   rc   rX   r   r   r   rc     s   
z"AsyncCheckpointHelper.save_counterc                 C   s   |  || dS )Save the checkpointed variables.

    Args:
      save_path: The file prefix of the checkpoint file.
      options: Optional CheckpointOption instance.

    Returns:
      The full path of the checkpoint file.
    N)r   r:   	save_pathr{   r   r   r   write  s   
zAsyncCheckpointHelper.writec                 C   s   |    t }| j  |   |   t  || _d| _	|r&t

|nd| _| jr0d| j_|| _| jd t }tjtt||d |S )a  Save the checkpointed variables.

    This method has exactly the same logic as save(), except it does not
    increment the underlying save_counter, which is done by the caller, e.g.,
    CheckpointManager.

    Args:
      save_path: The file prefix of the checkpoint file.
      options: Optional CheckpointOption instance.
      write_done_callback: Optional callback function executed after the async
        write is done.

    Returns:
      The full path of the checkpoint file.
    FNTr}   )rp   r9   r2   rw   rI   rt   r   
async_waitr-   r.   copyr$   $experimental_enable_async_checkpointr&   rv   r   AddCheckpointWriteDurationr   r   )r:   r   r{   r|   write_start_timewrite_end_timer   r   r   r     s*   
zAsyncCheckpointHelper._writec                 C   s   |    t }| j  |   |   |  j d }d	||}t
  || _d| _|r5t|nd| _| jr?d| j_| jd t }tjtt||d |S )r   r   z{}-{}TNFr}   )rp   r9   r2   rw   rI   rt   r#   rc   rd   formatr   r   r-   r.   r   r$   r   rv   r   r   r   r   )r:   r   r{   save_start_timerc   	full_pathsave_end_timer   r   r   r     s(   
zAsyncCheckpointHelper.savec                 C   s   |  ||S )a  Restore the checkpointed variables.

    This method has exactly the same logic as restore(). This method is
    implemented only to fulfill the duty of subclassing tf.train.Checkpoint.

    Args:
      save_path: The full name of the checkpoint file to be restored.
      options: CheckpointOption instance.

    Returns:
      A load status object, which can be used to make assertions about the
      status of a checkpoint restoration. See tf.train.Checkpoint.restore()
      for more details.
    )restorer   r   r   r   read@  s   zAsyncCheckpointHelper.readc                 C   sR   |rt  |n| j| _| jrd| j_| j  |  || j}| jr'|   |S )a`  Restore the checkpointed variables.

    Args:
      save_path: The full name of the checkpoint file to be restored.
      options: CheckpointOption instance.

    Returns:
      A load status object, which can be used to make assertions about the
      status of a checkpoint restoration. See tf.train.Checkpoint.restore()
      for more details.
    F)	r   r$   r   r2   rw   r#   r   r%   rF   )r:   r   r{   statusr   r   r   r   Q  s   
zAsyncCheckpointHelper.restorec                 C   s   | j   td dS )z+Sync on any ongoing save or restore events.zSync on ongoing save/restore.N)r2   rw   r   re   rX   r   r   r   syncq  s   
zAsyncCheckpointHelper.sync)N)NN)__name__
__module____qualname____doc__r>   r   functionrF   rI   rW   r#   rp   rt   r5   ri   r   r   rN   rO   propertyrc   r   r   r   r   r   r   r   r   r   r   r   F   s2    
K

6
9!



6
=
 r   )'r   r3   r]   r   r0   rg   r9   r   abslr   tensorflow.python.checkpointr   tensorflow.python.distributer   -tensorflow.python.distribute.sharded_variabler   tensorflow.python.eagerr   r   r   tensorflow.python.frameworkr	   r   r
   +tensorflow.python.ops.resource_variable_opsr   tensorflow.python.ops.variablesr   0tensorflow.python.saved_model.pywrap_saved_modelr   tensorflow.python.utilr   r8   Lockr7   r   rA   r   r   r   r   r   r   <module>   s6   