code: def _train(args, config):
      global _save_parameter_info
      comm = current_communicator()
      _CGLOAD_LOG_INTERVAL = 20
  
      best_epoch = None
      best_error = None
      last_epoch = 0
      if args.resume:
          last_epoch, best_epoch, best_error = _get_current_parameter(
              args, config
          )
          if best_epoch is not None:
              logger.log(
                  99,
                  "Best error {} recorded at epoch {} in previous training.".format(
                      best_error, best_epoch
                  ),
              )
              if best_epoch > last_epoch:
                  logger.log(
                      99,
                      "Resumed epoch is {} but this training keep this result.".format(
                          last_epoch
                      ),
                  )
          logger.log(99, "Resume from epoch {}".format(last_epoch + 1))
  
      callback.update_status(
          ("epoch.max", config.training_config.max_epoch)
      )
      callback.update_status(
          (
              "epoch.current",
              last_epoch + 1
              if last_epoch < config.training_config.max_epoch
              else config.training_config.max_epoch,
          )
      )
  
      max_iteration = (
          config.training_config.max_epoch
          * config.training_config.iter_per_epoch
      )
      if single_or_rankzero():
          logger.log(
              99,
              "Training epoch {} of {} begin".format(
                  last_epoch + 1, config.training_config.max_epoch
              ),
          )
  
      class Cost:
          pass
  
      cost = Cost()
      cost.sum_epoch = 0.0
      cost.num_iteration = 0
      cost.sum_iteration = 0.0
      cost.variables = None
  
      class TimeInfo:
          pass
  
      timeinfo = TimeInfo()
      timeinfo.past_time = 0
      timeinfo.estimate_time = 0
      timeinfo.last_past_time = None
  
      ctx = config.global_config.default_context
  
      if args.enable_ooc:
          logger.log(99, "OOC enabled.")
          logger.log(
              99, f"    OOC GPU memory size {args.ooc_gpu_memory_size}."
          )
          logger.log(
              99, f"    OOC Window length   {args.ooc_window_length}."
          )
      scheduler = lms_scheduler(
          ctx,
          use_lms=args.enable_ooc,
          gpu_memory_size=args.ooc_gpu_memory_size,
          window_length=args.ooc_window_length,
      )
      val_scheduler = lms_scheduler(
          ctx,
          use_lms=args.enable_ooc,
          gpu_memory_size=args.ooc_gpu_memory_size,
          window_length=args.ooc_window_length,
      )
  
      if max_iteration > 0:
          last_iteration = (
              last_epoch * config.training_config.iter_per_epoch
          )
          if last_iteration < max_iteration:
              timeinfo.start_time = time.time()
              timeinfo.last_epoch_start_time = timeinfo.start_time
  
              callback.update_status(
                  "processing", True, timeinfo.start_time
              )
  
              for iteration in range(last_iteration, max_iteration):
                  # instant load measurement
                  measure_cpu_gpu_instant_load()
  
                  cost = _update(iteration, config, cost, scheduler)
  
                  if np.isnan(cost.sum_epoch) or np.isinf(
                      cost.sum_epoch
                  ):
                      logger.log(99, "Cost is Nan")
                      return False, False
  
                  timeinfo = _calc_estimate_time(
                      timeinfo,
                      max_iteration,
                      last_iteration,
                      iteration + 1,
                  )
                  callback.update_time_train(
                      prediction=timeinfo.estimate_time
                  )
  
                  if 0 < config.timelimit < timeinfo.estimate_time:
                      logger.log(
                          99,
                          "Expected training time ({:.3f}s) will exceed time limit ({}s).".format(
                              timeinfo.estimate_time, config.timelimit
                          ),
                      )
                      return False, False
  
                  if (
                      iteration + 1
                  ) % config.training_config.iter_per_epoch == 0:
                      last_past_time = -1
                      # End of epoch
                      epoch = (
                          iteration
                          // config.training_config.iter_per_epoch
                          + 1
                      )
                      cost_avg_epoch = (
                          cost.sum_epoch / cost.num_iteration
                          if cost.num_iteration
                          else 0
                      )
                      cost.sum_epoch = 0.0
                      cost.num_iteration = 0
                      monitoring_report = []
  
                      # Evaluation
                      error_str = ""
                      if (
                          epoch
                          % config.training_config.monitor_interval
                          == 0
                          or epoch <= 5
                      ):
                          best_error, error_str = _evaluate(
                              args,
                              config,
                              monitoring_report,
                              best_error,
                              epoch,
                              val_scheduler,
                          )
  
                      # Cpu/Gpu average load
                      cg_load_str = ""
                      cgload_log = ""
                      cg_load = get_cpu_gpu_average_load()
                      if cg_load:
                          cg_load_str = (
                              "epoch {} average_load_matrix: {}".format(
                                  epoch, cg_load
                              )
                          )
                          span = _calc_epoch_span(timeinfo)
                          if span > _CGLOAD_LOG_INTERVAL:
                              cgload_log = _format_cgload_log(cg_load)
  
                      if single_or_rankzero():
                          # Write to monitoring_report.yml
                          f = open(
                              os.path.join(
                                  args.outdir, "monitoring_report.yml"
                              ),
                              "a",
                          )
                          f.write("{}:\n".format(epoch - 1))
                          f.write("  cost: {}\n".format(cost_avg_epoch))
                          for s in monitoring_report:
                              f.write(s)
                          f.close()
  
                          callback.update_status(
                              (
                                  ["monitoring_report", epoch, "cost"],
                                  cost_avg_epoch,
                              )
                          )
  
                          _save_parameters(
                              args, "current", epoch, config
                          )
  
                          callback.update_status(
                              ("epoch.current", epoch)
                          )
                          callback.update_status()
  
                          logger.log(
                              99,
                              "epoch {} of {} cost={:.6f} {} time=({:.1f}s /{:.1f}s) {}".format(
                                  epoch,
                                  config.training_config.max_epoch,
                                  cost_avg_epoch,
                                  error_str,
                                  timeinfo.past_time,
                                  timeinfo.estimate_time,
                                  cgload_log,
                              ),
                          )
  
                          if cg_load_str:
                              # cpu_gpu_average_load record at epoch level
                              callback.update_status(
                                  (
                                      ["cpu_gpu_epoch_load", epoch],
                                      cg_load,
                                  )
                              )
                              progress(cg_load_str, 1)
  
                          if not callback.check_training_time(
                              args, config, timeinfo, epoch, last_epoch
                          ):
                              _save_parameters(
                                  args, "current", epoch, config, True
                              )
                              return False, True
  
              if single_or_rankzero():
                  _save_parameters(args, "current", epoch, config, True)
      return True, False
  
imports: import glob
  import os
  import time
  import zipfile
  from collections import OrderedDict
  import nnabla
  import nnabla.utils.callback
  import nnabla.utils.load
  import numpy
  from contextlib2 import ExitStack
  from nnabla import available_contexts
  from nnabla.config import nnabla_config
  from nnabla.logger import logger
  from nnabla.parameter import save_parameters
  from nnabla.utils.cli.utility import NodeTimeInfoCollector
  from nnabla.utils.cli.utility import get_cpu_gpu_average_load
  from nnabla.utils.cli.utility import let_data_to_variable
  from nnabla.utils.cli.utility import lms_scheduler
  from nnabla.utils.cli.utility import load_train_state
  from nnabla.utils.cli.utility import measure_cpu_gpu_instant_load
  from nnabla.utils.cli.utility import save_optimizer_states
  from nnabla.utils.cli.utility import str_to_num
  from nnabla.utils.communicator_util import current_communicator, single_or_rankzero
  from nnabla.utils.nnp_format import nnp_version
  from nnabla.utils.progress import configure_progress, progress
  from six.moves import range
label_desc: Use image node_id 9 for calling a global function with example usage: _train(args, config) and returns: True,  False, False,  False, False,  False, False,  True