This is an automated email from the ASF dual-hosted git repository.
syfeng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new 343435a529 [Unity][MSC][M4.2][Step1] Enable plugin with manager, test
plugins in compile pipeline (#16495)
343435a529 is described below
commit 343435a5297db39365ba9c764c6fc15dc2789373
Author: Archermmt <[email protected]>
AuthorDate: Mon Feb 5 12:16:21 2024 +0800
[Unity][MSC][M4.2][Step1] Enable plugin with manager, test plugins in
compile pipeline (#16495)
* add plugin in manager
* remove wrapper
---
python/tvm/contrib/msc/core/runtime/runner.py | 9 +++
python/tvm/contrib/msc/core/tools/prune/pruner.py | 1 +
.../contrib/msc/core/tools/quantize/quantizer.py | 5 ++
python/tvm/contrib/msc/core/tools/tool.py | 47 ++++++++-------
.../msc/framework/tensorflow/codegen/codegen.py | 10 +++-
.../msc/framework/tensorrt/codegen/codegen.py | 17 +++++-
.../msc/framework/tensorrt/transform/pattern.py | 48 ++++++++++++++++
.../contrib/msc/framework/torch/codegen/codegen.py | 8 ++-
.../contrib/msc/framework/tvm/codegen/codegen.py | 10 +++-
python/tvm/contrib/msc/pipeline/manager.py | 66 ++++++++++++++++------
src/contrib/msc/core/codegen/base_codegen.h | 39 +++++++++++++
src/contrib/msc/core/transform/set_expr_layout.cc | 19 +++++++
src/contrib/msc/framework/tensorrt/codegen.cc | 30 +++++++++-
src/contrib/msc/framework/tensorrt/codegen_utils.h | 4 ++
.../msc/framework/tensorrt/tensorrt_opcode.cc | 54 ++++++++++++------
src/contrib/msc/framework/torch/codegen.cc | 26 +++++++--
src/contrib/msc/framework/torch/torch_opcode.cc | 27 ++++++++-
src/contrib/msc/framework/tvm/codegen.cc | 14 ++++-
src/contrib/msc/framework/tvm/relax_opcode.cc | 14 +++++
19 files changed, 374 insertions(+), 74 deletions(-)
diff --git a/python/tvm/contrib/msc/core/runtime/runner.py
b/python/tvm/contrib/msc/core/runtime/runner.py
index 2849eb05ed..6d3a364e90 100644
--- a/python/tvm/contrib/msc/core/runtime/runner.py
+++ b/python/tvm/contrib/msc/core/runtime/runner.py
@@ -57,6 +57,8 @@ class BaseRunner(object):
Whether compile model to trainable
stage: str
The stage of runner.
+ plugin: PluginManager
+ The plugin manager.
name: str
The name of the runner
debug_level: int
@@ -75,6 +77,7 @@ class BaseRunner(object):
device: str = "cpu",
training: bool = False,
stage: str = "default",
+ plugin: Any = None,
name: str = "main",
debug_level: int = 0,
logger: logging.Logger = None,
@@ -86,6 +89,7 @@ class BaseRunner(object):
self._build_config = msc_utils.copy_dict(build_config)
self._device = device if self._device_enabled(device) else "cpu"
self._stage = stage
+ self._plugin = plugin
self._name = name
self._debug_level = debug_level
self._training, self._trained = training, training
@@ -123,8 +127,11 @@ class BaseRunner(object):
stage=self._stage,
**config,
)
+ if self._plugin:
+ self._update_codegen({"use_plugin": True})
return {
"tools": {k: v.tool_style() for k, v in self._tools.items()},
+ "plugin": self._plugin,
"translate_config": self._translate_config,
"generate_config": self._generate_config,
"build_config": self._build_config,
@@ -1069,6 +1076,7 @@ class ModelRunner(BaseRunner):
codegen_config=self._generate_config.get("codegen"),
print_config=self._generate_config.get("print"),
build_folder=self._generate_config["build_folder"],
+ plugin=self._plugin,
)
def _inspect_model(self) -> dict:
@@ -1226,6 +1234,7 @@ class BYOCRunner(BaseRunner):
extra_options=extra_option,
build_folder=self._generate_config["build_folder"],
output_folder=self._generate_config.get("output_folder",
msc_utils.get_output_dir()),
+ plugin=self._plugin,
)
def _build_runnable(self, model: Any) -> Any:
diff --git a/python/tvm/contrib/msc/core/tools/prune/pruner.py
b/python/tvm/contrib/msc/core/tools/prune/pruner.py
index bb2ff99220..7eb4434a62 100644
--- a/python/tvm/contrib/msc/core/tools/prune/pruner.py
+++ b/python/tvm/contrib/msc/core/tools/prune/pruner.py
@@ -82,6 +82,7 @@ class BasePruner(WeightTool):
def _update_stages(strategy):
if "stages" not in strategy:
strategy["stages"] = [msc_utils.MSCStage.PRUNE]
+ strategy["tensor_types"] = ["weight", "output"]
return strategy
return super()._parse_strategys([_update_stages(s) for s in
strategy_list])
diff --git a/python/tvm/contrib/msc/core/tools/quantize/quantizer.py
b/python/tvm/contrib/msc/core/tools/quantize/quantizer.py
index bee8e6fa42..3b0f3267df 100644
--- a/python/tvm/contrib/msc/core/tools/quantize/quantizer.py
+++ b/python/tvm/contrib/msc/core/tools/quantize/quantizer.py
@@ -114,6 +114,11 @@ class BaseQuantizer(BaseTool):
Whether to process the tensor.
"""
+ if self._calibrated:
+ tensor_id = self.to_tensor_id(name, consumer)
+ if tensor_id not in self._plan:
+ return False
+ return self._plan.get(tensor_id, {}).get("nbits", 8) != -1
strategys = self._get_tensor_strategys(name, consumer)
if not strategys:
return False
diff --git a/python/tvm/contrib/msc/core/tools/tool.py
b/python/tvm/contrib/msc/core/tools/tool.py
index 7253841122..fec391339f 100644
--- a/python/tvm/contrib/msc/core/tools/tool.py
+++ b/python/tvm/contrib/msc/core/tools/tool.py
@@ -409,7 +409,7 @@ class BaseTool(object):
tensor_names = strategy.pop("tensor_names")
marks = [(n, "tensor") for n in tensor_names]
else:
- marks = [("default", t) for t in ["input", "output", "weight"]]
+ marks = [("default." + str(t), t) for t in tensor_types]
stages = strategy.pop("stages") if "stages" in strategy else
["default"]
for mark, t_type in marks:
if mark not in strategys:
@@ -1212,33 +1212,38 @@ class BaseTool(object):
tensor_id = self.to_tensor_id(name, consumer)
mark = "strategy.{}".format(self._stage)
+
+ def _check_strategy(s_ref):
+ return s_ref in self._strategys and
self._strategys[s_ref].support_stage(self._stage)
+
if mark not in self._tensor_cache.get(tensor_id, {}):
- if self.is_weight(name):
+ strategys = []
+ tensor_strategy = self._strategys.get(tensor_id)
+ if tensor_strategy and tensor_strategy.support_stage(self._stage):
+ strategys.append(tensor_strategy)
+ elif self.is_weight(name):
consumer = self.find_node(consumer)
- name_refs = [consumer.name + ".weight", consumer.optype +
".weight"]
+ for ref in [consumer.name, consumer.optype, "default"]:
+ if _check_strategy(ref + ".weight"):
+ strategys.append(self._strategys[ref + ".weight"])
+ break
elif consumer == "exit":
producer = self.find_producer(name)
- name_refs = [producer.name + ".output", producer.optype +
".output"]
+ for ref in [producer.name, producer.optype, "exit", "default"]:
+ if _check_strategy(ref + ".output"):
+ strategys.append(self._strategys[ref + ".output"])
+ break
else:
consumer = self.find_node(consumer)
+ for ref in [consumer.name, consumer.optype, "default"]:
+ if _check_strategy(ref + ".input"):
+ strategys.append(self._strategys[ref + ".input"])
+ break
producer = self.find_producer(name)
- name_refs = [
- producer.name + ".output",
- producer.optype + ".output",
- consumer.name + ".input",
- consumer.optype + ".input",
- ]
- strategys = []
- tensor_strategy = self._strategys.get(tensor_id)
- if tensor_strategy and tensor_strategy.support_stage(self._stage):
- strategys.append(tensor_strategy)
- if not strategys:
- for n in name_refs:
- if n in self._strategys and
self._strategys[n].support_stage(self._stage):
- strategys.append(self._strategys[n])
- d_strategy = self._strategys.get("default")
- if not strategys and d_strategy and
d_strategy.support_stage(self._stage):
- strategys.append(d_strategy)
+ for ref in [producer.name, producer.optype, "default"]:
+ if _check_strategy(ref + ".output"):
+ strategys.append(self._strategys[ref + ".output"])
+ break
self._save_tensor_cache(name, consumer, mark, strategys)
return self._get_tensor_cache(name, consumer, mark)
diff --git a/python/tvm/contrib/msc/framework/tensorflow/codegen/codegen.py
b/python/tvm/contrib/msc/framework/tensorflow/codegen/codegen.py
index 4555d23528..f24150efcd 100644
--- a/python/tvm/contrib/msc/framework/tensorflow/codegen/codegen.py
+++ b/python/tvm/contrib/msc/framework/tensorflow/codegen/codegen.py
@@ -16,7 +16,7 @@
# under the License.
"""tvm.contrib.msc.framework.tensorflow.codegen.codegen"""
-from typing import Dict, Optional
+from typing import Dict, Optional, Any
import tvm
from tvm.contrib.msc.core.ir import MSCGraph
@@ -32,6 +32,7 @@ def to_tensorflow(
codegen_config: Optional[Dict[str, str]] = None,
print_config: Optional[Dict[str, str]] = None,
build_folder: msc_utils.MSCDirectory = None,
+ plugin: Any = None,
) -> tf_v1.Graph:
"""Change MSCGraph to tensorflow graph.
@@ -47,6 +48,8 @@ def to_tensorflow(
The config for print.
build_folder: MSCDirectory
The folder for saving scripts and datas.
+ plugin: PluginManager
+ The plugin manager.
Returns
-------
@@ -63,4 +66,7 @@ def to_tensorflow(
codegen = CodeGen(
graph, _ffi_api.GetTensorflowSources, codegen_config, print_config,
build_folder
)
- return codegen.load(inputs + [weights], pre_load=_save_weights)
+ model_args = inputs + [weights]
+ if plugin:
+ model_args = model_args + [plugin]
+ return codegen.load(model_args, pre_load=_save_weights)
diff --git a/python/tvm/contrib/msc/framework/tensorrt/codegen/codegen.py
b/python/tvm/contrib/msc/framework/tensorrt/codegen/codegen.py
index d72b14cfd5..4643d49c1e 100644
--- a/python/tvm/contrib/msc/framework/tensorrt/codegen/codegen.py
+++ b/python/tvm/contrib/msc/framework/tensorrt/codegen/codegen.py
@@ -18,7 +18,7 @@
import os
import subprocess
-from typing import Dict, Optional, List, Union
+from typing import Dict, Optional, List, Union, Any
import numpy as np
import tvm
@@ -38,6 +38,7 @@ def to_sub_tensorrt(
print_config: Optional[Dict[str, str]] = None,
build_folder: msc_utils.MSCDirectory = None,
output_folder: msc_utils.MSCDirectory = None,
+ plugin: Any = None,
) -> str:
"""Change MSCGraph to TensorRT engine file.
@@ -55,6 +56,8 @@ def to_sub_tensorrt(
The folder for saving sources and datas.
export_folder: MSCDirectory
The folder for saving outputs.
+ plugin: PluginManager
+ The plugin manager.
Returns
-------
@@ -90,6 +93,10 @@ def to_sub_tensorrt(
f.write("{}\n".format(len(engine_wts)))
for name, data in engine_wts.items():
write_weight(name, msc_utils.cast_array(data), f)
+ # copy plugin
+ if plugin:
+ plugin.copy_libs("plugin_lib")
+ plugin.copy_includes("plugin")
# save utils sources
with folder.create_dir("utils") as utils_folder:
for name, source in get_trt_sources().items():
@@ -115,6 +122,10 @@ def to_sub_tensorrt(
with build_folder as folder:
sub_folder = folder.create_dir(graph.name)
+ if plugin:
+ codegen_config["extern_libs"] = [
+ sub_folder.create_dir("plugin_lib").relpath(f) for f in
plugin.list_libs()
+ ]
codegen = CodeGen(
graph,
_ffi_api.GetTensorRTSources,
@@ -140,6 +151,7 @@ def to_tensorrt(
extra_options: Optional[Union[Dict[str, str], List[Dict[str, str]]]] =
None,
build_folder: msc_utils.MSCDirectory = None,
output_folder: msc_utils.MSCDirectory = None,
+ plugin: Any = None,
) -> Dict[str, str]:
"""Change all MSCGraphs to TensorRT engine files.
@@ -161,6 +173,8 @@ def to_tensorrt(
The folder for saving sources and datas.
export_folder: MSCDirectory
The folder for saving outputs.
+ plugin: PluginManager
+ The plugin manager.
Returns
-------
@@ -183,6 +197,7 @@ def to_tensorrt(
print_configs[idx],
build_folder,
output_folder,
+ plugin=plugin,
)
if extra_options[idx]:
options.update(extra_options[idx])
diff --git a/python/tvm/contrib/msc/framework/tensorrt/transform/pattern.py
b/python/tvm/contrib/msc/framework/tensorrt/transform/pattern.py
index effa86595d..8eea3f7081 100644
--- a/python/tvm/contrib/msc/framework/tensorrt/transform/pattern.py
+++ b/python/tvm/contrib/msc/framework/tensorrt/transform/pattern.py
@@ -20,11 +20,13 @@
from typing import Mapping, Tuple, List, Union, Callable, Dict
from functools import wraps, partial
+import tvm
from tvm import relax
from tvm.relax.dpl import pattern
from tvm.relax.transform import PatternCheckContext, FusionPattern
from tvm.relax.backend.pattern_registry import register_patterns
from tvm.contrib.msc.core.transform import pattern as msc_pattern
+from tvm.contrib.msc.core import _ffi_api
def basic_pattern(
@@ -234,6 +236,43 @@ def _take_check(context: PatternCheckContext) -> bool:
return _check_expr(context.annotated_expr["input_1"], ("int32"))
+def _plugin_check(context: PatternCheckContext) -> bool:
+ """Check if the plugin pattern is correct.
+
+ Returns
+ -------
+ pass: bool
+ Whether the pattern is correct.
+ """
+
+ ext_func = context.annotated_expr["out"].args[0]
+ return bool(_ffi_api.IsPlugin(ext_func.global_symbol))
+
+
+def plugin_attrs_getter(
+ annotated_expr: Dict[str, tvm.relax.Expr],
+) -> Dict[str, str]:
+ """Get attributes for plugin pattern
+
+ Parameters
+ ----------
+ annotated_expr: dict<str,Expr>
+ The annotated exprs during fus pattern
+ anchor: str
+ The anchor key of expr
+
+ Returns
+ -------
+ attrs: dict<str,str>
+ The extra attributes for msc.
+ """
+
+ attrs = msc_pattern.msc_attrs_getter(annotated_expr, anchor="out")
+ ext_func = annotated_expr["out"].args[0]
+ attrs[_ffi_api.ToAttrKey("optype")] = ext_func.global_symbol
+ return attrs
+
+
def wrap_basic_check(
func: Callable[[PatternCheckContext], bool]
) -> Callable[[PatternCheckContext], bool]:
@@ -410,6 +449,15 @@ def get_patterns(target) -> List[Pattern]:
),
]
)
+ # plugin ops
+ patterns.append(
+ (
+ target + ".plugin",
+ *basic_pattern("relax.call_dps_packed", ["input", "input"]),
+ _plugin_check,
+ plugin_attrs_getter,
+ )
+ )
return patterns
diff --git a/python/tvm/contrib/msc/framework/torch/codegen/codegen.py
b/python/tvm/contrib/msc/framework/torch/codegen/codegen.py
index f885c81aa6..d4aeabb10a 100644
--- a/python/tvm/contrib/msc/framework/torch/codegen/codegen.py
+++ b/python/tvm/contrib/msc/framework/torch/codegen/codegen.py
@@ -16,7 +16,7 @@
# under the License.
"""tvm.contrib.msc.framework.torch.codegen.codegen"""
-from typing import Dict, Optional
+from typing import Dict, Optional, Any
import torch
import tvm
@@ -32,6 +32,7 @@ def to_torch(
codegen_config: Optional[Dict[str, str]] = None,
print_config: Optional[Dict[str, str]] = None,
build_folder: msc_utils.MSCDirectory = None,
+ plugin: Any = None,
) -> torch.nn.Module:
"""Change MSCGraph to torch nn.Module.
@@ -47,6 +48,8 @@ def to_torch(
The config for print.
build_folder: MSCDirectory
The folder for saving scripts and datas.
+ plugin: PluginManager
+ The plugin manager.
Returns
-------
@@ -73,4 +76,5 @@ def to_torch(
return model
codegen = CodeGen(graph, _ffi_api.GetTorchSources, codegen_config,
print_config, build_folder)
- return codegen.load([], pre_load=_save_weights, post_load=_bind_weights)
+ model_args = [plugin] if plugin else []
+ return codegen.load(model_args, pre_load=_save_weights,
post_load=_bind_weights)
diff --git a/python/tvm/contrib/msc/framework/tvm/codegen/codegen.py
b/python/tvm/contrib/msc/framework/tvm/codegen/codegen.py
index c344b92606..4038b74b7e 100644
--- a/python/tvm/contrib/msc/framework/tvm/codegen/codegen.py
+++ b/python/tvm/contrib/msc/framework/tvm/codegen/codegen.py
@@ -16,7 +16,7 @@
# under the License.
"""tvm.contrib.msc.framework.tvm.codegen.codegen"""
-from typing import Dict, Optional
+from typing import Dict, Optional, Any
import tvm
from tvm.relax.transform import BindParams
@@ -32,6 +32,7 @@ def to_relax(
codegen_config: Optional[Dict[str, str]] = None,
print_config: Optional[Dict[str, str]] = None,
build_folder: msc_utils.MSCDirectory = None,
+ plugin: Any = None,
) -> tvm.IRModule:
"""Change MSCGraph to IRModule.
@@ -47,6 +48,8 @@ def to_relax(
The config for print.
build_folder: MSCDirectory
The folder for saving scripts and datas.
+ plugin: PluginManager
+ The plugin manager.
Returns
-------
@@ -81,4 +84,7 @@ def to_relax(
)(mod)
codegen = CodeGen(graph, _ffi_api.GetRelaxSources, codegen_config,
print_config, build_folder)
- return codegen.load(inputs, pre_load=_save_weights, post_load=_post_proc)
+ model_args = inputs
+ if plugin:
+ model_args = model_args + [plugin]
+ return codegen.load(model_args, pre_load=_save_weights,
post_load=_post_proc)
diff --git a/python/tvm/contrib/msc/pipeline/manager.py
b/python/tvm/contrib/msc/pipeline/manager.py
index a8327a08cd..42ef227b55 100644
--- a/python/tvm/contrib/msc/pipeline/manager.py
+++ b/python/tvm/contrib/msc/pipeline/manager.py
@@ -32,6 +32,8 @@ from tvm.contrib.msc.core.utils.namespace import
MSCFramework, MSCMap, MSCKey
from tvm.contrib.msc.core.utils.message import MSCStage
from tvm.contrib.msc.core import utils as msc_utils
from tvm.contrib.msc.core.gym.control import create_controller
+from tvm.contrib.msc.core import _ffi_api
+from tvm.contrib.msc.plugin.utils import load_plugins
class BaseManager(object):
@@ -43,9 +45,25 @@ class BaseManager(object):
The raw model in framwork.
config: dict
The config for pipeline.
+ plugins: dict
+ The plugins for pipeline.
+ root: str
+ The root path for files.
"""
- def __init__(self, model: Any, config: dict):
+ def __init__(self, model: Any, config: dict, plugins: dict = None, root:
str = None):
+ # change path to root path
+ if root:
+
+ def _from_root_mark(val):
+ if root and isinstance(val, str) and MSCKey.ROOT_MARK in val:
+ return val.replace(MSCKey.ROOT_MARK, root)
+ return val
+
+ model = _from_root_mark(model)
+ config = msc_utils.map_dict(config, _from_root_mark)
+ plugins = msc_utils.map_dict(plugins, _from_root_mark)
+
# check stage
for stage in ["inputs", "outputs", "dataset", MSCStage.PREPARE,
MSCStage.COMPILE]:
assert stage in config, "{} should be given to run the
pipeline".format(stage)
@@ -55,6 +73,10 @@ class BaseManager(object):
self._model, self._device, self._training = self._get_runner_cls(
self._model_type
).load_native(model)
+ if plugins:
+ self._plugins = load_plugins(plugins)
+ else:
+ self._plugins = {}
use_cache = config.get("use_cache", True)
self._workspace = msc_utils.set_workspace(config.get("workspace"),
use_cache)
self._verbose = config.get("verbose", "info")
@@ -87,6 +109,12 @@ class BaseManager(object):
self._meta_config = config
self._optimize_type = config.get(MSCStage.OPTIMIZE,
{}).get("run_type", self._model_type)
self._compile_type = config.get(MSCStage.COMPILE, {}).get("run_type",
self._model_type)
+ # register plugins
+ if self._plugins:
+ for t in [self._model_type, self._optimize_type,
self._compile_type]:
+ assert t in self._plugins, "Missing plugin for {}".format(t)
+ for name, plugin in
self._plugins[self._model_type].get_ops_info().items():
+ _ffi_api.RegisterPlugin(name, msc_utils.dump_dict(plugin))
self._config, self._debug_levels = self.update_config(config)
self._tools_config = {}
self._relax_mod, self._runner = None, None
@@ -100,7 +128,7 @@ class BaseManager(object):
"duration": {},
"profile": {},
}
- return {"workspace": self._workspace.path, "config": config}
+ return {"workspace": self._workspace.path, "plugins": self._plugins,
"config": config}
def update_config(self, config: dict) -> dict:
"""Update config
@@ -300,20 +328,22 @@ class BaseManager(object):
self._logger.info("Load parsed mod from %s", cache_path)
else:
parse_config =
msc_utils.copy_dict(stage_config.get("parse_config", {}))
- runner_cls =
self._get_runner_cls(self._config[MSCStage.COMPILE]["run_type"])
- trans_func = (
- runner_cls.target_transform if hasattr(runner_cls,
"target_transform") else None
- )
- parse_info = {
- "parser": stage_config["parser"],
- "config": parse_config,
- "trans_func": trans_func,
- }
+ parse_info = {"parser": stage_config["parser"], "config":
parse_config}
self._logger.info(msc_utils.msg_block("PARSE", parse_info))
parse_config["as_msc"] = False
+ if self._model_type in self._plugins:
+ plugin = self._plugins[self._model_type]
+ parse_config["custom_convert_map"] = plugin.get_convert_map()
self._relax_mod, _ = stage_config["parser"](self._model,
**parse_config)
- if trans_func:
- self._relax_mod = trans_func(self._relax_mod)
+ for stage in [MSCStage.OPTIMIZE, MSCStage.COMPILE]:
+ if stage not in self._config:
+ continue
+ runner_cls =
self._get_runner_cls(self._config[stage]["run_type"])
+ if hasattr(runner_cls, "target_transform"):
+ self._logger.info(
+ "Transform for stage %s: %s", stage,
runner_cls.target_transform
+ )
+ self._relax_mod =
runner_cls.target_transform(self._relax_mod)
self._relax_mod = msc_transform.SetExprName()(self._relax_mod)
if cache_path:
with open(cache_path, "w") as f:
@@ -498,6 +528,7 @@ class BaseManager(object):
runner = runner_cls(
self._relax_mod,
tools_config=tools_config,
+ plugin=self._plugins.get(stage_config["run_type"]),
stage=stage,
logger=self._logger,
**run_config,
@@ -534,6 +565,10 @@ class BaseManager(object):
assert tool_type in stage_config, "Can not find config for tool " +
str(tool_type)
tool_stage, tool_config = self._get_tool_stage(tool_type),
stage_config[tool_type]
+ if "run_type" in tool_config:
+ run_type = tool_config.pop("run_type")
+ else:
+ run_type = stage_config["run_type"]
plan_file = tool_config["plan_file"]
if "gym_configs" in tool_config:
gym_configs = tool_config.pop("gym_configs")
@@ -548,10 +583,7 @@ class BaseManager(object):
self._logger.info("Skip %s with plan %s", tool_type, plan_file)
return plan_file
msc_utils.time_stamp(tool_stage)
- t_stage_config = {
- "run_type": stage_config["run_type"],
- "run_config": stage_config["run_config"],
- }
+ t_stage_config = {"run_type": run_type, "run_config":
stage_config["run_config"]}
runner = self._create_runner(
tool_stage, t_stage_config, tools_config=tools_config,
profile=False, use_cache=False
)
diff --git a/src/contrib/msc/core/codegen/base_codegen.h
b/src/contrib/msc/core/codegen/base_codegen.h
index 0b5756df7e..19d8b524b9 100644
--- a/src/contrib/msc/core/codegen/base_codegen.h
+++ b/src/contrib/msc/core/codegen/base_codegen.h
@@ -33,6 +33,7 @@
#include <vector>
#include "../ir/graph.h"
+#include "../ir/plugin.h"
#include "code_stack.h"
#include "codegen_utils.h"
@@ -81,6 +82,36 @@ class BaseOpCode {
return IdxWeightBase(node_, wtype, process);
}
+ /*! \brief Get the node attr as doc*/
+ const ExprDoc GetAttrDoc(const String& key, const String& type) {
+ if (StringUtils::StartsWith(type, "list")) {
+ const String& ele_type =
+ StringUtils::Replace(StringUtils::Replace(type, "list(", ""), ")",
"");
+ if (ele_type == "bool") {
+ return DocUtils::ToList(node_->GetTypeArrayAttr<bool>(key));
+ } else if (ele_type == "int" || ele_type == "int32") {
+ return DocUtils::ToList(node_->GetTypeArrayAttr<int>(key));
+ } else if (ele_type == "long" || ele_type == "int64") {
+ return DocUtils::ToList(node_->GetTypeArrayAttr<int64_t>(key));
+ } else if (ele_type == "float" || ele_type == "float32") {
+ return DocUtils::ToList(node_->GetTypeArrayAttr<float>(key));
+ } else if (ele_type == "string") {
+ return DocUtils::ToStrList(node_->GetTypeArrayAttr<std::string>(key));
+ }
+ } else if (type == "bool") {
+ return DocUtils::ToDoc(node_->GetTypeAttr<bool>(key));
+ } else if (type == "int" || type == "int32") {
+ return DocUtils::ToDoc(node_->GetTypeAttr<int>(key));
+ } else if (type == "long" || type == "int64") {
+ return DocUtils::ToDoc(node_->GetTypeAttr<int64_t>(key));
+ } else if (type == "float" || type == "float32") {
+ return DocUtils::ToDoc(node_->GetTypeAttr<float>(key));
+ } else if (type == "string") {
+ return DocUtils::ToStr(node_->GetTypeAttr<std::string>(key));
+ }
+ return DocUtils::ToDoc(node_->GetTypeAttr<std::string>(key));
+ }
+
/*! \brief Get comment for default node*/
const String Comment() { return Comment(node_); }
@@ -169,6 +200,14 @@ class BaseCodeGen {
}
}
+ /*! \brief Get the optype for op codegen*/
+ const String GetOpType(const MSCJoint& node) {
+ if (config_->use_plugin && IsPlugin(node->optype)) {
+ return "plugin";
+ }
+ return node->optype;
+ }
+
/*! \brief Get the docs for the op*/
virtual const Array<Doc> GetOpCodes(const MSCJoint& node) = 0;
diff --git a/src/contrib/msc/core/transform/set_expr_layout.cc
b/src/contrib/msc/core/transform/set_expr_layout.cc
index affb653a23..0ece7a51ca 100644
--- a/src/contrib/msc/core/transform/set_expr_layout.cc
+++ b/src/contrib/msc/core/transform/set_expr_layout.cc
@@ -509,6 +509,21 @@ InferLayoutOutput ForwardInferLayoutTake(const Call& call,
return InferLayoutOutput({LayoutDecision("WE"), input_layout},
{output_layout}, Attrs());
}
+InferLayoutOutput ForwardInferLayoutPlugin(const Call& call,
+ const Map<String, Array<String>>&
desired_layouts,
+ const VarLayoutMap& var_layout_map)
{
+ if (!call->args[0]->IsInstance<ExternFuncNode>()) {
+ return InferLayoutOutput();
+ }
+ const auto& name = Downcast<ExternFunc>(call->args[0])->global_symbol;
+ const auto* pf = runtime::Registry::Get("msc.plugin.op.InferLayout" + name);
+ if (pf == nullptr) {
+ return InferLayoutOutput();
+ }
+ const auto& args = Downcast<Tuple>(call->args[1]);
+ return (*pf)(args->fields, var_layout_map);
+}
+
TVM_REGISTER_OP("relax.nn.conv1d")
.set_attr<FRelaxInferLayout>("FMSCForwardInferLayout", MSCInferLayoutConv);
TVM_REGISTER_OP("relax.nn.conv2d")
@@ -603,6 +618,10 @@ TVM_REGISTER_OP("relax.nn.group_norm")
TVM_REGISTER_OP("relax.nn.layer_norm")
.set_attr<FRelaxInferLayout>("FMSCForwardInferLayout",
ForwardInferLayoutNormalize);
+// plugin op
+TVM_REGISTER_OP("relax.call_dps_packed")
+ .set_attr<FRelaxInferLayout>("FMSCForwardInferLayout",
ForwardInferLayoutPlugin);
+
// Backward Infer
InferLayoutOutput BackwardInferLayoutCommon(const Call& call,
const Map<String, Array<String>>&
desired_layouts,
diff --git a/src/contrib/msc/framework/tensorrt/codegen.cc
b/src/contrib/msc/framework/tensorrt/codegen.cc
index 13c231092a..717eb75e1f 100644
--- a/src/contrib/msc/framework/tensorrt/codegen.cc
+++ b/src/contrib/msc/framework/tensorrt/codegen.cc
@@ -27,6 +27,8 @@
#include <tvm/ir/module.h>
#include <tvm/relax/expr.h>
+#include <set>
+
#include "../../core/codegen/codegen_json.h"
namespace tvm {
@@ -43,6 +45,17 @@ void TensorRTCodeGen::CodeGenClassDeclare() {
if (config()->precision == "int8") {
stack_.line("#include \"utils/trt_quantize.h\"");
}
+ // plugin headers
+ if (config()->use_plugin) {
+ std::set<String> plugins;
+ for (const auto& n : graph()->node_names) {
+ const auto& node = graph()->FindNode(n);
+ if (IsPlugin(node->optype) && !plugins.count(node->optype)) {
+ stack_.line("#include \"plugin/" + node->optype + "_op.h\"");
+ plugins.insert(node->optype);
+ }
+ }
+ }
stack_.line().line("using namespace nvinfer1;").line();
StartNamespace();
// start class declare
@@ -439,6 +452,7 @@ void TensorRTCodeGen::CodeGenCmake() {
stack_.line("cmake_minimum_required(VERSION " + config()->cmake_version + "
FATAL_ERROR)")
.line("project(" + graph()->name + ")")
.line("find_package(CUDA)")
+ .line()
.line("find_path(TRT_INCLUDE_DIR NvInfer.h HINTS " +
config()->tensorrt_root +
" PATH_SUFFIXES include)")
.line("find_library(TRT_LIBS nvinfer HINTS " + config()->tensorrt_root +
@@ -447,13 +461,23 @@ void TensorRTCodeGen::CodeGenCmake() {
"message(STATUS \"Build project with TRT_INCLUDE_DIR
${TRT_INCLUDE_DIR} and "
"TRT_LIBS "
"${TRT_LIBS}\")")
+ .line()
.line("add_definitions(-DTRT_MAJOR=" +
std::to_string(config()->version[0]) + ")")
.line("add_definitions(-DTRT_MINOR=" +
std::to_string(config()->version[1]) + ")")
.line("add_definitions(-DTRT_PATCH=" +
std::to_string(config()->version[2]) + ")")
- .line("file(GLOB_RECURSE TRT_SRCS *.cc)")
+ .line();
+ if (config()->use_plugin) {
+ stack_.line("add_definitions(-DPLUGIN_SUPPORT_TENSORRT)").line();
+ }
+ String link_libs = " ${TRT_LIBS}";
+ if (config()->extern_libs.size() > 0) {
+ stack_.line("set(EXTERN_LIBS " + StringUtils::Join(config()->extern_libs,
" ") + ")");
+ link_libs = link_libs + " ${EXTERN_LIBS}";
+ }
+ stack_.line("file(GLOB_RECURSE TRT_SRCS *.cc)")
.line("cuda_add_executable(" + graph()->name + " ${TRT_SRCS})")
.line("target_include_directories(" + graph()->name + " PUBLIC
${TRT_INCLUDE_DIR})")
- .line("target_link_libraries(" + graph()->name + " ${TRT_LIBS})");
+ .line("target_link_libraries(" + graph()->name + link_libs + ")");
}
const String TensorRTCodeGen::IdxTensor(const MSCTensor& tensor) {
@@ -518,7 +542,7 @@ const String TensorRTCodeGen::ToDims(const Array<Integer>&
dims, bool use_ndim)
const Array<Doc> TensorRTCodeGen::GetOpCodes(const MSCJoint& node) {
const auto& ops_map = GetTensorRTOpCodes();
- auto it = ops_map->find(node->optype);
+ auto it = ops_map->find(GetOpType(node));
ICHECK(it != ops_map->end()) << "Unsupported tensorrt op(" << node->optype
<< "): " << node;
it->second->Config(node, config());
try {
diff --git a/src/contrib/msc/framework/tensorrt/codegen_utils.h
b/src/contrib/msc/framework/tensorrt/codegen_utils.h
index bfaecb8d3d..f006b21b81 100644
--- a/src/contrib/msc/framework/tensorrt/codegen_utils.h
+++ b/src/contrib/msc/framework/tensorrt/codegen_utils.h
@@ -25,6 +25,7 @@
#define TVM_CONTRIB_MSC_FRAMEWORK_TENSORRT_CODEGEN_UTILS_H_
#include <string>
+#include <vector>
#include "../../core/codegen/base_codegen.h"
#include "../../core/codegen/codegen_utils.h"
@@ -89,6 +90,7 @@ struct TensorRTCodeGenConfig {
std::string precision{"float32"};
std::string precision_mode{"strict"};
std::string tensorrt_root{"/usr/local/cuda"};
+ std::vector<std::string> extern_libs;
CODEGEN_CONFIG_MEMBERS
void Load(dmlc::JSONReader* reader) {
std::string key;
@@ -114,6 +116,8 @@ struct TensorRTCodeGenConfig {
reader->Read(&precision_mode);
} else if (key == "tensorrt_root") {
reader->Read(&tensorrt_root);
+ } else if (key == "extern_libs") {
+ reader->Read(&extern_libs);
} else {
CODEGEN_CONFIG_PARSE
}
diff --git a/src/contrib/msc/framework/tensorrt/tensorrt_opcode.cc
b/src/contrib/msc/framework/tensorrt/tensorrt_opcode.cc
index 2cacd11907..a080fdd778 100644
--- a/src/contrib/msc/framework/tensorrt/tensorrt_opcode.cc
+++ b/src/contrib/msc/framework/tensorrt/tensorrt_opcode.cc
@@ -73,15 +73,15 @@ const String TensorRTOpCode::DeclareInputs(bool simplify) {
const auto& idx_input = StringUtils::Replace(IdxInput(), "*", "");
stack_.declare("std::vector<ITensor*>", inputs_ref + "_vec")
.declare_arg(node()->inputs.size())
- .declare_arg(idx_input)
- .assign(inputs_ref, inputs_ref + "_vec.data()", "ITensor**");
+ .declare_arg(idx_input);
} else {
- stack_.declare("std::vector<ITensor*>", IdxNode(), 0, false);
+ stack_.declare("std::vector<ITensor*>", inputs_ref + "_vec", 0, false);
for (size_t i = 0; i < node()->inputs.size(); i++) {
const auto& idx_input = StringUtils::Replace(IdxInput(i), "*", "");
stack_.declare_arg(idx_input);
}
}
+ stack_.assign(inputs_ref, inputs_ref + "_vec.data()", "ITensor**");
return inputs_ref;
}
@@ -298,10 +298,7 @@ class TensorRTConcatCodeGen : public TensorRTOpCode {
const auto& producer = node()->ProducerOf(0);
ICHECK(node()->parents.size() == 1 && producer->optype == "tuple")
<< "Concat expect parent as tuple, get " << node();
- stack_.op_call()
- .inplace_start("data", "", IdxNodeBase(producer))
- .inplace_end()
- .call_arg(producer->inputs.size());
+
stack_.op_call().call_arg(IdxNodeBase(producer)).call_arg(producer->inputs.size());
SetLayerByValue("Axis", AttrToAxis());
}
};
@@ -679,11 +676,8 @@ class TensorRTTupleCodeGen : public TensorRTOpCode {
protected:
void CodeGenBuild() final {
- stack_.declare("std::vector<ITensor*>", IdxNode(), 0, false);
- for (size_t i = 0; i < node()->inputs.size(); i++) {
- const auto& idx_input = StringUtils::Replace(IdxInput(i), "*", "");
- stack_.declare_arg(idx_input);
- }
+ const auto& inputs_ref = DeclareInputs();
+ stack_.assign(IdxNode(), inputs_ref, "auto");
}
};
@@ -710,6 +704,35 @@ class TensorRTWhereCodeGen : public TensorRTOpCode {
void CodeGenBuild() final { stack_.op_call().op_inputs_arg(false); }
};
+class TensorRTPluginOpCodeGen : public TensorRTOpCode {
+ public:
+ TENSORRT_OP_CODEGEN_METHODS(TensorRTPluginOpCodeGen)
+
+ protected:
+ void CodeGenBuild() final {
+ const auto& producer = node()->ParentAt(0);
+ ICHECK(producer->optype == "tuple")
+ << "Only support tensorrt plugin with tuple, get " << producer;
+
+ const auto& plugin = GetPlugin(node()->optype);
+ const auto& input_ref = "inputs_" + std::to_string(producer->index);
+ const String& func_name = "plugin::" + node()->optype + "DynamicPlugin";
+ const String& plugin_ref = "plugin_" + std::to_string(node()->index);
+ const String& layouts_ref = "layouts_" + std::to_string(node()->index);
+ stack_.declare("std::vector<std::string>", layouts_ref, 0, false);
+ for (const auto& i : node()->GetInputs()) {
+ stack_.declare_arg(DocUtils::ToStr(i->layout.name()));
+ }
+ stack_.func_call(func_name, DocUtils::ToDeclare("auto", plugin_ref))
+ .call_arg(DocUtils::ToStr(node()->name));
+ for (const auto& a : plugin->attrs) {
+ stack_.call_arg(GetAttrDoc(a->name, a->type));
+ }
+ stack_.call_arg(layouts_ref);
+
stack_.op_call().call_arg(input_ref).call_arg(plugin->inputs.size()).call_arg(plugin_ref);
+ }
+};
+
const std::shared_ptr<std::unordered_map<String,
std::shared_ptr<TensorRTOpCode>>>
GetTensorRTOpCodes() {
static auto map = std::make_shared<std::unordered_map<String,
std::shared_ptr<TensorRTOpCode>>>();
@@ -796,16 +819,15 @@ GetTensorRTOpCodes() {
// special op
map->emplace("input", std::make_shared<TensorRTInputCodeGen>("Input"));
+ map->emplace("get_item", std::make_shared<TensorRTGetItemCodeGen>(""));
+ map->emplace("tuple", std::make_shared<TensorRTTupleCodeGen>(""));
+ map->emplace("plugin",
std::make_shared<TensorRTPluginOpCodeGen>("PluginV2"));
// msc ops
map->emplace("msc.conv2d_bias",
std::make_shared<TensorRTConvCodeGen>("ConvolutionNd", true));
map->emplace("msc.linear",
std::make_shared<TensorRTLinearCodeGen>("FullyConnected", false));
map->emplace("msc.linear_bias",
std::make_shared<TensorRTLinearCodeGen>("FullyConnected", true));
- // special op
- map->emplace("get_item", std::make_shared<TensorRTGetItemCodeGen>(""));
- map->emplace("tuple", std::make_shared<TensorRTTupleCodeGen>(""));
-
return map;
}
diff --git a/src/contrib/msc/framework/torch/codegen.cc
b/src/contrib/msc/framework/torch/codegen.cc
index 012f0311b2..54859ad0ce 100644
--- a/src/contrib/msc/framework/torch/codegen.cc
+++ b/src/contrib/msc/framework/torch/codegen.cc
@@ -44,8 +44,14 @@ void TorchCodeGen::CodeGenGraph() {
stack_.func_decorator("msc_tools.wrap_step(\"build\",\"" +
config()->tools_tag + "\")");
}
stack_.func_arg("self", "torch.nn.Module");
- stack_.func_start();
-
stack_.func_call("super").call_arg(graph()->name).call_arg("self").method_call("__init__");
+ if (config()->use_plugin) {
+ stack_.func_arg("plugin", "Any");
+ }
+ stack_.func_start()
+ .func_call("super")
+ .call_arg(graph()->name)
+ .call_arg("self")
+ .method_call("__init__");
for (const auto& n : graph()->node_names) {
const auto& node = graph()->FindNode(n);
if (node->optype == "input") {
@@ -99,9 +105,17 @@ void TorchCodeGen::CodeGenGraph() {
}
void TorchCodeGen::CodeGenInference() {
- stack_.comment("Build Model")
- .func_call(graph()->name, "model")
- .comment("Load weights")
+ if (config()->use_plugin) {
+ stack_.comment("Import Plugin")
+ .line("from msc_plugin.torch import PluginManager")
+ .line()
+ .func_call("PluginManager", "plugin");
+ }
+ stack_.comment("Build Model").func_call(graph()->name, "model");
+ if (config()->use_plugin) {
+ stack_.call_arg("plugin");
+ }
+ stack_.comment("Load weights")
.func_call("torch.load", "weights")
.call_arg(DocUtils::ToStr(graph()->name + ".pth"))
.func_call("load_state_dict", "", "model")
@@ -126,7 +140,7 @@ void TorchCodeGen::CodeGenInference() {
const Array<Doc> TorchCodeGen::GetOpCodes(const MSCJoint& node) {
const auto& ops_map = GetTorchOpCodes();
- auto it = ops_map->find(node->optype);
+ auto it = ops_map->find(GetOpType(node));
ICHECK(it != ops_map->end()) << "Unsupported torch op(" << node->optype <<
"): " << node;
it->second->Config(node, config(), is_init_);
try {
diff --git a/src/contrib/msc/framework/torch/torch_opcode.cc
b/src/contrib/msc/framework/torch/torch_opcode.cc
index 5086678758..59d30e7740 100644
--- a/src/contrib/msc/framework/torch/torch_opcode.cc
+++ b/src/contrib/msc/framework/torch/torch_opcode.cc
@@ -223,7 +223,13 @@ class TorchConstantCodeGen : public TorchOpCode {
}
}
- void CodeGenForward() final { stack_.assign(IdxNode(), module_ref()); }
+ void CodeGenForward() final {
+ if (config()->use_tools) {
+ stack_.assign(IdxNode(), IdxWeight("const", true));
+ } else {
+ stack_.assign(IdxNode(), module_ref());
+ }
+ }
};
class TorchConvCodeGen : public TorchOpCode {
@@ -510,7 +516,7 @@ class TorchReshapeCodeGen : public TorchOpCode {
const auto& out_layout = node()->OutputAt(0)->layout;
if (out_layout.defined()) {
int32_t batch_dim = out_layout.IndexOf(tvm::tir::LayoutAxis::Get("N"));
- if (batch_dim > 0) {
+ if (batch_dim >= 0) {
shape.Set(batch_dim, Integer(-1));
}
}
@@ -608,6 +614,21 @@ class TorchTupleCodeGen : public TorchOpCode {
void CodeGenForward() final { stack_.op_call().op_inputs_arg(); }
};
+class TorchPluginOpCodeGen : public TorchOpCode {
+ TORCH_OP_CODEGEN_METHODS(TorchPluginOpCodeGen)
+
+ protected:
+ void CodeGenInit() final {
+ const auto& plugin = GetPlugin(node()->optype);
+ stack_.op_call("plugin." + node()->optype);
+ for (const auto& a : plugin->attrs) {
+ stack_.call_arg(GetAttrDoc(a->name, a->type), a->name);
+ }
+ }
+
+ void CodeGenForward() final { stack_.op_call().op_inputs_arg(false); }
+};
+
const std::shared_ptr<std::unordered_map<String,
std::shared_ptr<TorchOpCode>>> GetTorchOpCodes() {
static auto map = std::make_shared<std::unordered_map<String,
std::shared_ptr<TorchOpCode>>>();
if (!map->empty()) return map;
@@ -728,6 +749,7 @@ const std::shared_ptr<std::unordered_map<String,
std::shared_ptr<TorchOpCode>>>
map->emplace("get_item", std::make_shared<TorchGetItemCodeGen>("", ""));
map->emplace("shape", std::make_shared<TorchShapeCodeGen>("", "torch.Size"));
map->emplace("tuple", std::make_shared<TorchTupleCodeGen>("", "tuple"));
+ map->emplace("plugin", std::make_shared<TorchPluginOpCodeGen>("Plugin", ""));
// msc ops
map->emplace("msc.attention", std::make_shared<TorchAttentionCodeGen>(
@@ -743,7 +765,6 @@ const std::shared_ptr<std::unordered_map<String,
std::shared_ptr<TorchOpCode>>>
std::make_shared<TorchLinearCodeGen>("nn.Linear",
"functional.linear", false));
map->emplace("msc.linear_bias",
std::make_shared<TorchLinearCodeGen>("nn.Linear",
"functional.linear", true));
-
return map;
}
diff --git a/src/contrib/msc/framework/tvm/codegen.cc
b/src/contrib/msc/framework/tvm/codegen.cc
index 20c47d9291..783551eed3 100644
--- a/src/contrib/msc/framework/tvm/codegen.cc
+++ b/src/contrib/msc/framework/tvm/codegen.cc
@@ -40,6 +40,9 @@ void RelaxCodeGen::CodeGenGraph() {
stack_.func_arg(idx_input, "relax.Var");
idx_inputs.push_back(idx_input);
}
+ if (config()->use_plugin) {
+ stack_.func_arg("plugin", "Any");
+ }
stack_.func_start().assign("inputs", DocUtils::ToList(idx_inputs, true));
// define weights
stack_.comment("Define the weights");
@@ -123,6 +126,12 @@ void RelaxCodeGen::CodeGenGraph() {
}
void RelaxCodeGen::CodeGenInference() {
+ if (config()->use_plugin) {
+ stack_.comment("Import Plugin")
+ .line("from msc_plugin.tvm import PluginManager")
+ .line()
+ .func_call("PluginManager", "plugin");
+ }
for (const auto& i : graph()->GetInputs()) {
const auto& producer = graph()->FindProducer(i);
stack_.func_call("relax.Var", IdxNodeBase(producer))
@@ -133,6 +142,9 @@ void RelaxCodeGen::CodeGenInference() {
.pop_nest();
}
stack_.comment("Build Module").func_call(graph()->name, "mod");
+ if (config()->use_plugin) {
+ stack_.call_arg("plugin");
+ }
for (const auto& i : graph()->GetInputs()) {
const auto& producer = graph()->FindProducer(i);
stack_.call_arg(IdxNodeBase(producer));
@@ -177,7 +189,7 @@ void RelaxCodeGen::CodeGenInference() {
const Array<Doc> RelaxCodeGen::GetOpCodes(const MSCJoint& node) {
const auto& ops_map = GetRelaxOpCodes();
- auto it = ops_map->find(node->optype);
+ auto it = ops_map->find(GetOpType(node));
ICHECK(it != ops_map->end()) << "Unsupported relax op(" << node->optype <<
"): " << node;
it->second->Config(node, config());
try {
diff --git a/src/contrib/msc/framework/tvm/relax_opcode.cc
b/src/contrib/msc/framework/tvm/relax_opcode.cc
index 16b78193ae..0b7ef6aa82 100644
--- a/src/contrib/msc/framework/tvm/relax_opcode.cc
+++ b/src/contrib/msc/framework/tvm/relax_opcode.cc
@@ -668,6 +668,19 @@ class RelaxTriCodeGen : public RelaxOpCode {
}
};
+class RelaxPluginOpCodeGen : public RelaxOpCode {
+ RELAX_OP_CODEGEN_METHODS(RelaxPluginOpCodeGen)
+
+ protected:
+ void CodeGenBuild() final {
+ const auto& plugin = GetPlugin(node()->optype);
+ stack_.op_call("plugin." + node()->optype).op_inputs_arg(false);
+ for (const auto& a : plugin->attrs) {
+ stack_.call_arg(GetAttrDoc(a->name, a->type), a->name);
+ }
+ }
+};
+
const std::shared_ptr<std::unordered_map<String,
std::shared_ptr<RelaxOpCode>>> GetRelaxOpCodes() {
static auto map = std::make_shared<std::unordered_map<String,
std::shared_ptr<RelaxOpCode>>>();
if (!map->empty()) return map;
@@ -798,6 +811,7 @@ const std::shared_ptr<std::unordered_map<String,
std::shared_ptr<RelaxOpCode>>>
map->emplace("get_item",
std::make_shared<RelaxGetItemCodeGen>("relax.TupleGetItem"));
map->emplace("shape",
std::make_shared<RelaxShapeCodeGen>("relax.ShapeExpr"));
map->emplace("tuple", std::make_shared<RelaxTupleCodeGen>("relax.Tuple"));
+ map->emplace("plugin", std::make_shared<RelaxPluginOpCodeGen>("Plugin"));
// msc ops
map->emplace("msc.attention",
std::make_shared<RelaxAttentionCodeGen>("relax.op.nn.attention"));