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 executedwith _transform.PassContext(opt_level=2,required_pass=["QuantizeAnnotate","QuantizeCalibrate","QuantizeRealize"]):with quantize_context():mod = quantize_seq(mod)
上面的例子是执行连续的Pass,所有优化级别小于或等于2的都执行,大于2的不执行。
opt_level = 3target = 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_nodeclass PassContext(RelayNode):"""The basis where a Relay optimization/analysis runs on.Each pass context contains a number of auxiliary information that is usedto help an optimization pass. Such information includes the error reporterto 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 foroperators 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_typeelif isinstance(fallback_device, TVMContext):fallback_device = fallback_device.device_typeif 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 selfdef __exit__(self, ptype, value, trace):_transform.ExitPassContext(self)@staticmethoddef 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, optionalOptimization level. The optimization pass name and level are as thefollowing:.. code-block:: pythonOPT_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, optionalThe fallback device. It is also used as the default device foroperators without specified device during heterogeneous execution.required_pass: set of str, optionalOptimization passes that are required regardless of optimization level.disabled_pass: set of str, optionalOptimization passes to be disabled during optimization.force_transform_avgpool2d : bool, optionalThe 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 falseas 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, optionalThe 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, optionalsvd_topn_percent% = sum(TopN singular values) / sum(All singular values).Returns-------pass_context: PassContextThe pass context for optimizations."""return PassContext(opt_level, fallback_device, required_pass,disabled_pass, force_transform_avgpool2d,ksize_global_avgpool2d_transform, svd_topn_percent)
