code: def train_fabric_ddp(fabric):
      make_deterministic()
      memory_stats = {}
  
      model = ConvNet()
      initial_state_dict = deepcopy(model.state_dict())
  
      optimizer = model.get_optimizer()
      model, optimizer = fabric.setup(model, optimizer)
  
      dataloader = model.get_dataloader()
      dataloader = fabric.setup_dataloaders(dataloader)
      loss_fn = model.get_loss_function()
  
      memory_stats["start"] = torch.cuda.memory_stats()
  
      model.train()
      iteration_timings = []
      iterator = iter(dataloader)
      for _ in range(model.num_steps):
          t0 = time.perf_counter()
  
          inputs, labels = next(iterator)
          optimizer.zero_grad()
          outputs = model(inputs)
          loss = loss_fn(outputs, labels)
          fabric.backward(loss)
          optimizer.step()
  
          t1 = time.perf_counter()
          iteration_timings.append(t1 - t0)
  
      memory_stats["end"] = torch.cuda.memory_stats()
  
      # check that the model has changed
      assert not is_state_dict_equal(
          initial_state_dict, model.state_dict()
      )
  
      return (
          model.state_dict(),
          torch.tensor(iteration_timings),
          memory_stats,
      )
  
file_path: pytorch-lightning/tests/parity_fabric/test_parity_ddp.py
imports: import os
  import time
  from copy import deepcopy
  import torch
  import torch.distributed
  import torch.nn.functional
  from lightning.fabric.fabric import Fabric
  from torch.nn.parallel.distributed import DistributedDataParallel
  from torch.utils.data import DataLoader
  from torch.utils.data.distributed import DistributedSampler
  from parity_fabric.models import ConvNet
  from parity_fabric.utils import cuda_reset, is_cuda_memory_close, is_state_dict_equal, is_timing_close, make_deterministic
label_desc: Use image node_id 2 for calling a global function with example usage: train_fabric_ddp(fabric) and returns: model,  torch,  memory_stats