class_docstr: A runner class to train and evaluate a model given a task and datasets.
  
  The runner uses pytorch distributed data parallel by default. Future release
  will support other distributed frameworks.
class_docstr_tok: ["A","runner","class","to","train","and","evaluate","a","model","given","a","task","and","datasets",".","The","runner","uses","pytorch","distributed","data","parallel","by","default",".","Future","release","will","support","other","distributed","frameworks","."]
docstr: Evaluate the model on a given split.
  
  Args:
      split_name (str): name of the split to evaluate on.
      cur_epoch (int): current epoch.
      skip_reload_best (bool): whether to skip reloading the best checkpoint.
          During training, we will reload the best checkpoint for validation.
          During testing, we will use provided weights and skip reloading the best checkpoint .
code: def eval_epoch(self, split_name, cur_epoch, skip_reload=False):
      """
      Evaluate the model on a given split.
  
      Args:
          split_name (str): name of the split to evaluate on.
          cur_epoch (int): current epoch.
          skip_reload_best (bool): whether to skip reloading the best checkpoint.
              During training, we will reload the best checkpoint for validation.
              During testing, we will use provided weights and skip reloading the best checkpoint .
      """
      data_loader = self.dataloaders.get(split_name, None)
      assert data_loader, "data_loader for split {} is None.".format(
          split_name
      )
  
      # TODO In validation, you need to compute loss as well as metrics
      # TODO consider moving to model.before_evaluation()
      model = self.unwrap_dist_model(self.model)
      if not skip_reload and cur_epoch == "best":
          model = self._reload_best_model(model)
      model.eval()
  
      self.task.before_evaluation(
          model=model,
          dataset=self.datasets[split_name],
      )
      results = self.task.evaluation(model, data_loader)
  
      if results is not None:
          return self.task.after_evaluation(
              val_result=results,
              split_name=split_name,
              epoch=cur_epoch,
          )
  
imports: import datetime
  import json
  import logging
  import os
  import time
  from pathlib import Path
  import torch
  import torch.distributed
  import webdataset
  from lavis.common.dist_utils import download_cached_file, get_rank, get_world_size, is_main_process, main_process
  from lavis.common.registry import registry
  from lavis.common.utils import is_url
  from lavis.datasets.data_utils import concat_datasets, reorg_datasets_by_split
  from lavis.datasets.datasets.dataloader_utils import IterLoader, MultiIterLoader, PrefetchLoader
  from torch.nn.parallel import DistributedDataParallel
  from torch.utils.data import DataLoader, DistributedSampler
  from torch.utils.data.dataset import ChainDataset
label_desc: Use image node_id 29 for calling the RunnerBase obj's underlying member method code with example usage: obj.eval_epoch(split_name, cur_epoch, skip_reload) and returns: self