masahi commented on a change in pull request #9108:
URL: https://github.com/apache/tvm/pull/9108#discussion_r727593939



##########
File path: src/runtime/pipeline/pipeline_struct.h
##########
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#define TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#include <assert.h>
+#include <dlpack/dlpack.h>
+#include <dmlc/json.h>
+
+#include <limits>
+#include <string>
+#include <unordered_map>
+#include <vector>
+/*!
+ * \brief All binding information of a output interface.
+ */
+struct OutputBindings {
+  /*!\brief Output interface binding information, 'int' is the index of the 
module that
+   *  uses this output data as the input interface data, 'string' is the input 
interface name
+   *  of the module.
+   */
+  std::unordered_map<int, std::string> bindings;
+  /*! The index value of the global interface to which the current output are 
bound.*/
+  int global_output_index = std::numeric_limits<int>::min();
+  /*!\brief Whether this binding is bound to the PipelineExecutor output 
interface.*/
+  bool IsGlobalOutput() const { return global_output_index >= 0; }
+  /*!
+   * \brief Create a module interface map from JSONReader.
+   * \param reader JSON reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      std::string input_name;
+      int mod_idx = std::numeric_limits<int>::min();
+      // Whether the output binding is global.
+      bool global_binding = false;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "input_name") {
+          reader->Read(&input_name);
+        } else if (key == "global_output_index") {
+          // There should be only one global binding.
+          ICHECK(global_output_index < 0);
+          reader->Read(&global_output_index);
+          // When the key value is 'global_output_index', it means that this 
output is bound to
+          // a global interface.
+          global_binding = true;
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // When this output is bound to a global interface, check if the global 
interface index
+      // is correct.

Review comment:
       What is "correct" index

##########
File path: src/runtime/pipeline/pipeline_executor.h
##########
@@ -36,25 +43,114 @@ namespace runtime {
  *
  *  This executor can be accessed by various language via TVM runtime 
PackedFunc API.
  */
-class TVM_DLL PipelineRuntime : public ModuleNode {
+class TVM_DLL PipelineExecutor : public ModuleNode {
  public:
   /*!
    * \Return the type key of the executor.
    */
-  const char* type_key() const final { return "PipelineRuntime"; }
+  const char* type_key() const final { return "PipelineExecutor"; }
   /*!
-   * \brief Initialize the pipeline executor with module array and json text.
+   * \brief Initialize the pipeline executor with module array and JSON text.
    * \param modules The module list used for building pipeline.
    * \param pipeline_json The configuration of modules dependencies.
    */
-  void Init(const Array<tvm::runtime::Module>& modules, const std::string& 
pipeline_json);
+  void Init(const std::vector<Module>& modules, const std::string& 
pipeline_json);
+  /*!
+   * \brief Use the information of mod_config to create a graph executor list.
+   * \param mod_config The configuration information generated by the library 
export function call.
+   */
+  std::vector<Module> CreateGraphModules(const ModuleConfig& mod_config);
   /*!
    * \brief Give frontends an access to packed functions.
    * \param name The name of the function.
    * \param sptr_to_self The pointer to the module node.
    * \return The corresponding packed function.
    */
   virtual PackedFunc GetFunction(const std::string& name, const 
ObjectPtr<Object>& sptr_to_self);
+
+  /*!
+   * \brief Get the number of outputs.
+   *
+   * \return The number of outputs.
+   */
+  int NumOutputs() const { return num_outputs_; }
+
+  /*!\brief Load the module files information.*/
+  ModuleConfig& LoadModuleConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      std::string lib_name;
+      std::string json_name;
+      std::string params_name;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "lib_name") {
+          reader->Read(&lib_name);
+        } else if (key == "json_name") {
+          reader->Read(&json_name);
+        } else if (key == "params_name") {
+          reader->Read(&params_name);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the vairable 'mod_idx' is successfully read, All moudles 
here are graph executor

Review comment:
       variable

##########
File path: src/runtime/pipeline/pipeline_struct.h
##########
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#define TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#include <assert.h>
+#include <dlpack/dlpack.h>
+#include <dmlc/json.h>
+
+#include <limits>
+#include <string>
+#include <unordered_map>
+#include <vector>
+/*!
+ * \brief All binding information of a output interface.
+ */
+struct OutputBindings {
+  /*!\brief Output interface binding information, 'int' is the index of the 
module that
+   *  uses this output data as the input interface data, 'string' is the input 
interface name
+   *  of the module.
+   */
+  std::unordered_map<int, std::string> bindings;
+  /*! The index value of the global interface to which the current output are 
bound.*/
+  int global_output_index = std::numeric_limits<int>::min();
+  /*!\brief Whether this binding is bound to the PipelineExecutor output 
interface.*/
+  bool IsGlobalOutput() const { return global_output_index >= 0; }
+  /*!
+   * \brief Create a module interface map from JSONReader.
+   * \param reader JSON reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      std::string input_name;
+      int mod_idx = std::numeric_limits<int>::min();
+      // Whether the output binding is global.
+      bool global_binding = false;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "input_name") {
+          reader->Read(&input_name);
+        } else if (key == "global_output_index") {
+          // There should be only one global binding.
+          ICHECK(global_output_index < 0);
+          reader->Read(&global_output_index);
+          // When the key value is 'global_output_index', it means that this 
output is bound to
+          // a global interface.
+          global_binding = true;
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // When this output is bound to a global interface, check if the global 
interface index
+      // is correct.
+      if (global_binding) {
+        ICHECK(global_output_index >= 0);
+      } else {
+        // When this output is bound to a graph executor module interface, 
check if the module
+        // index is correct.
+        ICHECK(mod_idx >= 0);
+        bindings[mod_idx] = input_name;
+      }
+    }
+  }
+};
+
+/*!
+ * \brief The binding information of all outputs of a module.
+ */
+struct OutputMap {
+  /*! \brief Output binding map, 'int' is output interface index.*/
+  std::unordered_map<int, OutputBindings> output_binding_map;
+  OutputMap& operator=(const OutputMap& output) {
+    output_binding_map = output.output_binding_map;
+    return *this;
+  }
+
+  /*!\brief This function is used to verify whether OutputMap is successfully 
loaded.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return output_binding_map.empty(); }
+  /*! \brief The pipeline outputs is the final outputs of pipeline, this 
function is used to
+   *   get how many pipeline outputs are in this Outputmap
+   *  \return Number of pipeline outputs.
+   */
+  size_t GetGlobalOutputNum(void) const {
+    size_t num_output = 0;
+    for (auto bindings : output_binding_map) {
+      num_output += bindings.second.IsGlobalOutput() ? 1 : 0;
+    }
+    return num_output;
+  }
+
+  /*!
+   * \brief Create a output binding map from JSONReader.
+   * \param reader Json reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int output_idx = -1;
+      OutputBindings binding;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "output_idx") {
+          reader->Read(&output_idx);
+        } else if (key == "dependent") {
+          reader->Read(&binding);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      ICHECK(output_idx >= 0);
+      output_binding_map[output_idx] = binding;
+    }
+  }
+};
+/*!
+ * \brief The binding or dependency information of each module output 
interface.
+ */
+struct PipelineConfig {
+  /*!\brief The module index is the key, this variable records all module 
pipeline configuration
+   * information.
+   */
+  std::unordered_map<int, OutputMap> config;
+  OutputMap& operator[](int key) {
+    ICHECK(config.find(key) != config.end());
+    return config[key];
+  }
+
+  void Insert(int key, const OutputMap& map) { config[key] = map; }
+
+  /*!\brief This function is used to verify whether config is loaded 
successfully.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return config.empty(); }
+
+  /*!
+   * \brief Get the number of global outputs that is the outputs of entire 
pipeline.
+   * \return How much output does the entire pipeline have.

Review comment:
          * \brief Get the number of global outputs.
      * \return The number of output the entire pipeline has.

##########
File path: src/runtime/pipeline/pipeline_struct.h
##########
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#define TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#include <assert.h>
+#include <dlpack/dlpack.h>
+#include <dmlc/json.h>
+
+#include <limits>
+#include <string>
+#include <unordered_map>
+#include <vector>
+/*!
+ * \brief All binding information of a output interface.
+ */
+struct OutputBindings {
+  /*!\brief Output interface binding information, 'int' is the index of the 
module that
+   *  uses this output data as the input interface data, 'string' is the input 
interface name
+   *  of the module.
+   */
+  std::unordered_map<int, std::string> bindings;
+  /*! The index value of the global interface to which the current output are 
bound.*/
+  int global_output_index = std::numeric_limits<int>::min();
+  /*!\brief Whether this binding is bound to the PipelineExecutor output 
interface.*/
+  bool IsGlobalOutput() const { return global_output_index >= 0; }
+  /*!
+   * \brief Create a module interface map from JSONReader.
+   * \param reader JSON reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      std::string input_name;
+      int mod_idx = std::numeric_limits<int>::min();
+      // Whether the output binding is global.
+      bool global_binding = false;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "input_name") {
+          reader->Read(&input_name);
+        } else if (key == "global_output_index") {
+          // There should be only one global binding.
+          ICHECK(global_output_index < 0);
+          reader->Read(&global_output_index);
+          // When the key value is 'global_output_index', it means that this 
output is bound to
+          // a global interface.
+          global_binding = true;
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // When this output is bound to a global interface, check if the global 
interface index
+      // is correct.
+      if (global_binding) {
+        ICHECK(global_output_index >= 0);
+      } else {
+        // When this output is bound to a graph executor module interface, 
check if the module
+        // index is correct.
+        ICHECK(mod_idx >= 0);
+        bindings[mod_idx] = input_name;
+      }
+    }
+  }
+};
+
+/*!
+ * \brief The binding information of all outputs of a module.
+ */
+struct OutputMap {
+  /*! \brief Output binding map, 'int' is output interface index.*/
+  std::unordered_map<int, OutputBindings> output_binding_map;
+  OutputMap& operator=(const OutputMap& output) {
+    output_binding_map = output.output_binding_map;
+    return *this;
+  }
+
+  /*!\brief This function is used to verify whether OutputMap is successfully 
loaded.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return output_binding_map.empty(); }
+  /*! \brief The pipeline outputs is the final outputs of pipeline, this 
function is used to
+   *   get how many pipeline outputs are in this Outputmap
+   *  \return Number of pipeline outputs.
+   */
+  size_t GetGlobalOutputNum(void) const {
+    size_t num_output = 0;
+    for (auto bindings : output_binding_map) {
+      num_output += bindings.second.IsGlobalOutput() ? 1 : 0;
+    }
+    return num_output;
+  }
+
+  /*!
+   * \brief Create a output binding map from JSONReader.
+   * \param reader Json reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int output_idx = -1;
+      OutputBindings binding;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "output_idx") {
+          reader->Read(&output_idx);
+        } else if (key == "dependent") {
+          reader->Read(&binding);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      ICHECK(output_idx >= 0);
+      output_binding_map[output_idx] = binding;
+    }
+  }
+};
+/*!
+ * \brief The binding or dependency information of each module output 
interface.
+ */
+struct PipelineConfig {
+  /*!\brief The module index is the key, this variable records all module 
pipeline configuration
+   * information.
+   */
+  std::unordered_map<int, OutputMap> config;
+  OutputMap& operator[](int key) {
+    ICHECK(config.find(key) != config.end());
+    return config[key];
+  }
+
+  void Insert(int key, const OutputMap& map) { config[key] = map; }
+
+  /*!\brief This function is used to verify whether config is loaded 
successfully.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return config.empty(); }
+
+  /*!
+   * \brief Get the number of global outputs that is the outputs of entire 
pipeline.
+   * \return How much output does the entire pipeline have.

Review comment:
       ```
      * \brief Get the number of global outputs.
      * \return The number of output the entire pipeline has.
    ```

##########
File path: src/runtime/pipeline/pipeline_struct.h
##########
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#define TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#include <assert.h>
+#include <dlpack/dlpack.h>
+#include <dmlc/json.h>
+
+#include <limits>
+#include <string>
+#include <unordered_map>
+#include <vector>
+/*!
+ * \brief All binding information of a output interface.
+ */
+struct OutputBindings {
+  /*!\brief Output interface binding information, 'int' is the index of the 
module that
+   *  uses this output data as the input interface data, 'string' is the input 
interface name
+   *  of the module.
+   */
+  std::unordered_map<int, std::string> bindings;
+  /*! The index value of the global interface to which the current output are 
bound.*/
+  int global_output_index = std::numeric_limits<int>::min();
+  /*!\brief Whether this binding is bound to the PipelineExecutor output 
interface.*/
+  bool IsGlobalOutput() const { return global_output_index >= 0; }
+  /*!
+   * \brief Create a module interface map from JSONReader.
+   * \param reader JSON reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      std::string input_name;
+      int mod_idx = std::numeric_limits<int>::min();
+      // Whether the output binding is global.
+      bool global_binding = false;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "input_name") {
+          reader->Read(&input_name);
+        } else if (key == "global_output_index") {
+          // There should be only one global binding.
+          ICHECK(global_output_index < 0);
+          reader->Read(&global_output_index);
+          // When the key value is 'global_output_index', it means that this 
output is bound to
+          // a global interface.
+          global_binding = true;
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // When this output is bound to a global interface, check if the global 
interface index
+      // is correct.
+      if (global_binding) {
+        ICHECK(global_output_index >= 0);
+      } else {
+        // When this output is bound to a graph executor module interface, 
check if the module
+        // index is correct.
+        ICHECK(mod_idx >= 0);
+        bindings[mod_idx] = input_name;
+      }
+    }
+  }
+};
+
+/*!
+ * \brief The binding information of all outputs of a module.
+ */
+struct OutputMap {
+  /*! \brief Output binding map, 'int' is output interface index.*/
+  std::unordered_map<int, OutputBindings> output_binding_map;
+  OutputMap& operator=(const OutputMap& output) {
+    output_binding_map = output.output_binding_map;
+    return *this;
+  }
+
+  /*!\brief This function is used to verify whether OutputMap is successfully 
loaded.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return output_binding_map.empty(); }
+  /*! \brief The pipeline outputs is the final outputs of pipeline, this 
function is used to
+   *   get how many pipeline outputs are in this Outputmap
+   *  \return Number of pipeline outputs.
+   */
+  size_t GetGlobalOutputNum(void) const {
+    size_t num_output = 0;
+    for (auto bindings : output_binding_map) {
+      num_output += bindings.second.IsGlobalOutput() ? 1 : 0;
+    }
+    return num_output;
+  }
+
+  /*!
+   * \brief Create a output binding map from JSONReader.
+   * \param reader Json reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int output_idx = -1;
+      OutputBindings binding;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "output_idx") {
+          reader->Read(&output_idx);
+        } else if (key == "dependent") {
+          reader->Read(&binding);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      ICHECK(output_idx >= 0);
+      output_binding_map[output_idx] = binding;
+    }
+  }
+};
+/*!
+ * \brief The binding or dependency information of each module output 
interface.
+ */
+struct PipelineConfig {
+  /*!\brief The module index is the key, this variable records all module 
pipeline configuration
+   * information.
+   */
+  std::unordered_map<int, OutputMap> config;
+  OutputMap& operator[](int key) {
+    ICHECK(config.find(key) != config.end());
+    return config[key];
+  }
+
+  void Insert(int key, const OutputMap& map) { config[key] = map; }
+
+  /*!\brief This function is used to verify whether config is loaded 
successfully.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return config.empty(); }
+
+  /*!
+   * \brief Get the number of global outputs that is the outputs of entire 
pipeline.
+   * \return How much output does the entire pipeline have.

Review comment:
       ```
      * \brief Get the number of global outputs.
      * \return The number of outputs the entire pipeline has.
    ```

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -72,22 +73,69 @@ def build(pipe_configs):
         mconf["dev"] = "{},{}".format(dev.device_type, dev.device_id)
         # Create a pipeline configuration.
         string_config[mod_idx] = mconf
-        mods[mod] = {"dev": dev}
+        libs[mod_idx] = {"lib": lib, "dev": dev}
 
-    return PipelineExecutorFactoryModule(mods, string_config)
+    return PipelineExecutorFactoryModule(libs, string_config)
 
 
 class PipelineModule(object):
     """Wrapper of runtime module, caller can use this module to set parameters 
and get outputs.
 
     Parameters
     ----------
-    module : PipelineExecutorFactoryModule
-        Common interface for pipeline executor factory modules.
+    module : Union[PipelineExecutorFactoryModule, Module]
+        Common interface for pipeline executor factory modules or Module.
     """
 
     def __init__(self, module):
-        self.module = module.module
+        if isinstance(module, PipelineExecutorFactoryModule):
+            self.module = module.module
+        else:
+            self.module = module
+        # Get the packed functions from the pipeline executor.
+        self._get_num_outputs = self.module["get_num_outputs"]
+
+    @property
+    def num_outputs(self):
+        """Get the number of outputs.
+        Returns
+        -------
+        count : int
+            The number of outputs.
+        """
+        return self._get_num_outputs()
+
+    @staticmethod
+    def load_library(config_file_name):
+        """Import files to create a pipeline executor.
+
+        Parameters
+        ----------
+        config_file_name : str
+            Path and name of the configuration file, the configuration file 
contains the
+            disk path of the parameter file, library file, and JSON file.
+        """
+        with open(config_file_name, "r") as file_handle:
+            config = file_handle.read()
+        config = json.loads(config)
+        if "load_config" not in config or "pipeline_config" not in config:
+            raise RuntimeError(
+                '"load_config" or "pipeline_config" is missing in %s' % 
config_file_name
+            )
+
+        # The config file use to load library, prameters, and JSON files.

Review comment:
       used

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -72,22 +73,69 @@ def build(pipe_configs):
         mconf["dev"] = "{},{}".format(dev.device_type, dev.device_id)
         # Create a pipeline configuration.
         string_config[mod_idx] = mconf
-        mods[mod] = {"dev": dev}
+        libs[mod_idx] = {"lib": lib, "dev": dev}
 
-    return PipelineExecutorFactoryModule(mods, string_config)
+    return PipelineExecutorFactoryModule(libs, string_config)
 
 
 class PipelineModule(object):
     """Wrapper of runtime module, caller can use this module to set parameters 
and get outputs.
 
     Parameters
     ----------
-    module : PipelineExecutorFactoryModule
-        Common interface for pipeline executor factory modules.
+    module : Union[PipelineExecutorFactoryModule, Module]
+        Common interface for pipeline executor factory modules or Module.
     """
 
     def __init__(self, module):
-        self.module = module.module
+        if isinstance(module, PipelineExecutorFactoryModule):
+            self.module = module.module
+        else:
+            self.module = module
+        # Get the packed functions from the pipeline executor.
+        self._get_num_outputs = self.module["get_num_outputs"]
+
+    @property
+    def num_outputs(self):
+        """Get the number of outputs.
+        Returns
+        -------
+        count : int
+            The number of outputs.
+        """
+        return self._get_num_outputs()
+
+    @staticmethod
+    def load_library(config_file_name):
+        """Import files to create a pipeline executor.
+
+        Parameters
+        ----------
+        config_file_name : str
+            Path and name of the configuration file, the configuration file 
contains the
+            disk path of the parameter file, library file, and JSON file.
+        """
+        with open(config_file_name, "r") as file_handle:
+            config = file_handle.read()
+        config = json.loads(config)
+        if "load_config" not in config or "pipeline_config" not in config:
+            raise RuntimeError(
+                '"load_config" or "pipeline_config" is missing in %s' % 
config_file_name
+            )
+
+        # The config file use to load library, prameters, and JSON files.
+        with open(config["load_config"], "r") as file_handle:
+            load_config = file_handle.read()
+
+        # The config file use to load pipeline compute config.

Review comment:
       used

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -139,13 +187,14 @@ def get_owner_idx(self):
             if isinstance(self.io_owner, PipelineConfig.ModuleWrapper):
                 return self.io_owner.idx
 
-            return 0
+            return -1
 
-        def is_global_interface(self):
-            """The global interface is the interface visible to the caller 
which use a pipeline
-            executor, the global input interface is responsible for passing 
parameters to the
-            internal module interface, and the global output interface is 
responsible for
-            outputting the results computed by the pipeline executor to a 
caller.
+        def is_pipeline_executor_interface(self):
+            """The pipeline interface is used to interact with the caller, 
there are two types
+            such interfaces, one is 'input' another is 'output'. the pipeline 
input interface
+            is responsible for passing parameters to the internal module 
interface, and the
+            pipeline output interface is responsible for outputting the 
results computed by
+            the pipeline executor to a caller.

Review comment:
       ```
   The pipeline interface is used to interact with the caller. There are two 
types
               of interfaces, one is 'input' and another is 'output'. The 
pipeline input interface
               is responsible for passing parameters to the internal module 
interface, and the
               pipeline output interface is responsible for outputting the 
results computed by
               the pipeline executor to the caller.
   ```

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -139,13 +187,14 @@ def get_owner_idx(self):
             if isinstance(self.io_owner, PipelineConfig.ModuleWrapper):
                 return self.io_owner.idx
 
-            return 0
+            return -1
 
-        def is_global_interface(self):
-            """The global interface is the interface visible to the caller 
which use a pipeline
-            executor, the global input interface is responsible for passing 
parameters to the
-            internal module interface, and the global output interface is 
responsible for
-            outputting the results computed by the pipeline executor to a 
caller.
+        def is_pipeline_executor_interface(self):
+            """The pipeline interface is used to interact with the caller, 
there are two types
+            such interfaces, one is 'input' another is 'output'. the pipeline 
input interface
+            is responsible for passing parameters to the internal module 
interface, and the
+            pipeline output interface is responsible for outputting the 
results computed by
+            the pipeline executor to a caller.

Review comment:
       ```
   The pipeline interface is used to interact with the caller. There are two 
types
   of interfaces, one is 'input' and another is 'output'. The pipeline input 
interface
   is responsible for passing parameters to the internal module interface, and 
the
   pipeline output interface is responsible for outputting the results computed 
by
   the pipeline executor to the caller.
   ```

##########
File path: src/runtime/pipeline/pipeline_executor.h
##########
@@ -36,25 +43,114 @@ namespace runtime {
  *
  *  This executor can be accessed by various language via TVM runtime 
PackedFunc API.
  */
-class TVM_DLL PipelineRuntime : public ModuleNode {
+class TVM_DLL PipelineExecutor : public ModuleNode {
  public:
   /*!
    * \Return the type key of the executor.
    */
-  const char* type_key() const final { return "PipelineRuntime"; }
+  const char* type_key() const final { return "PipelineExecutor"; }
   /*!
-   * \brief Initialize the pipeline executor with module array and json text.
+   * \brief Initialize the pipeline executor with module array and JSON text.
    * \param modules The module list used for building pipeline.
    * \param pipeline_json The configuration of modules dependencies.
    */
-  void Init(const Array<tvm::runtime::Module>& modules, const std::string& 
pipeline_json);
+  void Init(const std::vector<Module>& modules, const std::string& 
pipeline_json);
+  /*!
+   * \brief Use the information of mod_config to create a graph executor list.

Review comment:
       a list of graph executor

##########
File path: src/runtime/pipeline/pipeline_executor.h
##########
@@ -36,25 +43,114 @@ namespace runtime {
  *
  *  This executor can be accessed by various language via TVM runtime 
PackedFunc API.
  */
-class TVM_DLL PipelineRuntime : public ModuleNode {
+class TVM_DLL PipelineExecutor : public ModuleNode {
  public:
   /*!
    * \Return the type key of the executor.
    */
-  const char* type_key() const final { return "PipelineRuntime"; }
+  const char* type_key() const final { return "PipelineExecutor"; }
   /*!
-   * \brief Initialize the pipeline executor with module array and json text.
+   * \brief Initialize the pipeline executor with module array and JSON text.
    * \param modules The module list used for building pipeline.
    * \param pipeline_json The configuration of modules dependencies.
    */
-  void Init(const Array<tvm::runtime::Module>& modules, const std::string& 
pipeline_json);
+  void Init(const std::vector<Module>& modules, const std::string& 
pipeline_json);
+  /*!
+   * \brief Use the information of mod_config to create a graph executor list.
+   * \param mod_config The configuration information generated by the library 
export function call.
+   */
+  std::vector<Module> CreateGraphModules(const ModuleConfig& mod_config);
   /*!
    * \brief Give frontends an access to packed functions.
    * \param name The name of the function.
    * \param sptr_to_self The pointer to the module node.
    * \return The corresponding packed function.
    */
   virtual PackedFunc GetFunction(const std::string& name, const 
ObjectPtr<Object>& sptr_to_self);
+
+  /*!
+   * \brief Get the number of outputs.
+   *
+   * \return The number of outputs.
+   */
+  int NumOutputs() const { return num_outputs_; }
+
+  /*!\brief Load the module files information.*/
+  ModuleConfig& LoadModuleConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      std::string lib_name;
+      std::string json_name;
+      std::string params_name;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "lib_name") {
+          reader->Read(&lib_name);
+        } else if (key == "json_name") {
+          reader->Read(&json_name);
+        } else if (key == "params_name") {
+          reader->Read(&params_name);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the vairable 'mod_idx' is successfully read, All moudles 
here are graph executor

Review comment:
       variable
   
   modules

##########
File path: src/runtime/pipeline/pipeline_executor.h
##########
@@ -36,25 +43,114 @@ namespace runtime {
  *
  *  This executor can be accessed by various language via TVM runtime 
PackedFunc API.
  */
-class TVM_DLL PipelineRuntime : public ModuleNode {
+class TVM_DLL PipelineExecutor : public ModuleNode {
  public:
   /*!
    * \Return the type key of the executor.
    */
-  const char* type_key() const final { return "PipelineRuntime"; }
+  const char* type_key() const final { return "PipelineExecutor"; }
   /*!
-   * \brief Initialize the pipeline executor with module array and json text.
+   * \brief Initialize the pipeline executor with module array and JSON text.
    * \param modules The module list used for building pipeline.
    * \param pipeline_json The configuration of modules dependencies.
    */
-  void Init(const Array<tvm::runtime::Module>& modules, const std::string& 
pipeline_json);
+  void Init(const std::vector<Module>& modules, const std::string& 
pipeline_json);
+  /*!
+   * \brief Use the information of mod_config to create a graph executor list.
+   * \param mod_config The configuration information generated by the library 
export function call.
+   */
+  std::vector<Module> CreateGraphModules(const ModuleConfig& mod_config);
   /*!
    * \brief Give frontends an access to packed functions.
    * \param name The name of the function.
    * \param sptr_to_self The pointer to the module node.
    * \return The corresponding packed function.
    */
   virtual PackedFunc GetFunction(const std::string& name, const 
ObjectPtr<Object>& sptr_to_self);
+
+  /*!
+   * \brief Get the number of outputs.
+   *
+   * \return The number of outputs.
+   */
+  int NumOutputs() const { return num_outputs_; }
+
+  /*!\brief Load the module files information.*/
+  ModuleConfig& LoadModuleConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      std::string lib_name;
+      std::string json_name;
+      std::string params_name;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "lib_name") {
+          reader->Read(&lib_name);
+        } else if (key == "json_name") {
+          reader->Read(&json_name);
+        } else if (key == "params_name") {
+          reader->Read(&params_name);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the vairable 'mod_idx' is successfully read, All moudles 
here are graph executor
+      // modules, hence the value of 'mod_idx' should start from 0.

Review comment:
       I suggest just remove this comment, becuase "All modules here are graph 
executor modules, hence the value of 'mod_idx' should start from 0" doesn't 
make much sense.

##########
File path: src/runtime/pipeline/pipeline_executor.h
##########
@@ -36,25 +43,114 @@ namespace runtime {
  *
  *  This executor can be accessed by various language via TVM runtime 
PackedFunc API.
  */
-class TVM_DLL PipelineRuntime : public ModuleNode {
+class TVM_DLL PipelineExecutor : public ModuleNode {
  public:
   /*!
    * \Return the type key of the executor.
    */
-  const char* type_key() const final { return "PipelineRuntime"; }
+  const char* type_key() const final { return "PipelineExecutor"; }
   /*!
-   * \brief Initialize the pipeline executor with module array and json text.
+   * \brief Initialize the pipeline executor with module array and JSON text.
    * \param modules The module list used for building pipeline.
    * \param pipeline_json The configuration of modules dependencies.
    */
-  void Init(const Array<tvm::runtime::Module>& modules, const std::string& 
pipeline_json);
+  void Init(const std::vector<Module>& modules, const std::string& 
pipeline_json);
+  /*!
+   * \brief Use the information of mod_config to create a graph executor list.
+   * \param mod_config The configuration information generated by the library 
export function call.
+   */
+  std::vector<Module> CreateGraphModules(const ModuleConfig& mod_config);
   /*!
    * \brief Give frontends an access to packed functions.
    * \param name The name of the function.
    * \param sptr_to_self The pointer to the module node.
    * \return The corresponding packed function.
    */
   virtual PackedFunc GetFunction(const std::string& name, const 
ObjectPtr<Object>& sptr_to_self);
+
+  /*!
+   * \brief Get the number of outputs.
+   *
+   * \return The number of outputs.
+   */
+  int NumOutputs() const { return num_outputs_; }
+
+  /*!\brief Load the module files information.*/
+  ModuleConfig& LoadModuleConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      std::string lib_name;
+      std::string json_name;
+      std::string params_name;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "lib_name") {
+          reader->Read(&lib_name);
+        } else if (key == "json_name") {
+          reader->Read(&json_name);
+        } else if (key == "params_name") {
+          reader->Read(&params_name);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the vairable 'mod_idx' is successfully read, All moudles 
here are graph executor
+      // modules, hence the value of 'mod_idx' should start from 0.
+      ICHECK(mod_idx >= 0) << "Invalid mod_idx value " << mod_idx;
+      // Load the lib, json, and params information.
+      ICHECK(!lib_name.empty()) << "lib_name is empty.";
+      ICHECK(!json_name.empty()) << "json_name is empty.";
+      ICHECK(!params_name.empty()) << "params_name is empty.";
+      mod_config_[mod_idx] = GraphModuleLoadInfo(lib_name, json_name, 
params_name, dev);
+    }
+    return mod_config_;
+  }
+
+ private:
+  /*!\brief The class used to execute and schedule the pipeline logic.*/
+  PipelineScheduler pipeline_scheduler_;
+  /*!\brief The Dependency information of each graph runtime module of the 
pipeline.*/
+  PipelineConfig pipeline_config_;
+  /*!\brief The Module information used to create the graph runtimes.*/
+  ModuleConfig mod_config_;
+  /*!\brief How many outputs are in this pipeline executor.*/
+  size_t num_outputs_ = 0;
+  /*!\brief Json loader.*/
+  PipelineConfig& LoadPipelineConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      OutputMap output;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else if (key == "output") {
+          reader->Read(&output);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the variable 'mod_idx' is successfully read, All moudles 
here are graph executor
+      // modules, hence the value of 'mod_idx' should start from 0.

Review comment:
       Remove this comment

##########
File path: src/runtime/pipeline/pipeline_executor.h
##########
@@ -36,25 +43,114 @@ namespace runtime {
  *
  *  This executor can be accessed by various language via TVM runtime 
PackedFunc API.
  */
-class TVM_DLL PipelineRuntime : public ModuleNode {
+class TVM_DLL PipelineExecutor : public ModuleNode {
  public:
   /*!
    * \Return the type key of the executor.
    */
-  const char* type_key() const final { return "PipelineRuntime"; }
+  const char* type_key() const final { return "PipelineExecutor"; }
   /*!
-   * \brief Initialize the pipeline executor with module array and json text.
+   * \brief Initialize the pipeline executor with module array and JSON text.
    * \param modules The module list used for building pipeline.
    * \param pipeline_json The configuration of modules dependencies.
    */
-  void Init(const Array<tvm::runtime::Module>& modules, const std::string& 
pipeline_json);
+  void Init(const std::vector<Module>& modules, const std::string& 
pipeline_json);
+  /*!
+   * \brief Use the information of mod_config to create a graph executor list.
+   * \param mod_config The configuration information generated by the library 
export function call.
+   */
+  std::vector<Module> CreateGraphModules(const ModuleConfig& mod_config);
   /*!
    * \brief Give frontends an access to packed functions.
    * \param name The name of the function.
    * \param sptr_to_self The pointer to the module node.
    * \return The corresponding packed function.
    */
   virtual PackedFunc GetFunction(const std::string& name, const 
ObjectPtr<Object>& sptr_to_self);
+
+  /*!
+   * \brief Get the number of outputs.
+   *
+   * \return The number of outputs.
+   */
+  int NumOutputs() const { return num_outputs_; }
+
+  /*!\brief Load the module files information.*/
+  ModuleConfig& LoadModuleConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      std::string lib_name;
+      std::string json_name;
+      std::string params_name;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "lib_name") {
+          reader->Read(&lib_name);
+        } else if (key == "json_name") {
+          reader->Read(&json_name);
+        } else if (key == "params_name") {
+          reader->Read(&params_name);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the vairable 'mod_idx' is successfully read, All moudles 
here are graph executor
+      // modules, hence the value of 'mod_idx' should start from 0.
+      ICHECK(mod_idx >= 0) << "Invalid mod_idx value " << mod_idx;
+      // Load the lib, json, and params information.
+      ICHECK(!lib_name.empty()) << "lib_name is empty.";
+      ICHECK(!json_name.empty()) << "json_name is empty.";
+      ICHECK(!params_name.empty()) << "params_name is empty.";
+      mod_config_[mod_idx] = GraphModuleLoadInfo(lib_name, json_name, 
params_name, dev);
+    }
+    return mod_config_;
+  }
+
+ private:
+  /*!\brief The class used to execute and schedule the pipeline logic.*/
+  PipelineScheduler pipeline_scheduler_;
+  /*!\brief The Dependency information of each graph runtime module of the 
pipeline.*/
+  PipelineConfig pipeline_config_;
+  /*!\brief The Module information used to create the graph runtimes.*/
+  ModuleConfig mod_config_;
+  /*!\brief How many outputs are in this pipeline executor.*/
+  size_t num_outputs_ = 0;
+  /*!\brief Json loader.*/
+  PipelineConfig& LoadPipelineConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      OutputMap output;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else if (key == "output") {
+          reader->Read(&output);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the variable 'mod_idx' is successfully read, All moudles 
here are graph executor
+      // modules, hence the value of 'mod_idx' should start from 0.

Review comment:
       Remove this comment for the same reason as 
https://github.com/apache/tvm/pull/9108/files#r727604211

##########
File path: src/runtime/pipeline/pipeline_struct.h
##########
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#define TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#include <assert.h>
+#include <dlpack/dlpack.h>
+#include <dmlc/json.h>
+
+#include <limits>
+#include <string>
+#include <unordered_map>
+#include <vector>
+/*!
+ * \brief All binding information of a output interface.
+ */
+struct OutputBindings {
+  /*!\brief Output interface binding information, 'int' is the index of the 
module that
+   *  uses this output data as the input interface data, 'string' is the input 
interface name
+   *  of the module.
+   */
+  std::unordered_map<int, std::string> bindings;
+  /*! The index value of the global interface to which the current output are 
bound.*/
+  int global_output_index = std::numeric_limits<int>::min();
+  /*!\brief Whether this binding is bound to the PipelineExecutor output 
interface.*/
+  bool IsGlobalOutput() const { return global_output_index >= 0; }
+  /*!
+   * \brief Create a module interface map from JSONReader.
+   * \param reader JSON reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      std::string input_name;
+      int mod_idx = std::numeric_limits<int>::min();
+      // Whether the output binding is global.
+      bool global_binding = false;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "input_name") {
+          reader->Read(&input_name);
+        } else if (key == "global_output_index") {
+          // There should be only one global binding.
+          ICHECK(global_output_index < 0);
+          reader->Read(&global_output_index);
+          // When the key value is 'global_output_index', it means that this 
output is bound to
+          // a global interface.
+          global_binding = true;
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // When this output is bound to a global interface, check if the global 
interface index
+      // is correct.
+      if (global_binding) {
+        ICHECK(global_output_index >= 0);
+      } else {
+        // When this output is bound to a graph executor module interface, 
check if the module
+        // index is correct.
+        ICHECK(mod_idx >= 0);
+        bindings[mod_idx] = input_name;
+      }
+    }
+  }
+};
+
+/*!
+ * \brief The binding information of all outputs of a module.
+ */
+struct OutputMap {
+  /*! \brief Output binding map, 'int' is output interface index.*/
+  std::unordered_map<int, OutputBindings> output_binding_map;
+  OutputMap& operator=(const OutputMap& output) {
+    output_binding_map = output.output_binding_map;
+    return *this;
+  }
+
+  /*!\brief This function is used to verify whether OutputMap is successfully 
loaded.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return output_binding_map.empty(); }
+  /*! \brief The pipeline outputs is the final outputs of pipeline, this 
function is used to
+   *   get how many pipeline outputs are in this Outputmap
+   *  \return Number of pipeline outputs.
+   */
+  size_t GetGlobalOutputNum(void) const {
+    size_t num_output = 0;
+    for (auto bindings : output_binding_map) {
+      num_output += bindings.second.IsGlobalOutput() ? 1 : 0;
+    }
+    return num_output;
+  }
+
+  /*!
+   * \brief Create a output binding map from JSONReader.
+   * \param reader Json reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int output_idx = -1;
+      OutputBindings binding;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "output_idx") {
+          reader->Read(&output_idx);
+        } else if (key == "dependent") {
+          reader->Read(&binding);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      ICHECK(output_idx >= 0);
+      output_binding_map[output_idx] = binding;
+    }
+  }
+};
+/*!
+ * \brief The binding or dependency information of each module output 
interface.
+ */
+struct PipelineConfig {
+  /*!\brief The module index is the key, this variable records all module 
pipeline configuration

Review comment:
       The key is the module index

##########
File path: src/runtime/pipeline/pipeline_struct.h
##########
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#define TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#include <assert.h>
+#include <dlpack/dlpack.h>
+#include <dmlc/json.h>
+
+#include <limits>
+#include <string>
+#include <unordered_map>
+#include <vector>
+/*!
+ * \brief All binding information of a output interface.
+ */
+struct OutputBindings {
+  /*!\brief Output interface binding information, 'int' is the index of the 
module that
+   *  uses this output data as the input interface data, 'string' is the input 
interface name
+   *  of the module.
+   */
+  std::unordered_map<int, std::string> bindings;
+  /*! The index value of the global interface to which the current output are 
bound.*/
+  int global_output_index = std::numeric_limits<int>::min();
+  /*!\brief Whether this binding is bound to the PipelineExecutor output 
interface.*/
+  bool IsGlobalOutput() const { return global_output_index >= 0; }
+  /*!
+   * \brief Create a module interface map from JSONReader.
+   * \param reader JSON reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      std::string input_name;
+      int mod_idx = std::numeric_limits<int>::min();
+      // Whether the output binding is global.
+      bool global_binding = false;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "input_name") {
+          reader->Read(&input_name);
+        } else if (key == "global_output_index") {
+          // There should be only one global binding.
+          ICHECK(global_output_index < 0);
+          reader->Read(&global_output_index);
+          // When the key value is 'global_output_index', it means that this 
output is bound to
+          // a global interface.
+          global_binding = true;
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // When this output is bound to a global interface, check if the global 
interface index
+      // is correct.
+      if (global_binding) {
+        ICHECK(global_output_index >= 0);
+      } else {
+        // When this output is bound to a graph executor module interface, 
check if the module
+        // index is correct.
+        ICHECK(mod_idx >= 0);
+        bindings[mod_idx] = input_name;
+      }
+    }
+  }
+};
+
+/*!
+ * \brief The binding information of all outputs of a module.
+ */
+struct OutputMap {
+  /*! \brief Output binding map, 'int' is output interface index.*/
+  std::unordered_map<int, OutputBindings> output_binding_map;
+  OutputMap& operator=(const OutputMap& output) {
+    output_binding_map = output.output_binding_map;
+    return *this;
+  }
+
+  /*!\brief This function is used to verify whether OutputMap is successfully 
loaded.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return output_binding_map.empty(); }
+  /*! \brief The pipeline outputs is the final outputs of pipeline, this 
function is used to
+   *   get how many pipeline outputs are in this Outputmap
+   *  \return Number of pipeline outputs.
+   */
+  size_t GetGlobalOutputNum(void) const {
+    size_t num_output = 0;
+    for (auto bindings : output_binding_map) {
+      num_output += bindings.second.IsGlobalOutput() ? 1 : 0;
+    }
+    return num_output;
+  }
+
+  /*!
+   * \brief Create a output binding map from JSONReader.
+   * \param reader Json reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int output_idx = -1;
+      OutputBindings binding;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "output_idx") {
+          reader->Read(&output_idx);
+        } else if (key == "dependent") {
+          reader->Read(&binding);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      ICHECK(output_idx >= 0);
+      output_binding_map[output_idx] = binding;
+    }
+  }
+};
+/*!
+ * \brief The binding or dependency information of each module output 
interface.
+ */
+struct PipelineConfig {
+  /*!\brief The module index is the key, this variable records all module 
pipeline configuration
+   * information.
+   */
+  std::unordered_map<int, OutputMap> config;
+  OutputMap& operator[](int key) {
+    ICHECK(config.find(key) != config.end());
+    return config[key];
+  }
+
+  void Insert(int key, const OutputMap& map) { config[key] = map; }
+
+  /*!\brief This function is used to verify whether config is loaded 
successfully.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return config.empty(); }
+
+  /*!
+   * \brief Get the number of global outputs that is the outputs of entire 
pipeline.
+   * \return How much output does the entire pipeline have.
+   */
+  size_t GetGlobalOutputNum() const {
+    size_t num_output = 0;
+    for (auto mod_output : config) {
+      num_output += mod_output.second.GetGlobalOutputNum();
+    }
+    return num_output;
+  }
+};
+/*!
+ * \brief The informations used to initialize the graph executor module, the 
information

Review comment:
       information

##########
File path: src/runtime/pipeline/pipeline_executor.h
##########
@@ -36,25 +43,114 @@ namespace runtime {
  *
  *  This executor can be accessed by various language via TVM runtime 
PackedFunc API.
  */
-class TVM_DLL PipelineRuntime : public ModuleNode {
+class TVM_DLL PipelineExecutor : public ModuleNode {
  public:
   /*!
    * \Return the type key of the executor.
    */
-  const char* type_key() const final { return "PipelineRuntime"; }
+  const char* type_key() const final { return "PipelineExecutor"; }
   /*!
-   * \brief Initialize the pipeline executor with module array and json text.
+   * \brief Initialize the pipeline executor with module array and JSON text.
    * \param modules The module list used for building pipeline.
    * \param pipeline_json The configuration of modules dependencies.
    */
-  void Init(const Array<tvm::runtime::Module>& modules, const std::string& 
pipeline_json);
+  void Init(const std::vector<Module>& modules, const std::string& 
pipeline_json);
+  /*!
+   * \brief Use the information of mod_config to create a graph executor list.
+   * \param mod_config The configuration information generated by the library 
export function call.
+   */
+  std::vector<Module> CreateGraphModules(const ModuleConfig& mod_config);
   /*!
    * \brief Give frontends an access to packed functions.
    * \param name The name of the function.
    * \param sptr_to_self The pointer to the module node.
    * \return The corresponding packed function.
    */
   virtual PackedFunc GetFunction(const std::string& name, const 
ObjectPtr<Object>& sptr_to_self);
+
+  /*!
+   * \brief Get the number of outputs.
+   *
+   * \return The number of outputs.
+   */
+  int NumOutputs() const { return num_outputs_; }
+
+  /*!\brief Load the module files information.*/
+  ModuleConfig& LoadModuleConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      std::string lib_name;
+      std::string json_name;
+      std::string params_name;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "lib_name") {
+          reader->Read(&lib_name);
+        } else if (key == "json_name") {
+          reader->Read(&json_name);
+        } else if (key == "params_name") {
+          reader->Read(&params_name);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the vairable 'mod_idx' is successfully read, All moudles 
here are graph executor
+      // modules, hence the value of 'mod_idx' should start from 0.
+      ICHECK(mod_idx >= 0) << "Invalid mod_idx value " << mod_idx;
+      // Load the lib, json, and params information.
+      ICHECK(!lib_name.empty()) << "lib_name is empty.";
+      ICHECK(!json_name.empty()) << "json_name is empty.";
+      ICHECK(!params_name.empty()) << "params_name is empty.";
+      mod_config_[mod_idx] = GraphModuleLoadInfo(lib_name, json_name, 
params_name, dev);
+    }
+    return mod_config_;
+  }
+
+ private:
+  /*!\brief The class used to execute and schedule the pipeline logic.*/
+  PipelineScheduler pipeline_scheduler_;
+  /*!\brief The Dependency information of each graph runtime module of the 
pipeline.*/

Review comment:
       dependency

##########
File path: src/runtime/pipeline/pipeline_executor.h
##########
@@ -36,25 +43,114 @@ namespace runtime {
  *
  *  This executor can be accessed by various language via TVM runtime 
PackedFunc API.
  */
-class TVM_DLL PipelineRuntime : public ModuleNode {
+class TVM_DLL PipelineExecutor : public ModuleNode {
  public:
   /*!
    * \Return the type key of the executor.
    */
-  const char* type_key() const final { return "PipelineRuntime"; }
+  const char* type_key() const final { return "PipelineExecutor"; }
   /*!
-   * \brief Initialize the pipeline executor with module array and json text.
+   * \brief Initialize the pipeline executor with module array and JSON text.
    * \param modules The module list used for building pipeline.
    * \param pipeline_json The configuration of modules dependencies.
    */
-  void Init(const Array<tvm::runtime::Module>& modules, const std::string& 
pipeline_json);
+  void Init(const std::vector<Module>& modules, const std::string& 
pipeline_json);
+  /*!
+   * \brief Use the information of mod_config to create a graph executor list.
+   * \param mod_config The configuration information generated by the library 
export function call.
+   */
+  std::vector<Module> CreateGraphModules(const ModuleConfig& mod_config);
   /*!
    * \brief Give frontends an access to packed functions.
    * \param name The name of the function.
    * \param sptr_to_self The pointer to the module node.
    * \return The corresponding packed function.
    */
   virtual PackedFunc GetFunction(const std::string& name, const 
ObjectPtr<Object>& sptr_to_self);
+
+  /*!
+   * \brief Get the number of outputs.
+   *
+   * \return The number of outputs.
+   */
+  int NumOutputs() const { return num_outputs_; }
+
+  /*!\brief Load the module files information.*/
+  ModuleConfig& LoadModuleConfig(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int mod_idx = -1;
+      std::string lib_name;
+      std::string json_name;
+      std::string params_name;
+      std::string dev;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "lib_name") {
+          reader->Read(&lib_name);
+        } else if (key == "json_name") {
+          reader->Read(&json_name);
+        } else if (key == "params_name") {
+          reader->Read(&params_name);
+        } else if (key == "dev") {
+          reader->Read(&dev);
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // Check if the vairable 'mod_idx' is successfully read, All moudles 
here are graph executor
+      // modules, hence the value of 'mod_idx' should start from 0.
+      ICHECK(mod_idx >= 0) << "Invalid mod_idx value " << mod_idx;
+      // Load the lib, json, and params information.
+      ICHECK(!lib_name.empty()) << "lib_name is empty.";
+      ICHECK(!json_name.empty()) << "json_name is empty.";
+      ICHECK(!params_name.empty()) << "params_name is empty.";
+      mod_config_[mod_idx] = GraphModuleLoadInfo(lib_name, json_name, 
params_name, dev);
+    }
+    return mod_config_;
+  }
+
+ private:
+  /*!\brief The class used to execute and schedule the pipeline logic.*/
+  PipelineScheduler pipeline_scheduler_;
+  /*!\brief The Dependency information of each graph runtime module of the 
pipeline.*/
+  PipelineConfig pipeline_config_;
+  /*!\brief The Module information used to create the graph runtimes.*/

Review comment:
       module

##########
File path: src/runtime/pipeline/pipeline_struct.h
##########
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#define TVM_RUNTIME_PIPELINE_PIPELINE_STRUCT_H_
+#include <assert.h>
+#include <dlpack/dlpack.h>
+#include <dmlc/json.h>
+
+#include <limits>
+#include <string>
+#include <unordered_map>
+#include <vector>
+/*!
+ * \brief All binding information of a output interface.
+ */
+struct OutputBindings {
+  /*!\brief Output interface binding information, 'int' is the index of the 
module that
+   *  uses this output data as the input interface data, 'string' is the input 
interface name
+   *  of the module.
+   */
+  std::unordered_map<int, std::string> bindings;
+  /*! The index value of the global interface to which the current output are 
bound.*/
+  int global_output_index = std::numeric_limits<int>::min();
+  /*!\brief Whether this binding is bound to the PipelineExecutor output 
interface.*/
+  bool IsGlobalOutput() const { return global_output_index >= 0; }
+  /*!
+   * \brief Create a module interface map from JSONReader.
+   * \param reader JSON reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      std::string input_name;
+      int mod_idx = std::numeric_limits<int>::min();
+      // Whether the output binding is global.
+      bool global_binding = false;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "mod_idx") {
+          reader->Read(&mod_idx);
+        } else if (key == "input_name") {
+          reader->Read(&input_name);
+        } else if (key == "global_output_index") {
+          // There should be only one global binding.
+          ICHECK(global_output_index < 0);
+          reader->Read(&global_output_index);
+          // When the key value is 'global_output_index', it means that this 
output is bound to
+          // a global interface.
+          global_binding = true;
+        } else {
+          LOG(FATAL) << "do not support key " << key;
+        }
+      }
+      // When this output is bound to a global interface, check if the global 
interface index
+      // is correct.
+      if (global_binding) {
+        ICHECK(global_output_index >= 0);
+      } else {
+        // When this output is bound to a graph executor module interface, 
check if the module
+        // index is correct.
+        ICHECK(mod_idx >= 0);
+        bindings[mod_idx] = input_name;
+      }
+    }
+  }
+};
+
+/*!
+ * \brief The binding information of all outputs of a module.
+ */
+struct OutputMap {
+  /*! \brief Output binding map, 'int' is output interface index.*/
+  std::unordered_map<int, OutputBindings> output_binding_map;
+  OutputMap& operator=(const OutputMap& output) {
+    output_binding_map = output.output_binding_map;
+    return *this;
+  }
+
+  /*!\brief This function is used to verify whether OutputMap is successfully 
loaded.
+   * \return Return true to indicate that this class has not been successfully 
loaded.
+   */
+  bool Empty() { return output_binding_map.empty(); }
+  /*! \brief The pipeline outputs is the final outputs of pipeline, this 
function is used to
+   *   get how many pipeline outputs are in this Outputmap
+   *  \return Number of pipeline outputs.
+   */
+  size_t GetGlobalOutputNum(void) const {
+    size_t num_output = 0;
+    for (auto bindings : output_binding_map) {
+      num_output += bindings.second.IsGlobalOutput() ? 1 : 0;
+    }
+    return num_output;
+  }
+
+  /*!
+   * \brief Create a output binding map from JSONReader.
+   * \param reader Json reader.
+   */
+  void Load(dmlc::JSONReader* reader) {
+    reader->BeginArray();
+    while (reader->NextArrayItem()) {
+      std::string key;
+      reader->BeginObject();
+      int output_idx = -1;
+      OutputBindings binding;
+      while (reader->NextObjectItem(&key)) {
+        if (key == "output_idx") {
+          reader->Read(&output_idx);
+        } else if (key == "dependent") {

Review comment:
       `dependent` -> `dependencies`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to