code: def run(
      proc_id, n_gpus, n_cpus, args, devices, dataset, split, queue=None
  ):
      from .rgcn_model import RelGraphEmbedLayer
  
      dev_id = devices[proc_id]
      (
          g,
          node_feats,
          num_of_ntype,
          num_classes,
          num_rels,
          target_idx,
          train_idx,
          val_idx,
          test_idx,
          labels,
      ) = dataset
      labels = labels.cuda(dev_id)
      if split is not None:
          train_seed, val_seed, test_seed = split
          train_idx = train_idx[train_seed]
          # val_idx = val_idx[val_seed]
          # test_idx = test_idx[test_seed]
  
      fanouts = args.fanout
      node_tids = g.ndata[dgl.NTYPE]
      sampler = NeighborSampler(g, target_idx, fanouts)
      loader = DataLoader(
          dataset=train_idx.numpy(),
          batch_size=args.batch_size,
          collate_fn=sampler.sample_blocks,
          shuffle=True,
          num_workers=args.num_workers,
      )
  
      world_size = n_gpus
  
      dist_init_method = "tcp://{master_ip}:{master_port}".format(
          master_ip="127.0.0.1", master_port="12345"
      )
      backend = "nccl"
  
      # using sparse embedding or usig mix_cpu_gpu model (embedding model can not be stored in GPU)
      if args.dgl_sparse is False:
          backend = "gloo"
      print("backend using {}".format(backend))
      th.distributed.init_process_group(
          backend=backend,
          init_method=dist_init_method,
          world_size=world_size,
          rank=dev_id,
      )
  
      # node features
      # None for one-hot feature, if not none, it should be the feature tensor.
      #
      embed_layer = RelGraphEmbedLayer(
          dev_id,
          g.num_nodes(),
          node_tids,
          num_of_ntype,
          node_feats,
          args.n_hidden,
          dgl_sparse=args.dgl_sparse,
      )
  
      # create model
      # all model params are in device.
      model = EntityClassify(
          dev_id,
          g.num_nodes(),
          args.n_hidden,
          num_classes,
          num_rels,
          num_bases=args.n_bases,
          num_hidden_layers=args.n_layers - 2,
          dropout=args.dropout,
          use_self_loop=args.use_self_loop,
          layer_norm=args.layer_norm,
      )
  
      model.cuda(dev_id)
      model = DistributedDataParallel(
          model, device_ids=[dev_id], output_device=dev_id
      )
      if args.dgl_sparse:
          embed_layer.cuda(dev_id)
          if len(list(embed_layer.parameters())) > 0:
              embed_layer = DistributedDataParallel(
                  embed_layer, device_ids=[dev_id], output_device=dev_id
              )
      else:
          if len(list(embed_layer.parameters())) > 0:
              embed_layer = DistributedDataParallel(
                  embed_layer, device_ids=None, output_device=None
              )
  
      # optimizer
      dense_params = list(model.parameters())
      if args.node_feats:
          if n_gpus > 1:
              dense_params += list(
                  embed_layer.module.embeds.parameters()
              )
          else:
              dense_params += list(embed_layer.embeds.parameters())
      optimizer = th.optim.Adam(
          dense_params, lr=args.lr, weight_decay=args.l2norm
      )
  
      if args.dgl_sparse:
          all_params = list(model.parameters()) + list(
              embed_layer.parameters()
          )
          optimizer = th.optim.Adam(
              all_params, lr=args.lr, weight_decay=args.l2norm
          )
          if n_gpus > 1 and isinstance(
              embed_layer, DistributedDataParallel
          ):
              dgl_emb = embed_layer.module.dgl_emb
          else:
              dgl_emb = embed_layer.dgl_emb
          emb_optimizer = (
              dgl.optim.SparseAdam(
                  params=dgl_emb, lr=args.sparse_lr, eps=1e-8
              )
              if len(dgl_emb) > 0
              else None
          )
      else:
          if n_gpus > 1:
              embs = list(embed_layer.module.node_embeds.parameters())
          else:
              embs = list(embed_layer.node_embeds.parameters())
          emb_optimizer = (
              th.optim.SparseAdam(embs, lr=args.sparse_lr)
              if len(embs) > 0
              else None
          )
  
      # training loop
      print("start training...")
      forward_time = []
      backward_time = []
  
      train_time = 0
      validation_time = 0
      test_time = 0
      last_val_acc = 0.0
      do_test = False
      if n_gpus > 1 and n_cpus - args.num_workers > 0:
          th.set_num_threads(n_cpus - args.num_workers)
      steps = 0
      time_records = []
      model.train()
      embed_layer.train()
  
      # Warm up
      for i, sample_data in enumerate(loader):
          seeds, blocks = sample_data
          t0 = time.time()
          feats = embed_layer(
              blocks[0].srcdata[dgl.NID],
              blocks[0].srcdata["ntype"],
              blocks[0].srcdata["type_id"],
              node_feats,
          )
          logits = model(blocks, feats)
          loss = F.cross_entropy(logits, labels[seeds])
          t1 = time.time()
          optimizer.zero_grad()
          if emb_optimizer is not None:
              emb_optimizer.zero_grad()
  
          loss.backward()
          if emb_optimizer is not None:
              emb_optimizer.step()
          optimizer.step()
          gc.collect()
          if i >= 3:
              break
  
      # real time
      for i, sample_data in enumerate(loader):
          seeds, blocks = sample_data
          t0 = time.time()
          feats = embed_layer(
              blocks[0].srcdata[dgl.NID],
              blocks[0].srcdata["ntype"],
              blocks[0].srcdata["type_id"],
              node_feats,
          )
          logits = model(blocks, feats)
          loss = F.cross_entropy(logits, labels[seeds])
          t1 = time.time()
          optimizer.zero_grad()
          if emb_optimizer is not None:
              emb_optimizer.zero_grad()
  
          loss.backward()
          if emb_optimizer is not None:
              emb_optimizer.step()
          optimizer.step()
          th.distributed.barrier()
          t2 = time.time()
  
          forward_time.append(t1 - t0)
          backward_time.append(t2 - t1)
          time_records.append(t2 - t0)
  
          gc.collect()
          if i >= 10:
              break
  
      if proc_id == 0:
          queue.put(np.array(time_records))
  
imports: import argparse
  import gc
  import logging
  import time
  from pathlib import Path
  from types import SimpleNamespace
  import dgl
  import numpy
  import torch
  import torch.multiprocessing
  import torch.nn
  import torch.nn.functional
  from dgl.nn import RelGraphConv
  from torch.multiprocessing import Queue
  from torch.nn.parallel import DistributedDataParallel
  from torch.utils.data import DataLoader
  from ..None import utils
label_desc: Use image node_id 2 for calling a global function with example usage: run(proc_id, n_gpus, n_cpus, args, devices, dataset, split, queue) without return types