定义

移除无用函数,Remove Unused Function,顾名思义,就是删除Module中定义但未用到的函数

当然,它也是一个模块级的优化,

举例子:

def get_mod():
mod = tvm.IRModule({})
fn1 = relay.Function([], relay.const(1))
fn2 = relay.Function([], relay.const(2))
fn3 = relay.Function([], relay.const(3))
g1 = relay.GlobalVar("g1")
g2 = relay.GlobalVar("g2")
g3 = relay.GlobalVar("g3")
mod[g1] = fn1
mod[g2] = fn2
mod[g3] = fn3
p = relay.var("p", "bool")
mod["main"] = relay.Function([p], relay.Call(relay.If(p, g1, g2), []))
return mod mod = get_mod()
ref_mod = get_mod()
mod = relay.transform.RemoveUnusedFunctions()(mod)
print(mod)

例子中,get_mod定义了三个函数fn1fn2fn3,下面并未使用fn3,因此,fn3是个无用函数,应该被移除

该例子输出结果如下:



通过RemoveUnusedFunctions函数后,fn3已被移除

意义

删除无用代码,可以缩减IR代码,可使程序更小、编译更快、(通常)执行也更快。同时它还可以增强编译器改进代码的能力。

实现

同样,该pass会通过TVM_REGISTER_GLOBAL在C++端进行注册,python端通过FFI接口进行访问,不过需要注意的是,该Pass的IRModule对象中一定要有main函数,否则在运行该Pass时会因找不到main方法而报错。

Python端访问:

def RemoveUnusedFunctions(entry_functions=None):
if entry_functions is None:
entry_functions = ["main"]
return _ffi_api.RemoveUnusedFunctions(entry_functions)

C++端注册:

Pass RemoveUnusedFunctions(Array<runtime::String> entry_functions) {
runtime::TypedPackedFunc<IRModule(IRModule, PassContext)> pass_func = [=](IRModule m,
PassContext pc) {
return relay::vm::RemoveUnusedFunctions(m, entry_functions);
};
return CreateModulePass(pass_func, 1, "RemoveUnusedFunctions", {});
} TVM_REGISTER_GLOBAL("relay._transform.RemoveUnusedFunctions").set_body_typed(RemoveUnusedFunctions);

CreateModulePass说明了该Pass是一个Module模块级别的优化

该Pass优化的真正实现是在RemoveUnusedFunctions方法中,代码实现如下:

IRModule RemoveUnusedFunctions(const IRModule& module, Array<runtime::String> entry_funcs) {
std::unordered_set<std::string> called_funcs{};
for (auto entry : entry_funcs) {
VLOG(2) << "RemoveUnusedFunctions:" << entry;
auto funcs = CallTracer(module).Trace(entry);
called_funcs.insert(funcs.cbegin(), funcs.cend());
}
for(auto func : called_funcs)
{
VLOG(2) << "called_funcs:" << func;
}
auto existing_functions = module->functions;
for (auto f : existing_functions) {
VLOG(2) << "existing_functions:" << f.first->name_hint;
auto it = called_funcs.find(f.first->name_hint);
if (it == called_funcs.end()) {
module->Remove(f.first);
}
}
return module;
}

该函数调用CallTracer类(继承ExprVisitor类)的成员函数Trace(),获取IRModule对象中main函数调用的所有函数,并保存在unordered_set<std::string>类型变量called_funcs_中,然后RemoveUnusedFunctions()函数遍历IRModule对象中的所有函数,将不在called_funcs_中的函数视为无用函数,并将它从IRModule对象中移除。

通过上述的调试信息,可以进行佐证:

该Pass优化还是比较简单的

Respect~

TVM Pass优化 -- 移除无用函数(Remove Unused Function)的更多相关文章

  1. TVM Pass IR如何使用

    TVM Pass IR如何使用 随着Relay / tir中优化遍数的增加,执行并手动维护其依赖关系变得很棘手.引入了一个基础结构来管理优化过程,并应用于TVM堆栈中IR的不同层. Relay / t ...

  2. 如何使用TVM Pass红外线

    如何使用TVM Pass红外线 随着Relay / tir中优化遍数的增加,执行并手动维护其依赖关系变得很棘手.引入了一个基础结构来管理优化过程,将其应用于TVM堆栈中IR的不同层. Relay / ...

  3. 7.MySQL优化---存储过程和存储函数

    转自互联网. 当一个大型系统在建立时,会发现,很多的SQL操作是有重叠的,个别计算是相同的,比如:业务系统中,计算一张工单的计算方式.当遇到这些情况时,我们运用存储过程就是一个非常棒的优化啦.那么,什 ...

  4. TVM图优化与算子融合

    TVM图优化与算子融合 计算图的定义 Computational graphs: a common way to represent programs in deep learning framewo ...

  5. [js高手之路]性能优化技巧 - 缓存与函数重载实战

    所谓缓存,通俗点讲就是把已经做过的事情结果先暂时存起来,下次再做同样的事情,不用再重新去做,只要把之前的存的结果拿出来用即可,很明显大大提升了效率.他的应用场景非常广泛.如: 1.缓存ajax结果,大 ...

  6. 动手实现 Redux(三):纯函数(Pure Function)简介

    我们接下来会继续优化我们的 createStore 的模式,让它使我们的应用程序获得更好的性能. 但在开始之前,我们先用一节的课程来介绍一下一个函数式编程里面非常重要的概念 —— 纯函数(Pure F ...

  7. 使用"立即执行函数"(Immediately-Invoked Function Expression,IIFE)

    一.原始写法 模块就是实现特定功能的一组方法. 只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块. function m1(){ //... } function m2(){ // ...

  8. JavaScript学习09 函数本质及Function对象深入探索

    JavaScript学习09 函数本质及Function对象深入探索 在JavaScript中,函数function就是对象. JS中没有方法重载 在JavaScript中,没有方法(函数)重载的概念 ...

  9. 认识js函数对象(Function Object)

    认识函数对象(Function Object) 可以用function关键字定义一个函数,对于每个函数可以为其指定一个函数名,通过函 数名来进行调用.这些都是代码给用户的印象,而在JavaScript ...

  10. 函数查询(Function Query)

    函数查询 可以利用 numeric字段的值 或者 与字段相关的的某个特定的值的函数,来对文档进行评分. 1.    使用函数查询的方法 这里主要有三种方法可以使用函数查询,这三种s方法都是通过solr ...

随机推荐

  1. signature hdr data: BAD (signature 头部数据:不当)

    这应该属于 rpm 4.12-4.13 早期版本的BUG,不止CentOS8会这样 解决方式也很干脆,就是手动更新rpm版本,跳过存在bug的版本,然后yum.rpm就都会正常,就可以自动更新最新的软 ...

  2. startup_stm32f10x_xx.s 启动代码文件的选择

    网上查到的各个文件的解释是: startup_stm32f10x_cl.s 互联型的器件startup_stm32f10x_hd.s 大容量startup_stm32f10x_hd_vl.s 大容量s ...

  3. Typecho防黑安全加固-修改后台路径

    删除安装文件 成功安装后删除install.php文件.install/文件夹. 修改后台地址 把admin修改为黑客猜不到的名字,例如pipixia,防止黑客穷举密码. 修改admin文件夹名称 修 ...

  4. 【BUUCTF】Easy MD5

    [BUUCTF]Easy MD5 (SQL注入.PHP代码审计) 题目来源 收录于:BUUCTF BJDCTF2020 题目描述 抓包得到提示 select * from 'admin' where ...

  5. ppt 文字 +图 样式 设计

    1. 设计前 设计后 图 +文字排版 图多 字少

  6. python 字典使用

    整理很好的文章 文章复制链接: https://mp.weixin.qq.com/s/Aj65A-uuTaARW3vvYTxvzQ 1.检查键是否存在于字典中 def key_in_dict(d, k ...

  7. Qt QSqlDatabase的removeDatabase需要注意的地方

    文章目录 问题描述 Qt官方解决方法 另外一种解决方式 碎碎念 关于智能指针 问题描述 今天在做之前代码的重构的时候,在调用QSqlDatabase的removeDatabase函数的时候,出现了如下 ...

  8. HarmonyOS NEXT 基于原生能力获取视频缩略图

    大家好,我是 V 哥. 不得不佩服 HarmonyOS NEXT 原生能力的强大,如果你想在 鸿蒙 APP 开发中获取视频缩略图,不用依赖第三方库,就可以高效和稳定的实现,AVMetadataHelp ...

  9. BUUCTF---rsa2

    题目 N = 101991809777553253470276751399264740131157682329252673501792154507006158434432009141995367241 ...

  10. 【JUC】基础总结

    多线程的思考:为什么需要run()和start()方法,只用其中一个不行吗? run()和start() run()是运行的时候就直接执行所有代码 start()相当于开启线程,并发执行,让这些线程开 ...