code: def training(local_rank, config):
      rank = idist.get_rank()
      manual_seed(config["seed"] + rank)
      device = idist.device()
  
      logger = setup_logger(
          name="IMDB-Training", distributed_rank=local_rank
      )
  
      log_basic_info(logger, config)
  
      output_path = config["output_dir"]
      if rank == 0:
          now = datetime.now().strftime("%Y%m%d-%H%M%S")
          folder_name = f"{config['model']}_backend-{idist.backend()}-{idist.get_world_size()}_{now}"
          output_path = Path(output_path) / folder_name
          if not output_path.exists():
              output_path.mkdir(parents=True)
          config["output_dir"] = output_path.as_posix()
          logger.info(f"Output path: {config['output_dir']}")
  
          if "cuda" in device.type:
              config["cuda device name"] = torch.cuda.get_device_name(
                  local_rank
              )
  
          if config["with_clearml"]:
              from clearml import Task
  
              task = Task.init(
                  "IMDB-Training", task_name=output_path.stem
              )
              task.connect_configuration(config)
              # Log hyper parameters
              hyper_params = [
                  "model",
                  "dropout",
                  "n_fc",
                  "batch_size",
                  "max_length",
                  "weight_decay",
                  "num_epochs",
                  "learning_rate",
                  "num_warmup_epochs",
              ]
              task.connect({k: config[k] for k in hyper_params})
  
      # Setup dataflow, model, optimizer, criterion
      train_loader, test_loader = get_dataflow(config)
  
      config["num_iters_per_epoch"] = len(train_loader)
      model, optimizer, criterion, lr_scheduler = initialize(config)
  
      # Create trainer for current task
      trainer = create_trainer(
          model,
          optimizer,
          criterion,
          lr_scheduler,
          train_loader.sampler,
          config,
          logger,
      )
  
      # Let's now setup evaluator engine to perform model's validation and compute metrics
      metrics = {
          "Accuracy": Accuracy(
              output_transform=utils.thresholded_output_transform
          ),
          "Loss": Loss(criterion),
      }
  
      # We define two evaluators as they wont have exactly similar roles:
      # - `evaluator` will save the best model based on validation score
      evaluator = create_evaluator(model, metrics, config, tag="val")
      train_evaluator = create_evaluator(
          model, metrics, config, tag="train"
      )
  
      def run_validation(engine):
          epoch = trainer.state.epoch
          state = train_evaluator.run(train_loader)
          log_metrics(
              logger,
              epoch,
              state.times["COMPLETED"],
              "Train",
              state.metrics,
          )
          state = evaluator.run(test_loader)
          log_metrics(
              logger,
              epoch,
              state.times["COMPLETED"],
              "Test",
              state.metrics,
          )
  
      trainer.add_event_handler(
          Events.EPOCH_COMPLETED(every=config["validate_every"])
          | Events.COMPLETED
          | Events.STARTED,
          run_validation,
      )
  
      if rank == 0:
          # Setup TensorBoard logging on trainer and evaluators. Logged values are:
          #  - Training metrics, e.g. running average loss values
          #  - Learning rate
          #  - Evaluation train/test metrics
          evaluators = {"training": train_evaluator, "test": evaluator}
          tb_logger = common.setup_tb_logging(
              output_path,
              trainer,
              optimizer,
              evaluators=evaluators,
              log_every_iters=config["log_every_iters"],
          )
  
      # Store 2 best models by validation accuracy starting from num_epochs / 2:
      best_model_handler = Checkpoint(
          {"model": model},
          utils.get_save_handler(config),
          filename_prefix="best",
          n_saved=2,
          global_step_transform=global_step_from_engine(trainer),
          score_name="test_accuracy",
          score_function=Checkpoint.get_default_score_fn("Accuracy"),
      )
      evaluator.add_event_handler(
          Events.COMPLETED(
              lambda *_: trainer.state.epoch > config["num_epochs"] // 2
          ),
          best_model_handler,
      )
  
      try:
          trainer.run(train_loader, max_epochs=config["num_epochs"])
      except Exception as e:
          logger.exception("")
          raise e
  
      if rank == 0:
          tb_logger.close()
  
imports: import os
  from datetime import datetime
  from pathlib import Path
  import fire
  import torch
  import torch.nn
  import torch.optim
  import utils
  from torch.cuda.amp import autocast, GradScaler
  import ignite
  import ignite.distributed
  from ignite.contrib.engines import common
  from ignite.contrib.handlers import PiecewiseLinear
  from ignite.engine import Engine, Events
  from ignite.handlers import Checkpoint, global_step_from_engine
  from ignite.metrics import Accuracy, Loss
  from ignite.utils import manual_seed, setup_logger
label_desc: Use image node_id 1 for calling a global function with example usage: training(local_rank, config) without return types