
    ^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(    #hnn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{Gz?)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    kk*L*jY_`G;;'ZuzzZ`aD7D)GA{Q'IA$%A-/G%& 235==QWX__`acdes1i01VT[[\]^++au{{6Bzz1$EMM&ISFKz:&>ekkZ`aLL*j!9U[\&
 Q
JejjY_`AgJ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%'5OG$^^.o. 
	6GW-GT#u||"34i6QRItCJ/M1RSKOXpt\`do\oyT1BBpOp""(  ;;/335D
	6 ~~d#VWW%D)- q	
	6 
	6&  JJ""$	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"++	KKMOO@!	
?*!% %Q	&
% ?*( a<N 
 (1,J\a1Bh7q.C!% 1W1W% Bh* 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$))25E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_imaged   	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|-KUS+!,0A4H\<<
lM1=+##	
 +13v;l6M6M'22#L2TVYZ.|\JLIqV$I|''(KL+v>MF"7<}}  6;ZZ5Q5Q5S5>>Y^YfYf #,!!# ,,&883#'\>1=+ lIu5G<)BCHq$**-=-H"IJSU]_op lIt4Gk15I'3Jy#$>Gi/0

 +FFA~&)!TYY7NQ[7[-\&]#&=#12BD_`&69I&I#"AJ"N**,,V4K
KKk&& KKv'# KKUV
KK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   