Ë
    ëÓ^j-C  ã                  ó¤  — d Z ddlmZ ddlZddlmZ ddlmZmZ ddl	Z	ddl
mZmZ ddlmZ ddlmZ dd	lmZ dd
lmZ  e«       Z ed¬«       G d„ d«      «       Zdd„Z	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Z	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Z	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd„Zdd„Z	 	 d	 	 	 	 	 	 	 	 	 	 	 dd„Zy)a
  Auto-batch probing: find a safe micro-batch size before training.

Probe assumptions (worst-case so training does not OOM):
- Resolution: When multi_scale is True we use the maximum of the multi-scale
  augmentation scales (same as compute_multi_scale_scales). Otherwise we use model resolution. This ensures the step
  uses the max resolution seen in training.
- Targets: Memory grows with number of targets per image. We use
  auto_batch_max_targets_per_image (config) to synthesize that many targets per image so the probe reflects worst-case
  matcher and loss memory.
- EMA: When use_ema is True, an EMA copy of the model is kept in memory. We
  apply auto_batch_ema_headroom (e.g. 0.7) to the probed batch size so the effective safe batch leaves room for the EMA
  model.
é    )ÚannotationsN)Ú	dataclass)ÚAnyÚcast)ÚModelConfigÚTrainConfig)Úcompute_multi_scale_scales)Úbuild_criterion_from_config)Ú
get_logger)ÚNestedTensorT)Úfrozenc                  ó:   — e Zd ZU dZded<   ded<   ded<   ded<   y)	ÚAutoBatchResulta­  Result of auto-batch probing: safe micro-batch size and recommended grad accumulation.

    Attributes:
        safe_micro_batch: Per-device batch size that fits in memory for one train step.
        recommended_grad_accum_steps: Steps to accumulate to reach target effective batch.
        effective_batch_size: safe_micro_batch * recommended_grad_accum_steps.
        device_name: Human-readable GPU name used for probing.
    ÚintÚsafe_micro_batchÚrecommended_grad_accum_stepsÚeffective_batch_sizeÚstrÚdevice_nameN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Ú__annotations__© ó    úe/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/rfdetr/training/auto_batch.pyr   r   %   s!   … ñð ÓØ"%Ó%ØÓØÔr   r   c                óH   — t        | «      j                  «       }d|v xs d|v S )Nzout of memoryzcuda error: out of memory)r   Úlower)ÚexcÚmessages     r   Ú_is_cuda_oomr"   6   s(   € Ü�#‹h�n‰nÓ€GØ˜gÐ%ÒOÐ)DÈÐ)OÐOr   c           
     ó  — t        j                  | ||||¬«      }t        j                  | ||t         j                  |¬«      }t	        ||«      }	t        d|dz
  «      }
t        d|«      }g }t        | «      D �]‚  }t        j                  g d¢gt         j                  |¬«      j                  |d«      }t        j                  t        d|
«      gt         j                  |¬«      j                  |«      }t        j                  |t         j                  |¬«      }t        j                  |fdt         j                  |¬«      }||t        j                  |t         j                  |¬«      t        j                  ||gt         j                  |¬«      t        j                  ||gt         j                  |¬«      ||dœ}|r+t        j                  |||t         j                  |¬«      |d	<   |j                  |«       �Œ… |	|fS )
a  Build a minimal (samples, targets) batch for probing.

    Uses max_targets_per_image targets per image so memory reflects worst-case matcher and loss. When segmentation_head
    is True, each target dict includes "masks" of shape (max_targets_per_image, resolution, resolution).
    )Údevice)Údtyper$   r   é   )ç      à?r'   çš™™™™™É?r(   é   g{®Gáz¤?)ÚboxesÚlabelsÚimage_idÚ	orig_sizeÚsizeÚiscrowdÚareaÚmasks)ÚtorchÚrandnÚzerosÚboolr   ÚmaxÚrangeÚtensorÚfloat32ÚexpandÚminÚint64ÚfullÚappend)Úmicro_batch_sizeÚ
resolutionr$   Únum_classesÚsegmentation_headÚmax_targets_per_imageÚnum_channelsÚtensorsÚmaskÚsamplesÚ	max_labelÚnÚtargetsÚidxr*   r+   r/   r0   Úts                      r   Ú_make_synthetic_batchrM   ;   s™  € ô �k‰kÐ*¨L¸*ÀjÐY_Ô`€GÜ�;‰;Ð'¨°ZÄuÇzÁzÐZ`Ôa€DÜ˜7 DÓ)€Gä�A�{ Q‘Ó'€IÜˆAÐ$Ó%€AØ-/€GÜÐ%Ó&ó ˆä—‘Ò2Ð3¼5¿=¹=ÐQWÔX×_Ñ_Ð`aÐcdÓeˆÜ—‘œs 1 iÓ0Ð1¼¿¹ÈVÔT×[Ñ[Ð\]Ó^ˆÜ—+‘+˜a¤u§{¡{¸6ÔBˆÜ�z‰z˜1˜$ ¬E¯M©MÀ&ÔIˆàØÜŸ™ S´·±ÀFÔKÜŸ™ z°:Ð&>ÄeÇkÁkÐZ`ÔaÜ—L‘L *¨jÐ!9ÄÇÁÐU[Ô\ØØñ&
ˆñ ÜŸ™ Q¨
°JÄeÇjÁjÐY_Ô`ˆAˆg‰JØ�‰�qÖð#ð$ �GÐÐr   c           	     óŠ  — 	 | j                  d¬«       |j                  d¬«       t        |||||||	¬«      \  }}d|dœ}|
�|
|d<   t        j                  di |¤Ž5   | ||«      }t	        t
        t        t        j                  f    |||«      «      }t	        t
        t        t        f   t        |d«      «      }|D �cg c]  }||v sŒ||   ||   z  ‘Œ }}|st        d	«      ‚t        j                  |«      j                  «       }ddd«       t        j                  «      st        d
«      ‚t        j                  j                  |«       | j                  d¬«       |j                  d¬«       yc c}w # 1 sw Y   ŒrxY w# t        $ r4}t!        |«      r#t        j"                  j%                  «        Y d}~y‚ d}~ww xY w)zKRun one forward + loss + backward; return True if successful, False on OOM.T©Úset_to_none)r?   r@   r$   rA   rB   rC   rD   Úcuda)Údevice_typeÚenabledNr%   Úweight_dictznauto-batch probe could not build weighted losses: no overlap between criterion loss_dict and weight_dict keys.z5auto-batch probe produced a non-finite training loss.Fr   )Ú	zero_gradrM   r2   Úautocastr   Údictr   ÚTensorÚfloatÚgetattrÚRuntimeErrorÚstackÚsumÚisfiniteÚautogradÚbackwardr"   rQ   Úempty_cache)ÚmodelÚ	criterionr?   r@   r$   rA   ÚamprB   rC   rD   Úautocast_dtyperG   rJ   Úautocast_kwargsÚoutputsÚ	loss_dictrT   ÚnameÚweighted_lossesÚlossr    s                        r   Ú_probe_steprl   e   s¯  € ð'Ø�‰ DˆÔ)Ø×Ñ¨ÐÔ-Ü0Ø-Ø!ØØ#Ø/Ø"7Ø%ô
Ñˆ�ð ;AÈSÑ*QˆØÐ%Ø'5ˆO˜GÑ$Ü�^‰^Ñ.˜oÑ.ñ 
	6Ù˜G WÓ-ˆGÜœT¤#¤u§|¡|Ð"3Ñ4±iÀÈÓ6QÓRˆIÜœt¤C¬ JÑ/´¸ÀMÓ1RÓSˆKØOXÖpÀtÐ\`ÐdoÒ\o˜y¨™°¸TÑ1BÓBÐpˆOÐpÙ"Ü"ð(óð ô —;‘;˜Ó/×3Ñ3Ó5ˆD÷
	6ô �~‰~˜dÔ#ÜÐVÓWÐWä�‰×Ñ Ô%Ø�‰ DˆÔ)Ø×Ñ¨ÐÔ-Øùò q÷	
	6ð 
	6ûô& ò Ü˜ÔÜ�J‰J×"Ñ"Ô$ÜØûð	úsP   ‚AF ÁA#E9Â?	E4Ã	E4Ã2E9ÄA+F Å4E9Å9FÅ>F Æ	GÆ)F=Æ<F=Æ=Gc                ó  — |j                   dk7  rt        d«      ‚|	dk  rt        d«      ‚d|cxk  rdk  st        d«      ‚ t        d«      ‚| j                  }|j                  }| j	                  «        |j	                  «        	 d}d}d}||	k  r&t        | |||||||||
|«      r|}|d	z  }n|}n||	k  rŒ&|dk  rt        d
«      ‚|€|	dz   }|dz   }t        |dz
  |	«      }||k  r0||z   d	z  }t        | |||||||||
|«      r|}|dz   }n|dz
  }||k  rŒ0t        dt        j                  ||z  «      «      }|| j	                  |«       |j	                  |«       | j                  d¬«       |j                  d¬«       t        j                  j                  «        S # | j	                  |«       |j	                  |«       | j                  d¬«       |j                  d¬«       t        j                  j                  «        w xY w)am  Find the largest per-device batch size that fits in memory for one train step.

    Uses exponential search (1, 2, 4, ...) up to the first failure, then binary search between the last successful size
    and the first failure to get the exact maximum. The returned value is floor(max_ok * safety_margin), so
    safety_margin in (0, 1] scales down the result for headroom (e.g. 0.9 keeps 10% margin).

    Args:
        model: The model to probe (will be set to train mode).
        criterion: The loss criterion (must match model output and target format).
        resolution: Input spatial size (square).
        device: CUDA device to run on.
        num_classes: Number of classes (for synthetic targets).
        amp: Whether to use autocast for the forward.
        segmentation_head: If True, synthetic targets include "masks" for loss_masks.
        max_targets_per_image: Number of synthetic targets per image (worst-case memory).
        safety_margin: Fraction of max batch to return (0 < safety_margin <= 1).
        max_micro_batch: Cap on batch size to try.
        num_channels: Number of input image channels (for synthetic probe images).

    Returns:
        Safe micro-batch size (>= 1).

    Raises:
        RuntimeError: If device is not CUDA or if micro_batch_size=1 already fails (OOM).
        ValueError: If max_micro_batch < 1 or safety_margin not in (0, 1].
    rQ   z0auto-batch probing currently supports CUDA only.r&   zmax_micro_batch must be >= 1.r   g      ð?z safety_margin must be in (0, 1].Né   zjauto-batch probe failed at micro_batch_size=1. Try lowering resolution or enabling gradient_checkpointing.TrO   )Útyper[   Ú
ValueErrorÚtrainingÚtrainrl   r;   r6   ÚmathÚfloorrU   r2   rQ   ra   )rb   rc   r@   r$   rA   rd   rB   rC   Úsafety_marginÚmax_micro_batchrD   re   Úmodel_trainingÚcriterion_trainingÚlower_okÚ	candidateÚ
upper_failÚloÚhiÚmidr   s                        r   Úprobe_max_micro_batchr   �   sE  € ðP ‡{�{�fÒÜÐMÓNÐNØ˜ÒÜÐ8Ó9Ð9Ø�Ô$ Ò$ÜÐ;Ó<Ð<ð %ÜÐ;Ó<Ð<à—^‘^€NØ"×+Ñ+ÐØ	‡K�K„MØ‡O�OÔð@!ØˆØˆ	Øˆ
à˜?Ò*ÜØØØØØØØØ!Ø%ØØôð %�Ø˜Q‘‘	à&�
Øð% ˜?Ó*ð( �aŠ<ÜðNóð ð
 ÐØ(¨1Ñ,ˆJà˜‰\ˆÜ�˜a‘ Ó1ˆØ�BŠhØ˜‘7˜q‘.ˆCÜØØØØØØØØ!Ø%ØØôð �Ø˜1‘W‘à˜1‘W�ð% �B‹hô* ˜q¤$§*¡*¨X¸Ñ-EÓ"FÓGÐØà�‰�NÔ#Ø�‰Ð*Ô+Ø�‰ DˆÔ)Ø×Ñ¨ÐÔ-Ü�
‰
×ÑÕ øð	 	�‰�NÔ#Ø�‰Ð*Ô+Ø�‰ DˆÔ)Ø×Ñ¨ÐÔ-Ü�
‰
×ÑÕ ús   Â0F Â7AF Ä#F ÆA&Hc                ó†   — | dk  rt        d«      ‚|dk  rt        d«      ‚t        dt        j                  || z  «      «      S )a‚  Recommend gradient accumulation steps to reach target effective batch size.

    Args:
        safe_micro_batch: Per-step batch size that fits in memory.
        target_effective_batch: Desired effective batch (micro_batch * accum_steps).

    Returns:
        ceil(target_effective_batch / safe_micro_batch), at least 1.

    Raises:
        ValueError: If either argument is < 1.
    r&   zsafe_micro_batch must be >= 1.z$target_effective_batch must be >= 1.)rp   r6   rs   Úceil)r   Útarget_effective_batchs     r   Úrecommend_grad_accum_stepsrƒ     sI   € ð ˜!ÒÜÐ9Ó:Ð:Ø Ò!ÜÐ?Ó@Ð@Üˆq”$—)‘)Ð2Ð5EÑEÓFÓGÐGr   c                ód  — | j                   }t        j                  j                  «       r|j                  dk7  rt        d«      ‚t        |dd«      }t        |dd«      }|r[|sYt        |dd«      }t        |dd	«      }	t        |d
d«      }
t        |j                  ||	|
«      }|rt        |«      n|j                  }n|j                  }t        |dd«      }t        ||«      \  }}|j                  |«      }t        |j                  «      }t        |dd«      }|rU|dk(  rt        j                  }nAt        j                  j                  «       rt        j                   nt        j                  }nd}t#        | j$                  ||||j&                  ||j(                  |||t        |dd«      |¬«      }t        |dd«      }|rFt        |dd«      }t        dt+        j,                  ||z  «      «      }t.        j1                  d||«       t        |dd«      }t        |dd«      }t3        |t4        «      r t3        |t4        «      rt        d||z  «      }nd}|j6                  }|dkD  r#t        dt+        j8                  ||z  «      «      }n|}t;        ||«      }||z  }||z  }t        j                  j=                  |«      }t.        j1                  d|||j(                  ||«       t.        j1                  d||||«       t.        j1                  d«       t.        j1                  d«       t?        ||||¬ «      S )!a¤  Resolve batch_size='auto' into concrete batch_size and grad_accum_steps using a probe.

    Expects model_context to have attributes: .device (torch.device) and .model (nn.Module). Runs probe_max_micro_batch
    on the current model/criterion, then recommend_grad_accum_steps using train_config.auto_batch_target_effective. Logs
    device, segmentation flag, resolution, and the chosen values; also logs that the probe is train-step-only and that
    eval/test may use more memory.

    Args:
        model_context: Object with .device and .model (e.g. RFDETR.model from get_model()).
        model_config: Architecture config (resolution, num_classes, amp, segmentation_head).
        train_config: Training config (auto_batch_target_effective); batch_size should be "auto".
        safety_margin: Fraction of max batch to use (passed to probe_max_micro_batch).
        max_micro_batch: Upper bound on batch size to try (passed to probe_max_micro_batch).

    Returns:
        AutoBatchResult with safe_micro_batch, recommended_grad_accum_steps, effective_batch_size, and device_name.

    Raises:
        RuntimeError: If CUDA is not available or model_context.device is not CUDA.
    rQ   z;batch_size='auto' requires a CUDA device for probing in v1.Úmulti_scaleFÚdo_random_resize_via_paddingÚexpanded_scalesTÚ
patch_sizeé   Únum_windowsr)   Ú auto_batch_max_targets_per_imageéd   Ú	amp_dtypeÚautoÚfp16NrD   é   )rb   rc   r@   r$   rA   rd   rB   rC   ru   rv   rD   re   Úuse_emaÚauto_batch_ema_headroomgffffffæ?r&   z=[auto-batch] Applied EMA headroom (%.2f): safe_micro_batch=%sÚdevicesÚ	num_nodesza[auto-batch] device=%s world_size=%s segmentation=%s probe_resolution=%s max_targets_per_image=%szl[auto-batch] safe_micro_batch=%s grad_accum_steps=%s effective_batch_per_device=%s global_effective_batch=%szC[auto-batch] This probe estimates train-step-safe micro-batch only.zY[auto-batch] Validation/test (especially segmentation mask eval) may require more memory.)r   r   r   r   ) r$   r2   rQ   Úis_availablero   r[   rZ   r	   r@   r6   r
   Útor5   rd   Úfloat16Úis_bf16_supportedÚbfloat16r   rb   rA   rB   rs   rt   ÚloggerÚinfoÚ
isinstancer   Úauto_batch_target_effectiver�   rƒ   Úget_device_namer   )Úmodel_contextÚmodel_configÚtrain_configru   rv   r$   r…   Údo_random_resizer‡   rˆ   rŠ   ÚscalesÚprobe_resolutionrC   rc   Ú_Úamp_enabledÚamp_dtype_strÚprobe_autocast_dtyper   r‘   Úheadroomr“   r”   Ú
world_sizeÚtarget_effective_globalÚtarget_effective_per_deviceÚgrad_accum_stepsÚeffective_batch_size_per_deviceÚglobal_effective_batch_sizer   s                                  r   Úresolve_auto_batch_configr°   (  s  € ð6 ×!Ñ!€FÜ�:‰:×"Ñ"Ô$¨¯©°vÒ(=ÜÐXÓYÐYô ˜,¨°uÓ=€KÜ˜|Ð-KÈUÓSÐÙÑ+Ü! ,Ð0AÀ4ÓHˆÜ˜\¨<¸Ó<ˆ
Ü˜l¨M¸1Ó=ˆÜ+Ø×#Ñ#ØØØó	
ˆñ +1œ3˜vœ;°l×6MÑ6MÑà'×2Ñ2Ðä# LÐ2TÐVYÓZÐä.¨|¸\ÓJ�L€IˆqØ—‘˜VÓ$€Iä�|×'Ñ'Ó(€KÜ˜L¨+°vÓ>€MÙØ˜FÒ"Ü7<·}±}Ñ ô 6;·Z±Z×5QÑ5QÔ5S¤5§>¢>ÔY^×YfÑYfÑ à#Ðä,Ø×!Ñ!ØØ#ØØ ×,Ñ,ØØ&×8Ñ8Ø3Ø#Ø'Ü˜\¨>¸1Ó=Ø+ôÐô �l I¨uÓ5€GÙÜ˜<Ð)BÀCÓHˆÜ˜q¤$§*¡*Ð-=ÀÑ-HÓ"IÓJÐÜ�‰ÐSÐU]Ð_oÔpô �l I¨tÓ4€GÜ˜ k°1Ó5€IÜ�'œ3Ô¤J¨y¼#Ô$>Ü˜˜G iÑ/Ó0‰
àˆ
ð +×FÑFÐØ�A‚~Ü&)¨!¬T¯Y©YÐ7NÐQ[Ñ7[Ó-\Ó&]Ñ#à&=Ð#ä1Ð2BÐD_Ó`ÐØ&6Ð9IÑ&IÐ#Ø"AÀJÑ"NÐÜ—*‘*×,Ñ,¨VÓ4€Kä
‡K�KØkØØØ×&Ñ&ØØôô ‡K�KØvØØØ'Ø#ôô ‡K�KÐUÔVÜ
‡K�KÐkÔläØ)Ø%5Ø<Øô	ð r   )r    ÚBaseExceptionÚreturnr5   )Fr&   r�   )r?   r   r@   r   r$   útorch.devicerA   r   rB   r5   rC   r   rD   r   r²   z2tuple[NestedTensor, list[dict[str, torch.Tensor]]])Fr&   r�   N)rb   útorch.nn.Modulerc   r´   r?   r   r@   r   r$   r³   rA   r   rd   r5   rB   r5   rC   r   rD   r   re   útorch.dtype | Noner²   r5   )Fr&   çÍÌÌÌÌÌì?é€   r�   N)rb   r´   rc   r´   r@   r   r$   r³   rA   r   rd   r5   rB   r5   rC   r   ru   rY   rv   r   rD   r   re   rµ   r²   r   )r   r   r‚   r   r²   r   )r¶   r·   )rŸ   r   r    r   r¡   r   ru   rY   rv   r   r²   r   )r   Ú
__future__r   rs   Údataclassesr   Útypingr   r   r2   Úrfdetr.configr   r   Úrfdetr.datasets.cocor	   Úrfdetr.modelsr
   Úrfdetr.utilities.loggerr   Úrfdetr.utilities.tensorsr   rš   r   r"   rM   rl   r   rƒ   r°   r   r   r   ú<module>rÀ      s2  ðñõ #ã Ý !ß ã ç 2Ý ;Ý 5Ý .Ý 1á	‹€ñ �$Ô÷ð ó ðó Pð $Ø!"Øð'Øð'àð'ð ð'ð ð	'ð
 ð'ð ð'ð ð'ð 8ó'ðd $Ø!"ØØ)-ð5Øð5àð5ð ð5ð ð	5ð
 ð5ð ð5ð 
ð5ð ð5ð ð5ð ð5ð 'ð5ð 
ó5ð~ $Ø!"ØØØØ)-ðt!Øðt!àðt!ð ðt!ð ð	t!ð
 ðt!ð 
ðt!ð ðt!ð ðt!ð ðt!ð ðt!ð ðt!ð 'ðt!ð 	ót!ónHð0 Øð@Øð@àð@ð ð@ð ð	@ð
 ð@ð ô@r   