code: def _evaluate_impl(
      state: State,
      eval_unit: TEvalUnit,
      callback_handler: CallbackHandler,
  ) -> None:
      # input validation
      eval_state = none_throws(state.eval_state)
  
      state._active_phase = ActivePhase.EVALUATE
      logger.info(
          f"Started evaluate with max_steps_per_epoch={eval_state.max_steps_per_epoch}"
      )
  
      # Set all modules to eval mode
      # access modules made available through AppStateMixin
      tracked_modules = eval_unit.tracked_modules()
      prior_module_train_states = _set_module_training_mode(
          tracked_modules, False
      )
  
      eval_unit.on_eval_start(state)
      callback_handler.on_eval_start(state, eval_unit)
  
      # Conditionally run this to avoid running this multiple times
      # in the case of resuming from a checkpoint mid-epoch
      if eval_unit.eval_progress.num_steps_completed_in_epoch == 0:
          eval_unit.on_eval_epoch_start(state)
          callback_handler.on_eval_epoch_start(state, eval_unit)
  
      with get_timing_context(state, "evaluate.iter(dataloader)"):
          data_iter = iter(eval_state.dataloader)
      step_input = data_iter
  
      prev_steps_in_epoch = (
          eval_unit.eval_progress.num_steps_completed_in_epoch
      )
  
      while not (
          state.should_stop
          or _is_epoch_done(
              eval_unit.eval_progress,
              eval_state.max_steps_per_epoch,
              eval_state.max_steps,
          )
      ):
          try:
              with get_timing_context(
                  state, "evaluate.next(data_iter)"
              ), eval_state.iteration_timer.time("data_wait_time"):
                  step_input = eval_unit.get_next_eval_batch(
                      state, data_iter
                  )
                  callback_handler.on_eval_get_next_batch_end(
                      state, eval_unit
                  )
  
              with eval_state.iteration_timer.time(
                  "eval_iteration_time"
              ):
                  callback_handler.on_eval_step_start(state, eval_unit)
                  eval_state._step_output = eval_unit.eval_step(
                      state, step_input
                  )
  
                  eval_unit.eval_progress.increment_step()
                  callback_handler.on_eval_step_end(state, eval_unit)
  
                  # clear step_output to avoid retaining extra memory
                  eval_state._step_output = None
          except StopIteration:
              break
  
      # Possibly warn about an empty dataloader
      any_steps_completed = (
          abs(
              eval_unit.eval_progress.num_steps_completed_in_epoch
              - prev_steps_in_epoch
          )
          > 0
      )
      if not any_steps_completed:
          logger.warning("No steps completed during evaluate epoch!")
  
      # set progress counters for the next epoch
      eval_unit.eval_progress.increment_epoch()
  
      eval_unit.on_eval_epoch_end(state)
      callback_handler.on_eval_epoch_end(state, eval_unit)
  
      eval_unit.on_eval_end(state)
      callback_handler.on_eval_end(state, eval_unit)
  
      # Reset training mode for modules at the end of the epoch
      # This ensures that side-effects made by the loop are reset before
      # returning back to the user
      _reset_module_training_mode(
          tracked_modules, prior_module_train_states
      )
  
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 2 for calling a global function with example usage: _evaluate_impl(state, eval_unit, callback_handler) without return types