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



##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -70,24 +71,72 @@ def build(pipe_configs):
         )
 
         mconf["dev"] = "{},{}".format(dev.device_type, dev.device_id)
-        # Create a pipeline configuration.
+        # Create a pipeline configuration, 'mod_idx' start from 0.
         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 : PipelineExecutorFactoryModule/Module

Review comment:
       ```suggestion
       module : Union[PipelineExecutorFactoryModule, Module]
   ```

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -70,24 +71,72 @@ def build(pipe_configs):
         )
 
         mconf["dev"] = "{},{}".format(dev.device_type, dev.device_id)
-        # Create a pipeline configuration.
+        # Create a pipeline configuration, 'mod_idx' start from 0.
         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 : 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.
+        """
+        config = ""

Review comment:
       Don't need this line.

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -532,12 +578,73 @@ def graph_executor_create(self, pipeline_mods, 
mod_config):
         mod_config : str
             The Modudle configuration.
         """
+        # Should store modules in the list named 'mods' in index order.
+        mods = [None for _ in range(len(pipeline_mods))]
+        for lib_index in pipeline_mods:
+            pipeline_lib = pipeline_mods[lib_index]["lib"]
+            dev = pipeline_mods[lib_index]["dev"]
+            lib = graph_executor.GraphModule(pipeline_lib["default"](dev))
+            # Return a module list sorted by lib_index.
+            mods[lib_index] = lib.module
 
-        mods = []
-        for pipeline_mod in pipeline_mods:
-            mod = graph_executor.GraphModule(
-                pipeline_mod["default"](pipeline_mods[pipeline_mod]["dev"])
+        return mods, json.dumps(mod_config)
+
+    def export_library(self, directory_path):
+        """Export the pipeline executor into disk files.
+
+        Parameters
+        ----------
+        directory_path : str
+            Export the files to this directory.
+        """
+        if not self.pipeline_mods:
+            raise RuntimeError(f"The pipeline executor has not been 
initialized.")
+
+        # Check if the directory_path exists.
+        if not os.path.exists(directory_path):
+            raise RuntimeError(f"The directory {directory_path} does not 
exist.")
+        # Create an load configuration.
+        load_config_file_name = "{}/load_config".format(directory_path)
+        pipeline_config_file_name = "{}/pipeline_config".format(directory_path)
+        config = {}
+        config["load_config"] = load_config_file_name
+        config["pipeline_config"] = pipeline_config_file_name
+        load_config = []
+        # Export the library, JSON, and parameter into files, then export 
these files path
+        # into a configuration file.
+        for lib_index in self.pipeline_mods:
+            mconfig = {}
+            mconfig["mod_idx"] = lib_index
+            mconfig["lib_name"] = "{}/lib{}.so".format(directory_path, 
lib_index)
+            mconfig["json_name"] = "{}/json{}".format(directory_path, 
lib_index)
+            mconfig["params_name"] = "{}/params{}".format(directory_path, 
lib_index)
+            mconfig["dev"] = "{},{}".format(
+                self.pipeline_mods[lib_index]["dev"].device_type,
+                self.pipeline_mods[lib_index]["dev"].device_id,
             )
-            mods.append(mod.module)
 
-        return mods, json.dumps(mod_config)
+            # Get the graph, lib, and parameters from 
GraphExecutorFactoryModule.
+            graph, lib, params = self.pipeline_mods[lib_index]["lib"]
+            # Export the lib, graph, and parameters to disk.
+            lib.export_library(mconfig["lib_name"])
+            with open(mconfig["json_name"], "w") as file_handle:
+                file_handle.write(graph)
+            with open(mconfig["params_name"], "wb") as file_handle:
+                file_handle.write(relay.save_param_dict(params))
+
+            load_config.append(mconfig)
+
+        # Export the configuration file to disk.
+        with open(load_config_file_name, "w") as file_handle:
+            file_handle.write(json.dumps(load_config))
+
+        # Export the pipeline configuration file to disk.
+        with open(pipeline_config_file_name, "w") as file_handle:
+            file_handle.write(json.dumps(self.mods_config))
+
+        # Export the configuration file to disk.
+        config_file_name = "{}/config".format(directory_path)
+        with open(config_file_name, "w") as file_handle:
+            file_handle.write(json.dumps(config))

Review comment:
       ```suggestion
               json.dump(config, file_handle)
   ```

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -532,12 +578,73 @@ def graph_executor_create(self, pipeline_mods, 
mod_config):
         mod_config : str
             The Modudle configuration.
         """
+        # Should store modules in the list named 'mods' in index order.
+        mods = [None for _ in range(len(pipeline_mods))]
+        for lib_index in pipeline_mods:
+            pipeline_lib = pipeline_mods[lib_index]["lib"]
+            dev = pipeline_mods[lib_index]["dev"]
+            lib = graph_executor.GraphModule(pipeline_lib["default"](dev))
+            # Return a module list sorted by lib_index.
+            mods[lib_index] = lib.module
 
-        mods = []
-        for pipeline_mod in pipeline_mods:
-            mod = graph_executor.GraphModule(
-                pipeline_mod["default"](pipeline_mods[pipeline_mod]["dev"])
+        return mods, json.dumps(mod_config)
+
+    def export_library(self, directory_path):
+        """Export the pipeline executor into disk files.
+
+        Parameters
+        ----------
+        directory_path : str
+            Export the files to this directory.
+        """
+        if not self.pipeline_mods:
+            raise RuntimeError(f"The pipeline executor has not been 
initialized.")
+
+        # Check if the directory_path exists.
+        if not os.path.exists(directory_path):
+            raise RuntimeError(f"The directory {directory_path} does not 
exist.")
+        # Create an load configuration.
+        load_config_file_name = "{}/load_config".format(directory_path)
+        pipeline_config_file_name = "{}/pipeline_config".format(directory_path)
+        config = {}
+        config["load_config"] = load_config_file_name
+        config["pipeline_config"] = pipeline_config_file_name
+        load_config = []
+        # Export the library, JSON, and parameter into files, then export 
these files path
+        # into a configuration file.
+        for lib_index in self.pipeline_mods:
+            mconfig = {}
+            mconfig["mod_idx"] = lib_index
+            mconfig["lib_name"] = "{}/lib{}.so".format(directory_path, 
lib_index)
+            mconfig["json_name"] = "{}/json{}".format(directory_path, 
lib_index)
+            mconfig["params_name"] = "{}/params{}".format(directory_path, 
lib_index)
+            mconfig["dev"] = "{},{}".format(
+                self.pipeline_mods[lib_index]["dev"].device_type,
+                self.pipeline_mods[lib_index]["dev"].device_id,
             )
-            mods.append(mod.module)
 
-        return mods, json.dumps(mod_config)
+            # Get the graph, lib, and parameters from 
GraphExecutorFactoryModule.
+            graph, lib, params = self.pipeline_mods[lib_index]["lib"]
+            # Export the lib, graph, and parameters to disk.
+            lib.export_library(mconfig["lib_name"])
+            with open(mconfig["json_name"], "w") as file_handle:
+                file_handle.write(graph)
+            with open(mconfig["params_name"], "wb") as file_handle:
+                file_handle.write(relay.save_param_dict(params))
+
+            load_config.append(mconfig)
+
+        # Export the configuration file to disk.
+        with open(load_config_file_name, "w") as file_handle:
+            file_handle.write(json.dumps(load_config))
+
+        # Export the pipeline configuration file to disk.
+        with open(pipeline_config_file_name, "w") as file_handle:
+            file_handle.write(json.dumps(self.mods_config))

Review comment:
       ```suggestion
               json.dump(self.mods_config, file_handle)
   ```

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -70,24 +71,72 @@ def build(pipe_configs):
         )
 
         mconf["dev"] = "{},{}".format(dev.device_type, dev.device_id)
-        # Create a pipeline configuration.
+        # Create a pipeline configuration, 'mod_idx' start from 0.
         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 : 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.
+        """
+        config = ""
+        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(f"Config file format is wrong.")

Review comment:
       ```suggestion
               raise RuntimeError('"load_config" or "pipeline_config" is 
missing in %s' % config_file_name)
   ```

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -532,12 +578,73 @@ def graph_executor_create(self, pipeline_mods, 
mod_config):
         mod_config : str
             The Modudle configuration.
         """
+        # Should store modules in the list named 'mods' in index order.
+        mods = [None for _ in range(len(pipeline_mods))]
+        for lib_index in pipeline_mods:
+            pipeline_lib = pipeline_mods[lib_index]["lib"]
+            dev = pipeline_mods[lib_index]["dev"]
+            lib = graph_executor.GraphModule(pipeline_lib["default"](dev))
+            # Return a module list sorted by lib_index.
+            mods[lib_index] = lib.module
 
-        mods = []
-        for pipeline_mod in pipeline_mods:
-            mod = graph_executor.GraphModule(
-                pipeline_mod["default"](pipeline_mods[pipeline_mod]["dev"])
+        return mods, json.dumps(mod_config)
+
+    def export_library(self, directory_path):
+        """Export the pipeline executor into disk files.
+
+        Parameters
+        ----------
+        directory_path : str
+            Export the files to this directory.
+        """
+        if not self.pipeline_mods:
+            raise RuntimeError(f"The pipeline executor has not been 
initialized.")
+
+        # Check if the directory_path exists.
+        if not os.path.exists(directory_path):
+            raise RuntimeError(f"The directory {directory_path} does not 
exist.")
+        # Create an load configuration.
+        load_config_file_name = "{}/load_config".format(directory_path)
+        pipeline_config_file_name = "{}/pipeline_config".format(directory_path)
+        config = {}
+        config["load_config"] = load_config_file_name
+        config["pipeline_config"] = pipeline_config_file_name
+        load_config = []
+        # Export the library, JSON, and parameter into files, then export 
these files path
+        # into a configuration file.
+        for lib_index in self.pipeline_mods:
+            mconfig = {}
+            mconfig["mod_idx"] = lib_index
+            mconfig["lib_name"] = "{}/lib{}.so".format(directory_path, 
lib_index)
+            mconfig["json_name"] = "{}/json{}".format(directory_path, 
lib_index)
+            mconfig["params_name"] = "{}/params{}".format(directory_path, 
lib_index)
+            mconfig["dev"] = "{},{}".format(
+                self.pipeline_mods[lib_index]["dev"].device_type,
+                self.pipeline_mods[lib_index]["dev"].device_id,
             )
-            mods.append(mod.module)
 
-        return mods, json.dumps(mod_config)
+            # Get the graph, lib, and parameters from 
GraphExecutorFactoryModule.
+            graph, lib, params = self.pipeline_mods[lib_index]["lib"]
+            # Export the lib, graph, and parameters to disk.
+            lib.export_library(mconfig["lib_name"])
+            with open(mconfig["json_name"], "w") as file_handle:
+                file_handle.write(graph)
+            with open(mconfig["params_name"], "wb") as file_handle:
+                file_handle.write(relay.save_param_dict(params))
+
+            load_config.append(mconfig)
+
+        # Export the configuration file to disk.
+        with open(load_config_file_name, "w") as file_handle:
+            file_handle.write(json.dumps(load_config))

Review comment:
       ```suggestion
               json.dump(load_config, file_handle)
   ```

##########
File path: src/runtime/pipeline/pipeline_executor.cc
##########
@@ -21,31 +21,128 @@
  * \file pipeline_executor.cc
  */
 #include "pipeline_executor.h"
-
 namespace tvm {
 namespace runtime {
+/*!
+ * \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.
+ */
+PackedFunc PipelineExecutor::GetFunction(const std::string& name,
+                                         const ObjectPtr<Object>& 
sptr_to_self) {
+  if (name == "get_num_outputs") {
+    return PackedFunc(
+        [sptr_to_self, this](TVMArgs args, TVMRetValue* rv) { *rv = 
this->NumOutputs(); });
+  } else {
+    LOG(FATAL) << "Unknown packed function: " << name;
+    return PackedFunc();
+  }
+  return nullptr;
+}
 
-void PipelineRuntime::Init(const Array<tvm::runtime::Module>& modules,
-                           const std::string& pipeline_json) {
-  return;
+/*!
+ * \brief Use the mod_config information to create a graph runtime list.
+ * \param mod_config The config information that generates by the export 
library function call.
+ */
+std::vector<Module> PipelineExecutor::CreateGraphModules(const ModuleConfig& 
mod_config) {
+  const PackedFunc* graph_executor_create = 
Registry::Get("tvm.graph_executor.create");
+  std::vector<Module> ret;
+  ret.resize(mod_config.size());
+  for (auto config : mod_config) {
+    // Load library.
+    auto lib = Module::LoadFromFile(config.second.lib_name.c_str());
+
+    // Read json.
+    std::ifstream ifJson(config.second.json_name.c_str());
+    if (ifJson.fail()) {
+      LOG(FATAL) << "json file not found!";

Review comment:
       ```suggestion
         LOG(FATAL) << "json file not found: " << config.second.json_name;
   ```

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -70,24 +71,72 @@ def build(pipe_configs):
         )
 
         mconf["dev"] = "{},{}".format(dev.device_type, dev.device_id)
-        # Create a pipeline configuration.
+        # Create a pipeline configuration, 'mod_idx' start from 0.
         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 : 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.
+        """
+        config = ""
+        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(f"Config file format is wrong.")
+
+        # The config file use to load library, prameters, and JSON files.
+        load_config = ""

Review comment:
       Don't need this line.

##########
File path: python/tvm/contrib/pipeline_executor.py
##########
@@ -70,24 +71,72 @@ def build(pipe_configs):
         )
 
         mconf["dev"] = "{},{}".format(dev.device_type, dev.device_id)
-        # Create a pipeline configuration.
+        # Create a pipeline configuration, 'mod_idx' start from 0.
         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 : 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.
+        """
+        config = ""
+        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(f"Config file format is wrong.")
+
+        # The config file use to load library, prameters, and JSON files.
+        load_config = ""
+        with open(config["load_config"], "r") as file_handle:
+            load_config = file_handle.read()
+
+        # The config file use to load pipeline compute config.
+        pipeline_config = ""

Review comment:
       Don't need this line.




-- 
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