class_docstr: TrainLoop contains the core training loop logic.
class_docstr_tok: ["TrainLoop","contains","the","core","training","loop","logic","."]
docstr: Save the model to disk, possibly with a suffix.
docstr_tok: ["Save","the","model","to","disk",",","possibly","with","a","suffix","."]
code: def save_model(self, suffix=None):
      """
      Save the model to disk, possibly with a suffix.
      """
      if not self.opt.get("model_file"):
          # nothing to save to, just exit
          return
  
      fn = self.opt["model_file"]
      if suffix:
          fn += suffix
  
      if not is_primary_worker():
          # never do IO as a non-primary worker
          if hasattr(self.agent, "save_nonprimary"):
              self.agent.save_nonprimary(fn)
          return
  
      while True:
          # don't ever let a ctrl-c interrupt saving
          try:
              self.agent.save(fn)
              self._save_train_stats(suffix)
              if self.opt["wandb_log"] and self.opt["wandb_log_model"]:
                  self.wb_logger.log_model(fn)
              break
          except KeyboardInterrupt:
              pass
  
imports: import copy
  import random
  import torch
  import json
  import os
  import signal
  from typing import Tuple
  import numpy
  import parlai.utils.logging
  from parlai.core.agents import create_agent, create_agent_from_shared
  from parlai.core.exceptions import StopTrainException
  from parlai.core.logs import TensorboardLogger, WandbLogger, ClearMLLogger
  from parlai.core.metrics import Metric
  from parlai.core.metrics import aggregate_named_reports, aggregate_unnamed_reports, dict_report
  from parlai.core.opt import Opt
  from parlai.core.params import ParlaiParser, print_announcements
  from parlai.core.script import ParlaiScript, register_script
  from parlai.core.worlds import create_task, World
  from parlai.scripts.build_dict import build_dict, setup_args
  from parlai.scripts.eval_model import get_task_world_logs
  from parlai.utils.distributed import sync_object, is_primary_worker, all_gather_list, is_distributed, get_rank, num_workers
  from parlai.utils.io import PathManager
  from parlai.utils.misc import Timer, nice_report
  from parlai.utils.world_logging import WorldLogger
label_desc: Use image node_id 2 for calling the TrainLoop obj's underlying member method code with example usage: obj.save_model(suffix) without return types