code: def create_dataloader(
      name,
      graph,
      features,
      item_set,
      device,
      batch_size,
      fanouts,
      shuffle,
      num_workers,
  ):
      """Create a GraphBolt dataloader for training, validation or testing."""
  
      ###########################################################################
      # Initialize the ItemSampler to sample mini-batches from the dataset.
      # `item_set`:
      #   The set of items to sample from. This is typically the
      #   training, validation or test set.
      # `batch_size`:
      #   The number of nodes to sample in each mini-batch.
      # `shuffle`:
      #   Whether to shuffle the items in the dataset before sampling.
      datapipe = gb.ItemSampler(
          item_set, batch_size=batch_size, shuffle=shuffle
      )
  
      # Sample neighbors for each seed node in the mini-batch.
      # `graph`:
      #   The graph(FusedCSCSamplingGraph) from which to sample neighbors.
      # `fanouts`:
      #   The number of neighbors to sample for each node in each layer.
      datapipe = datapipe.sample_neighbor(graph, fanouts=fanouts)
  
      # Fetch the features for each node in the mini-batch.
      # `features`:
      #   The feature store from which to fetch the features.
      # `node_feature_keys`:
      #   The node features to fetch. This is a dictionary where the keys are
      #   node types and the values are lists of feature names.
      node_feature_keys = {"paper": ["feat"]}
      if name == "ogb-lsc-mag240m":
          node_feature_keys["author"] = ["feat"]
          node_feature_keys["institution"] = ["feat"]
      datapipe = datapipe.fetch_feature(features, node_feature_keys)
  
      # Move the mini-batch to the appropriate device.
      # `device`:
      #   The device to move the mini-batch to.
      # [Rui] Usually, we move the mini-batch to target device in the datapipe.
      # However, in this example, we leaves the mini-batch on CPU and move it to
      # GPU after blocks are created. This is because this example is busy on
      # GPU due to embedding layer. And block creation on CPU could be overlapped
      # with optimization operation on GPU and it results in better performance.
      device = torch.device("cpu")
      datapipe = datapipe.copy_to(device)
  
      # Create a DataLoader from the datapipe.
      # `num_workers`:
      #   The number of worker processes to use for data loading.
      return gb.DataLoader(datapipe, num_workers=num_workers)
  
imports: import argparse
  import itertools
  import sys
  import time
  import dgl
  import dgl.graphbolt
  import dgl.nn
  import psutil
  import torch
  import torch.nn
  import torch.nn.functional
  from dgl.nn import HeteroEmbedding
  from ogb.lsc import MAG240MEvaluator
  from ogb.nodeproppred import Evaluator
  from tqdm import tqdm
label_desc: Use image node_id 2 for calling a global function with example usage: create_dataloader(name, graph, features, item_set, device, batch_size, fanouts, shuffle, num_workers) and returns: gb