Ë
    éÓ^j'#  ã                   ó‚   — d Z ddlmZ ddlmZmZmZ ddlZddlm	Z	 ddl
mZmZ ddlmZ  G d„ de	j                  «      Zy)	zàBase training task abstraction.

This module provides the base TrainingTask class that encapsulates a complete
forward pass including loss computation. Tasks return a dictionary with loss
components and outputs for logging.
é    )Únullcontext)ÚAnyÚDictÚOptionalN)Úget_state_dictÚunwrap_model)Ú
ModelEmaV3c                   ó@  ‡ — e Zd ZdZ	 	 	 d(deej                     deej                     defˆ fd„Z	ˆ fd„Z
	 d)dee   d	d fd
„Z	 	 d*dedee   d	eej                     fd„Zd+ded	eej                     fd„Z	 	 	 d,dededeej                     d	ej                  fd„Zd	efd„Z	 	 d*dedee   d	eej                     fd„Zd)dee   d	dfd„Zd+defd„Zd-deej                     ded	eej                     fd„Zd-deej                     ded	eeef   fd„Z	 	 	 d.deeeef      dedeej                     ded	df
d„Zdefded	eeef   fd „Z	 	 	 d/d!eeef   d"eeeef      deded	df
d#„Z d$„ Z!d%ejD                  d&ejD                  d	eeejD                  f   fd'„Z#ˆ xZ$S )0ÚTrainingTaska  Base class for training tasks.

    A training task encapsulates a complete forward pass including loss computation.
    Tasks return a dictionary containing the training loss and other components for logging.

    The returned dictionary must contain:
        - 'loss': The training loss for backward pass (required)
        - 'output': Model output/logits for metric computation (recommended)
        - Other task-specific loss components for logging (optional)

    Args:
        device: Device for task tensors/buffers (defaults to cpu)
        dtype: Dtype for task tensors/buffers (defaults to torch default)
        verbose: Enable info logging

    Example:
        >>> task = SomeTask(model, criterion, device=torch.device('cuda'))
        >>>
        >>> # Prepare for distributed training (if needed)
        >>> if distributed:
        >>>     task.prepare_distributed(device_ids=[local_rank])
        >>>
        >>> # Training loop
        >>> result = task(input, target)
        >>> result['loss'].backward()
    NÚdeviceÚdtypeÚverbosec                 ó¦   •— t         ‰| �  «        |�|nt        j                  d«      | _        |�|nt        j                  «       | _        || _        y )NÚcpu)ÚsuperÚ__init__Útorchr   Úget_default_dtyper   r   )Úselfr   r   r   Ú	__class__s       €úY/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/timm/task/task.pyr   zTrainingTask.__init__-   sE   ø€ ô 	‰ÑÔØ &Ð 2‘f¼¿¹ÀUÓ8KˆŒØ#Ð/‘U´U×5LÑ5LÓ5NˆŒ
Øˆ�ó    c                 ó°   •—  t        j                  d«      j                  |i |¤Ž}|j                  | _        |j                  | _        t        ‰| �  |i |¤ŽS )zFMove task to device/dtype, keeping self.device and self.dtype in sync.r   )r   ÚemptyÚtor   r   r   )r   ÚargsÚkwargsÚdummyr   s       €r   r   zTrainingTask.to8   sL   ø€ à!”—‘˜A“×!Ñ! 4Ð2¨6Ñ2ˆØ—l‘lˆŒØ—[‘[ˆŒ
Ü‰w‰z˜4Ð* 6Ñ*Ð*r   Ú
device_idsÚreturnc                 ó   — | S )aÈ  Prepare task for distributed training.

        This method wraps trainable components in DistributedDataParallel (DDP)
        while leaving non-trainable components (like frozen teacher models) unwrapped.

        Should be called after task initialization but before training loop.

        Args:
            device_ids: List of device IDs for DDP (e.g., [local_rank])
            **ddp_kwargs: Additional arguments passed to DistributedDataParallel

        Returns:
            self (for method chaining)

        Example:
            >>> task = LogitDistillationTask(student, teacher, criterion)
            >>> task.compile()
            >>> task.prepare_distributed(device_ids=[args.local_rank])
        © )r   r   Ú
ddp_kwargss      r   Úprepare_distributedz TrainingTask.prepare_distributed?   s	   € ð2 ˆr   ÚbackendÚmodec                  ó   — y)a'  Compile hot task components before distributed wrapping.

        Subclasses should compile the train/eval modules that do the tensor
        work, not the outer task wrapper. The return value is the eval-facing
        compiled module/callable used by validation and checkpoint export.
        Nr"   ©r   r%   r&   Úcompile_kwargss       r   ÚcompilezTrainingTask.compileZ   s   € ð r   FÚemac                 ó:   — |rt        | dd«      S t        | d| «      S )z1Return the module that owns trainable parameters.Útrainable_module_emaNÚtrainable_module)Úgetattr)r   r+   s     r   Úget_trainable_modulez!TrainingTask.get_trainable_moduleh   s%   € áÜ˜4Ð!7¸Ó>Ð>Ü�tÐ/°Ó6Ð6r   ÚdecayÚ
use_warmupc                 ó`   — t        | j                  «       f|||dœ|¤Ž| _        | j                  S )z+Create an EMA copy of the trainable module.)r1   r2   r   )r	   r0   r-   )r   r1   r2   r   r   s        r   Ú	setup_emazTrainingTask.setup_eman   sC   € ô %/Ø×%Ñ%Ó'ð%
àØ!Øñ	%
ð
 ñ%
ˆÔ!ð ×(Ñ(Ð(r   c                 ó*   — | j                  d¬«      duS )z5Return whether this task has an EMA trainable module.T©r+   N)r0   )r   s    r   Úhas_emazTrainingTask.has_ema   s   € à×(Ñ(¨TÐ(Ó2¸$Ð>Ð>r   c                 ó˜   — | j                  «       syt        j                  | j                  d¬«      f||dœ|¤Ž| _        | j                  S )z3Compile the EMA eval model if one has been created.NTr6   )r%   r&   )r7   r   r*   Úget_eval_modelÚeval_model_emar(   s       r   Úcompile_emazTrainingTask.compile_emaƒ   sU   € ð �|‰|Œ~ØÜ#Ÿm™mØ×Ñ DÐÓ)ð
àØñ
ð ñ	
ˆÔð ×"Ñ"Ð"r   Ústepc                 óš   — | j                  «       r;| j                  d¬«      j                  t        | j                  «       «      |¬«       yy)z3Update EMA state from the current trainable module.Tr6   )r<   N)r7   r0   Úupdater   )r   r<   s     r   Ú
update_emazTrainingTask.update_ema”   s@   € à�<‰<Œ>Ø×%Ñ%¨$Ð%Ó/×6Ñ6´|ÀD×D]ÑD]ÓD_Ó7`ÐgkÐ6Õlð r   Úexclude_headc                 ó’   — | j                  «       }|r!|j                  «       D �cg c]  }|‘Œ c}dd S |j                  «       S c c}w )z/Return parameters to use for gradient clipping.Néþÿÿÿ)r0   Ú
parameters)r   r@   r.   Úps       r   Úget_clip_parametersz TrainingTask.get_clip_parameters™   sI   € à×4Ñ4Ó6ÐÙØ/×:Ñ:Ó<Ö=˜!’AÒ=¸c¸rÐBÐBØ×*Ñ*Ó,Ð,ùò >s   ¥	AÚmodulec                 ój   — |€0|rdnd}t        | |«      rt        | |«      S | j                  |¬«      }|S )zÃReturn the eval model/callable used for validation.

        Checkpoint state_dict handling uses unwrap_model separately so DDP and
        compiled wrappers do not leak into saved keys.
        r:   Ú
eval_modelr6   )Úhasattrr/   r0   )r   rF   r+   Ú	eval_attrs       r   r9   zTrainingTask.get_eval_model    sB   € ð ˆ>Ù,/Ñ(°\ˆIÜ�t˜YÔ'Ü˜t YÓ/Ð/Ø×.Ñ.°3Ð.Ó7ˆFØˆr   c                 ó   — i S )z:Return task-owned state outside the eval model state_dict.r"   )r   rF   r+   s      r   Úget_task_statezTrainingTask.get_task_state­   s   € àˆ	r   ÚstateÚstrictc                  ó   — y)z8Load task-owned state outside the eval model state_dict.Nr"   )r   rM   rN   rF   r+   s        r   Úload_task_statezTrainingTask.load_task_state±   s   € ð r   c                 ó˜   — | j                  |¬«      }|€i S |rdnd}|rdnd}| j                  |¬«      }|t        ||«      i}|r|||<   |S )z3Return checkpoint state entries owned by this task.r6   Ústate_dict_emaÚ
state_dictÚtask_state_emaÚ
task_state)r9   rL   r   )r   r+   Ú	unwrap_fnrH   Ú	model_keyÚtask_keyrU   rM   s           r   Úget_checkpoint_statez!TrainingTask.get_checkpoint_state»   sk   € ð ×(Ñ(¨SÐ(Ó1ˆ
ØÐØˆIá(+Ñ$°ˆ	Ù'*Ñ#°ˆØ×(Ñ(¨SÐ(Ó1ˆ
àœN¨:°yÓAÐBˆÙØ(ˆE�(‰OØˆr   rS   rU   c                 ó¼   — | j                  |¬«      }|€|rt        d«      ‚t        d«      ‚t        |«      j                  ||¬«       | j	                  |||¬«       y)z-Load model and task-owned checkpoint entries.r6   Nz4Cannot load EMA checkpoint state before setup_ema().z3Cannot load checkpoint state without an eval model.)rN   )rN   r+   )r9   ÚRuntimeErrorr   Úload_state_dictrP   )r   rS   rU   r+   rN   rH   s         r   Úload_checkpoint_statez"TrainingTask.load_checkpoint_stateÎ   se   € ð ×(Ñ(¨SÐ(Ó1ˆ
ØÐÙÜ"Ð#YÓZÐZÜÐTÓUÐUÜ�ZÓ ×0Ñ0°ÀFÐ0ÔKØ×Ñ˜Z°¸CÐÕ@r   c                 óz   — | j                  «       }|� || urt        |d«      r|j                  «       S t        «       S )zÏReturn a no-sync context for gradient accumulation.

        Tasks that wrap a trainable component with DDP delegate to that
        component's no_sync(). Non-distributed tasks use a no-op context.
        Úno_sync)r0   rI   r_   r   )r   rF   s     r   r_   zTrainingTask.no_syncÞ   s=   € ð ×*Ñ*Ó,ˆØÐ &°Ñ"4¼ÀÈÔ9SØ—>‘>Ó#Ð#Ü‹}Ðr   ÚinputÚtargetc                 ó   — t         ‚)zðPerform forward pass and compute loss.

        Args:
            input: Input tensor [B, C, H, W]
            target: Target labels [B]

        Returns:
            Dictionary with at least 'loss' key containing the training loss
        )ÚNotImplementedError)r   r`   ra   s      r   ÚforwardzTrainingTask.forwardé   s
   € ô "Ð!r   )NNT)N)ÚinductorN)F)g§èH.ÿï?FN)NF)TNF)NFT)%Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   Úboolr   r   Úlistr$   ÚstrÚnnÚModuler*   r0   Úfloatr4   r7   r;   Úintr?   rE   r9   r   r   rL   rP   r   rY   r]   r_   ÚTensorrd   Ú__classcell__)r   s   @r   r   r      sÜ  ø„ ñð: .2Ø+/Ø ñ		à˜UŸ\™\Ñ*ð	ð ˜EŸK™KÑ(ð	ð õ		ô+ð *.ñà  ™ðð 
ó	ð: &Ø"&ñàðð ˜3‘-ðð
 
�"—)‘)Ñ	óñ7¨ð 7¸À"Ç)Á)Ñ9Ló 7ð "Ø$Ø-1ñ	)àð)ð ð)ð ˜UŸ\™\Ñ*ð	)ð 
�‰ó)ð"?˜ó ?ð &Ø"&ñ#àð#ð ˜3‘-ð#ð
 
�"—)‘)Ñ	ó#ñ"m˜x¨™}ð m¸ó mñ
-°ó -ñ X¨b¯i©iÑ%8ð Àdð ÐW_Ð`b×`iÑ`iÑWjó ñ X¨b¯i©iÑ%8ð Àdð ÐW[Ð\_ÐadÐ\dÑWeó ð  Ø*.Øñà˜D  c ™NÑ+ðð ðð ˜RŸY™YÑ'ð	ð
 ðð 
óð Ø"ñàðð 
ˆc�3ˆh‰ó	ð, 48ØØñAà˜S #˜X™ðAð !  c¨3 h¡Ñ0ðAð ð	Að
 ðAð 
óAò 	ð"à—<‘<ð"ð —L‘Lð"ð 
ˆc�5—<‘<ÐÑ	 ÷	"r   r   )ri   Ú
contextlibr   Útypingr   r   r   r   Útorch.nnrm   Útimm.utils.modelr   r   Útimm.utils.model_emar	   rn   r   r"   r   r   ú<module>rx      s3   ðñõ #ß &Ñ &ã Ý ç 9Ý +ôf"�2—9‘9õ f"r   