code: def run(args, dev_id, data):
      dropout = 0.2
  
      th.cuda.set_device(dev_id)
  
      # Unpack data
      train_mask, val_mask, in_feats, labels, n_classes, g = data
      train_nid = train_mask.nonzero().squeeze()
      val_nid = val_mask.nonzero().squeeze()
  
      # Create sampler
      sampler = NeighborSampler(
          g, [int(_) for _ in args.fan_out.split(",")]
      )
  
      # Create PyTorch DataLoader for constructing blocks
      dataloader = DataLoader(
          dataset=train_nid.numpy(),
          batch_size=args.batch_size,
          collate_fn=sampler.sample_blocks,
          shuffle=True,
          drop_last=False,
          num_workers=args.num_workers_per_gpu,
      )
  
      # Define model
      model = SAGE(
          in_feats, args.num_hidden, n_classes, args.num_layers, F.relu
      )
  
      # Move the model to GPU and define optimizer
      model = model.to(dev_id)
      loss_fcn = nn.CrossEntropyLoss()
      loss_fcn = loss_fcn.to(dev_id)
      optimizer = optim.Adam(model.parameters(), lr=args.lr)
  
      # Compute history tensor and their aggregation before training on CPU
      model.eval()
      init_history(g, model, dev_id)
      model.train()
  
      # Training loop
      avg = 0
      iter_tput = []
      for epoch in range(args.num_epochs):
          tic = time.time()
          model.train()
          tic_step = time.time()
          for step, (blocks, hist_blocks) in enumerate(dataloader):
              # The nodes for input lies at the LHS side of the first block.
              # The nodes for output lies at the RHS side of the last block.
              input_nodes = blocks[0].srcdata[dgl.NID]
              seeds = blocks[-1].dstdata[dgl.NID]
  
              blocks, hist_blocks = load_subtensor(
                  g, labels, blocks, hist_blocks, dev_id, True
              )
  
              # forward
              batch_pred = model(blocks)
              # update history
              update_history(g, blocks)
              # compute loss
              batch_labels = blocks[-1].dstdata["label"]
              loss = loss_fcn(batch_pred, batch_labels)
              # backward
              optimizer.zero_grad()
              loss.backward()
              optimizer.step()
              iter_tput.append(len(seeds) / (time.time() - tic_step))
              if step % args.log_every == 0:
                  acc = compute_acc(batch_pred, batch_labels)
                  print(
                      "Epoch {:05d} | Step {:05d} | Loss {:.4f} | Train Acc {:.4f} | Speed (samples/sec) {:.4f}".format(
                          epoch,
                          step,
                          loss.item(),
                          acc.item(),
                          np.mean(iter_tput[3:]),
                      )
                  )
              tic_step = time.time()
          toc = time.time()
          print("Epoch Time(s): {:.4f}".format(toc - tic))
          if epoch >= 5:
              avg += toc - tic
          if epoch % args.eval_every == 0 and epoch != 0:
              model.eval()
              eval_acc = evaluate(
                  model, g, labels, val_nid, args.val_batch_size, dev_id
              )
              print("Eval Acc {:.4f}".format(eval_acc))
  
      print("Avg epoch time: {}".format(avg / (epoch - 4)))
  
imports: import argparse
  import time
  import dgl
  import dgl.function
  import dgl.nn.pytorch
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import torch.optim
  import tqdm
  from dgl.data import RedditDataset
  from torch.utils.data import DataLoader
label_desc: Use image node_id 6 for calling a global function with example usage: run(args, dev_id, data) without return types