docstr: get all useless nodes in chunk region and prepose them
  
  Args:
      all_node_info (Dict): describe all node's chunk dim and fix dim
      start_idx (int): chunk start idx
      end_idx (int): chunk end idx
  
  Returns:
      List[Node]: all nodes to be preposed
docstr_tok: ["get","all","useless","nodes","in","chunk","region","and","prepose","them","Args",":","all_node_info","(","Dict",")",":","describe","all","node","'s","chunk","dim","and","fix","dim","start_idx","(","int",")",":","chunk","start","idx","end_idx","(","int",")",":","chunk","end","idx","Returns",":","List","[","Node","]",":","all","nodes","to","be","preposed"]
code: def _get_prepose_nodes(
      self,
      all_node_info: Dict,
      start_idx: int,
      end_idx: int,
      chunk_info,
  ) -> List[Node]:
      """
      get all useless nodes in chunk region and prepose them
  
      Args:
          all_node_info (Dict): describe all node's chunk dim and fix dim
          start_idx (int): chunk start idx
          end_idx (int): chunk end idx
  
      Returns:
          List[Node]: all nodes to be preposed
      """
      # get all possible prepose nodes
      maybe_prepose_nodes = []
      for node, node_info in all_node_info.items():
          if node_info["chunk_dim"] is None:
              maybe_prepose_nodes.append(node)
      for node in self.node_mgr.get_node_slice_by_idx(
          start_idx, end_idx
      ):
          if (
              node not in all_node_info
              and node not in chunk_info["outputs"]
          ):
              maybe_prepose_nodes.append(node)
      maybe_prepose_nodes.sort(
          key=lambda x: self.node_mgr.find_node_idx(x),
          reverse=True,
      )  # from last node to first node
      prepose_nodes = []
      # set every node as root, search its args, if all legal, turn root and args as prepose nodes
      while len(maybe_prepose_nodes) > 0:
          tmp_cur_prepose_nodes = [maybe_prepose_nodes[0]]
          tmp_cur_related_prepose_nodes = []
          prepose_flag = True
  
          # loop cur node's all arg until out of chunk
          while len(tmp_cur_prepose_nodes) > 0:
              if prepose_flag == False:
                  break
              tmp_next_prepose_nodes = []
              tmp_cur_related_prepose_nodes.extend(
                  tmp_cur_prepose_nodes
              )
              for cur_prepose_node in tmp_cur_prepose_nodes:
                  if prepose_flag == False:
                      break
                  for (
                      cur_prepose_node_arg
                  ) in cur_prepose_node.all_input_nodes:
                      if type(cur_prepose_node_arg) != type(
                          cur_prepose_node
                      ):
                          continue
                      # out of loop
                      if not (
                          start_idx
                          <= self.node_mgr.find_node_idx(
                              cur_prepose_node_arg
                          )
                          < end_idx
                      ):
                          continue
                      # compute op in loop
                      elif cur_prepose_node_arg in all_node_info:
                          if (
                              all_node_info[cur_prepose_node_arg][
                                  "chunk_dim"
                              ]
                              is None
                          ):
                              tmp_next_prepose_nodes.append(
                                  cur_prepose_node_arg
                              )
                          else:
                              prepose_flag = False
                              break
                      # non compute op
                      else:
                          tmp_next_prepose_nodes.append(
                              cur_prepose_node_arg
                          )
              tmp_cur_prepose_nodes = tmp_next_prepose_nodes
  
          if prepose_flag == False:
              maybe_prepose_nodes.remove(maybe_prepose_nodes[0])
              continue
          else:
              for n in tmp_cur_related_prepose_nodes:
                  if n not in prepose_nodes:
                      prepose_nodes.append(n)
                  if n in maybe_prepose_nodes:
                      maybe_prepose_nodes.remove(n)
      # sort by index
      prepose_nodes.sort(key=lambda x: self.node_mgr.find_node_idx(x))
      chunk_info["args"]["prepose_nodes"] = prepose_nodes
  
file_path: colossalai/colossalai/autochunk/trace_flow.py
imports: from typing import Dict, List, Tuple
  from torch.fx.node import Node
  from .trace_indice import TraceIndice
  from .utils import NodeMgr, find_chunk_all_input_nodes, find_chunk_compute_input_and_output_nodes, find_tensor_shape_node, flat_list, get_node_name, get_node_shape, is_non_compute_node
label_desc: Use image node_id 7 for calling the TraceFlow obj's underlying member method code with example usage: obj._get_prepose_nodes(all_node_info, start_idx, end_idx, chunk_info) without return types