code: def evaluate(
      eval_unit: TEvalUnit,
      eval_dataloader: Iterable[TEvalData],
      *,
      max_steps_per_epoch: Optional[int] = None,
      callbacks: Optional[List[Callback]] = None,
      timer: Optional[TimerProtocol] = None,
  ) -> None:
      """
      The ``evaluate`` entry point takes in a :class:`~torchtnt.framework.unit.EvalUnit` object, a train dataloader (any Iterable), optional arguments to modify loop execution,
      and runs the evaluation loop.
  
      Args:
          eval_unit: an instance of :class:`~torchtnt.framework.unit.EvalUnit` which implements `eval_step`.
          eval_dataloader: dataloader to be used during evaluation, which can be *any* iterable, including PyTorch DataLoader, DataLoader2, etc.
          max_steps_per_epoch: the max number of steps to run per epoch. None means evaluate until the dataloader is exhausted.
          callbacks: an optional list of :class:`~torchtnt.framework.callback.Callback` s.
          timer: an optional Timer which will be used to time key events (using a Timer with CUDA synchronization may degrade performance).
  
  
      Below is an example of calling :py:func:`~torchtnt.framework.evaluate`.
  
      .. code-block:: python
  
          from torchtnt.framework.evaluate import evaluate
  
          eval_unit = MyEvalUnit(module=..., optimizer=..., lr_scheduler=...)
          eval_dataloader = torch.utils.data.DataLoader(...)
          evaluate(eval_unit, eval_dataloader, max_steps_per_epoch=20)
  
      Below is pseudocode of what the :py:func:`~torchtnt.framework.evaluate` entry point does.
  
      .. code-block:: text
  
          set unit's tracked modules to eval mode
          call on_eval_start on unit first and then callbacks
          while not done:
              call on_eval_epoch_start on unit first and then callbacks
              try:
                  call get_next_eval_batch on unit
                  call on_eval_step_start on callbacks
                  call eval_step on unit
                  increment step counter
                  call on_eval_step_end on callbacks
              except StopIteration:
                  break
          increment epoch counter
          call on_eval_epoch_end on unit first and then callbacks
          call on_eval_end on unit first and then callbacks
      """
      _log_api_usage("evaluate")
      callback_handler = CallbackHandler(callbacks or [])
      state = State(
          entry_point=EntryPoint.EVALUATE,
          eval_state=PhaseState(
              dataloader=eval_dataloader,
              max_steps_per_epoch=max_steps_per_epoch,
          ),
          timer=timer,
      )
      try:
          _evaluate_impl(state, eval_unit, callback_handler)
          logger.info("Finished evaluation")
          if state.timer:
              logger.info(get_timer_summary(state.timer))
      except Exception as e:
          # TODO: log for diagnostics
          logger.info(e)
          eval_unit.on_exception(state, e)
          callback_handler.on_exception(state, eval_unit, e)
          raise e
  
file_path: tnt/torchtnt/framework/evaluate.py
imports: import logging
  from typing import Iterable, List, Optional
  import torch
  from pyre_extensions import none_throws
  from torchtnt.framework._callback_handler import CallbackHandler
  from torchtnt.framework._loop_utils import _is_epoch_done, _log_api_usage, _reset_module_training_mode, _set_module_training_mode
  from torchtnt.framework.callback import Callback
  from torchtnt.framework.state import ActivePhase, EntryPoint, PhaseState, State
  from torchtnt.framework.unit import TEvalData, TEvalUnit
  from torchtnt.framework.utils import get_timing_context
  from torchtnt.utils.timer import get_timer_summary, TimerProtocol
label_desc: Use image node_id 1 for calling a global function with example usage: evaluate(eval_unit, eval_dataloader) without return types