class_docstr: A collection of remote modules (of type RemoteModule) with connections showing how inputs
  to the model or outputs of individual modules are use as inputs of subsequent modules.
  The graph has a number of helper functions that add new modules to the graph and define inputs
  to these module.
docstr: Precomputes self.model_input_consumers and self.output_consumers for internal use by the pipleine
  class. These two lists show consumers of inputs to the model, and outputs of each module of
  the graph. Each consumer is a pair (i, j) which stands for the j'th input to the i'th module
  in the graph.
docstr_tok: ["Precomputes","self.model_input_consumers","and","self.output_consumers","for","internal","use","by","the","pipleine","class",".","These","two","lists","show","consumers","of","inputs","to","the","model",",","and","outputs","of","each","module","of","the","graph",".","Each","consumer","is","a","pair","(","i",",","j",")","which","stands","for","the","j'th","input","to","the","i'th","module","in","the","graph","."]
code: def _compile(self) -> None:
      """Precomputes self.model_input_consumers and self.output_consumers for internal use by the pipleine
      class. These two lists show consumers of inputs to the model, and outputs of each module of
      the graph. Each consumer is a pair (i, j) which stands for the j'th input to the i'th module
      in the graph.
      """
  
      # TODO: We need to make sure following conditions hold before preparing the graph for the pipeline:
      #   * the graph has a least one module, and is connected.
      #   * num_inputs and num_outputs for modules matche list of connections defined in the graph.
      #   * all inputs to a module should come from model input, or modules with smaller index in
      #     the graph. This condition is used in implementaion of DistributedPipeline.forward. Even
      #     if we relax this condition, still need to make sure the graph is acyclic.
  
      m = len(self.nodes)
      self.model_input_consumers = []
      for node in self.nodes:
          for input_index, input_item in enumerate(node.inputs):
              data_consumer = NodeDataConsumer(
                  node, input_index, input_item.output_idx
              )
              if input_item.producer is not None:
                  input_item.producer.output_consumers.append(
                      data_consumer
                  )
              else:
                  self.model_input_consumers.append(data_consumer)
  
imports: from dataclasses import dataclass
  from typing import List, Optional, Set, Tuple, Union
  from torch import Tensor, nn
  from torch.distributed import rpc
  from torch.distributed.nn import RemoteModule
  from .data import DataConsumer
label_desc: Use image node_id 7 for calling the PipelineModulesGraph obj's underlying member method code with example usage: obj._compile() without return types