code: def inference(self, loader, feature, norm):
      # We add state: {} here, which is used to store additional state,
      # such as residual connections.
      loader = [(sub_data, {}) for sub_data in loader]
  
      if len(self.histories) == 0:
          for sub_data, state in loader:
              (
                  g,
                  batch_size,
                  n_id,
                  offset,
                  count,
                  feat,
                  sub_norm,
              ) = process_batch_data(sub_data, feature, norm)
              out = self.forward_layer(0, g, feat, sub_norm, state)[
                  :batch_size
              ]
              # Push out to self._final_out()
              async_write(out, self._final_out(), offset, count)
          return self._final_out()
  
      # Push outputs of 0-th layer to the history.
      for sub_data, state in loader:
          (
              g,
              batch_size,
              n_id,
              offset,
              count,
              feat,
              sub_norm,
          ) = process_batch_data(sub_data, feature, norm)
          out = self.forward_layer(0, g, feat, sub_norm, state)[
              :batch_size
          ]
          self.pool.async_push(
              out, self.histories[0].emb, offset, count
          )
      self.pool.sync_push()
  
      for i in range(1, len(self.histories)):
          # Pull the complete layer-wise history.
          for sub_data, _ in loader:
              (
                  _,
                  batch_size,
                  n_id,
                  offset,
                  count,
                  _,
                  _,
              ) = process_batch_data(sub_data)
              if batch_size < len(n_id):
                  cpu_nid = n_id[batch_size:].cpu()
                  self.pool.async_pull(
                      self.histories[i - 1].emb, cpu_nid, offset, count
                  )
          for sub_data, state in loader:
              (
                  g,
                  batch_size,
                  n_id,
                  offset,
                  count,
                  _,
                  sub_norm,
              ) = process_batch_data(sub_data, norm=norm)
              x = self.pool.sync_pull()[: len(n_id)]
              out = self.forward_layer(i, g, x, sub_norm, state)[
                  :batch_size
              ]
              self.pool.async_push(
                  out, self.histories[i].emb, offset, count
              )
              self.pool.free_pull()
          self.pool.sync_push()
  
      # Pull the histories from last layer.
      for sub_data, _ in loader:
          _, batch_size, n_id, offset, count, _, _ = process_batch_data(
              sub_data
          )
          if batch_size < len(n_id):
              cpu_nid = n_id[batch_size:].cpu()
              self.pool.async_pull(
                  self.histories[-1].emb, cpu_nid, offset, count
              )
  
      # Compute final embeddings.
      for sub_data, state in loader:
          (
              g,
              batch_size,
              n_id,
              offset,
              count,
              _,
              sub_norm,
          ) = process_batch_data(sub_data, norm=norm)
          x = self.pool.sync_pull()[: len(n_id)]
          out = self.forward_layer(
              self.num_layers - 1, g, x, sub_norm, state
          )[:batch_size]
          self.pool.async_push(out, self._final_out(), offset, count)
          self.pool.free_pull()
      self.pool.sync_push()
  
      return self._final_out()
  
file_path: PGL/apps/GNNAutoScale/gnn_models/base_model.py
imports: import os
  import sys
  import numpy
  import paddle
  from pgl.utils.stream_pool import StreamPool, async_write
  from history import History
  from utils import process_batch_data, check_device
label_desc: Use image node_id 7 for calling the ScalableGNN obj's underlying member method code with example usage: obj.inference(loader, feature, norm) and returns: self, self