1 FunctionPass
Pass FoldConstant() {
runtime::TypedPackedFunc<Function(Function, Module, PassContext)> pass_func =
[=](Function f, Module m, PassContext pc) {
return Downcast<Function>(FoldConstant(f, m));
};
return CreateFunctionPass(pass_func, 2, "FoldConstant", {});
}
TVM_REGISTER_API("relay._transform.FoldConstant")
.set_body_typed(FoldConstant);
说明:CreateFunctionPass(pass_func, 2, “FoldConstant”, {});中的第2个参数2,表示该Pass的优化等级是2。
那么,这个优化等级有什么用呢?在用户提供的优化级别下运行时,帮助Pass基础结构识别是否需要执行某个Pass。假设用户指定的优化级别是2,那么所有优化级别小于或等于2的Pass都执行,大于2的Pass都不执行。
# only the passes that have optimization level less or equal to 2 will be executed
with _transform.PassContext(opt_level=2,
required_pass=["QuantizeAnnotate",
"QuantizeCalibrate",
"QuantizeRealize"]):
with quantize_context():
mod = quantize_seq(mod)
上面的例子是执行连续的Pass,所有优化级别小于或等于2的都执行,大于2的不执行。
opt_level = 3
target = tvm.target.cuda()
with relay.build_config(opt_level=opt_level):
graph, lib, params = relay.build_module.build(
mod, target, params=params)
上面的例子是在relay.build时,表示所有优化级别小于或等于3的都执行,大于3的不执行。
build_config其实也是调用了PassContext,代码如下:
@register_relay_node
class PassContext(RelayNode):
"""The basis where a Relay optimization/analysis runs on.
Each pass context contains a number of auxiliary information that is used
to help an optimization pass. Such information includes the error reporter
to record the errors of during the optimization, etc.
opt_level : Optional[int]
The optimization level of this pass.
fallback_device : Optional[Union[int, str, TVMContext]]
The fallback device type. It is also used as the default device for
operators that are not annotated during heterogeneous execution.
required_pass : Optional[Union[List[str], Set[str], Tuple[str]]]
The list of passes that are required by a certain pass.
disabled_pass : Optional[Union[List[str], Set[str], Tuple[str]]]
The list of passes that are disabled.
force_transform_avgpool2d : Optional[Bool]
The flag indicated whether force transform avgpool2d to conv2d in VaccTransformAvgPool pass.
ksize_global_avgpool2d_transform : Optional[int]
The kernel type we used to decompose large global avgpool2d.
svd_topn_percent : Optional[int]
svd_topn_percent = sum(TopN singular values) / sum(All singular values).
"""
def __init__(self,
opt_level=2,
fallback_device=_nd.cpu(),
required_pass=None,
disabled_pass=None,
force_transform_avgpool2d=True,
ksize_global_avgpool2d_transform=0,
svd_topn_percent = 100):
if isinstance(fallback_device, str):
fallback_device = _nd.context(fallback_device).device_type
elif isinstance(fallback_device, TVMContext):
fallback_device = fallback_device.device_type
if not isinstance(fallback_device, int):
raise TypeError("required_pass is expected to be the type of " +
"int/str/TVMContext.")
required = list(required_pass) if required_pass else []
if not isinstance(required, (list, tuple)):
raise TypeError("required_pass is expected to be the type of " +
"list/tuple/set.")
disabled = list(disabled_pass) if disabled_pass else []
if not isinstance(disabled, (list, tuple)):
raise TypeError("disabled_pass is expected to be the type of " +
"list/tuple/set.")
if not (svd_topn_percent <= 100 and svd_topn_percent > 0):
raise TypeError("svd_top_n_weight is expected to be in (0, 100].")
self.__init_handle_by_constructor__(_transform.PassContext, opt_level,
fallback_device, required,
disabled, force_transform_avgpool2d,
ksize_global_avgpool2d_transform,
svd_topn_percent)
def __enter__(self):
_transform.EnterPassContext(self)
return self
def __exit__(self, ptype, value, trace):
_transform.ExitPassContext(self)
@staticmethod
def current():
"""Return the current pass context."""
return _transform.GetCurrentPassContext()
def build_config(opt_level=2,
fallback_device=_nd.cpu(),
required_pass=None,
disabled_pass=None,
force_transform_avgpool2d=True,
ksize_global_avgpool2d_transform=0,
svd_topn_percent = 100):
"""Configure the build behavior by setting config variables.
Parameters
----------
opt_level: int, optional
Optimization level. The optimization pass name and level are as the
following:
.. code-block:: python
OPT_PASS_LEVEL = {
"SimplifyInference": 0,
"OpFusion": 1,
"FoldConstant": 2,
"FoldScaleAxis": 3,
"AlterOpLayout": 3,
"CanonicalizeOps": 3,
"CanonicalizeCast": 3,
"EliminateCommonSubexpr": 3,
"CombineParallelConv2D": 4,
"CombineParallelDense": 4
}
fallback_device : int, str, or tvm.TVMContext, optional
The fallback device. It is also used as the default device for
operators without specified device during heterogeneous execution.
required_pass: set of str, optional
Optimization passes that are required regardless of optimization level.
disabled_pass: set of str, optional
Optimization passes to be disabled during optimization.
force_transform_avgpool2d : bool, optional
The flag indicated whether force transform avgpool2d to conv2d in VaccTransformAvgPool pass.
The initial purpose of adding this flag is to support transform avgpool2d in inception_v3 model in Keras and ONNX.
If enabled, VaccTransformAvgPool pass will ignore the count_include_pad check and treat count_include_pad false
as true. The accuracy loss caused by this approximate convert is little through Table 60 in spec.
If disabled, VaccTransformAvgPool pass will do count_include_pad check and reject when check failed.
ksize_global_avgpool2d_transform : int, optional
The kernel type we used to decompose large global avgpool2d.
We provide 2 options to choose: 0 represents 3x3 s2; 1 represents 5x5 s4.
As our hardware do better support for 3x3 kernel, so we choose 3x3 s2 as default.
svd_topn_percent : int, optional
svd_topn_percent% = sum(TopN singular values) / sum(All singular values).
Returns
-------
pass_context: PassContext
The pass context for optimizations.
"""
return PassContext(opt_level, fallback_device, required_pass,
disabled_pass, force_transform_avgpool2d,
ksize_global_avgpool2d_transform, svd_topn_percent)