定义

移除无用函数,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. 全面详解C语言使用cJSON解析JSON字符[转载]

    cJSON对象的实现采用了树形结构,每个对象是树的一个节点,每个节点由cJSON这个结构体组成,对象中的元素也由cJSON这个结构体组成.同一层的对象和元素是双向链表结构,由next和prev指针链接 ...

  2. AI在电子游戏中的应用:如何让虚拟世界更具沉浸感

    在过去的几十年里,电子游戏已从简单的像素化图形演变为高度复杂.视觉震撼的虚拟世界.从<超级马里奥>到<荒野大镖客2>,游戏的画面.音效和交互方式不断突破技术的极限.近年来,人工 ...

  3. mysql 查询结果为空时值时执行后面的sql语句

    sql server支持变量所以一般使用方法如下: DECLARE @Val varchar(50) select @Val = param_value where t_param where par ...

  4. SQL Server 2005与2008清空日志方法

    SQL2008 的收缩日志 由于SQL2008对文件和日志管理进行了优化,所以以下语句在SQL2005中可以运行但在SQL2008中已经被取消:SQL2005 清空日志的方法:Backup Log D ...

  5. python 字典使用

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

  6. glib-2.60在win64,msys2下编译

    前阵子,工作原因,需要在win7 64下的msys2来编译glib,下面是一些踩过的坑: 事先声明一下,这些个解决方式及纯粹是为了编译通过,可能有些做法不太适合一些需要正常使用的场合,烦请各位注意下. ...

  7. js回忆录(4) -- 对象,构造函数

    1.对象 && 构造函数 js是一门基于对象的语言,里边所有的数据类型都可以当对象使唤(当然null和undefined除外),当我们在v8引擎里声明一个对象时会发现每个对象属性里边都 ...

  8. Hack The Box-代理连接及靶机-Meow-喵呜

    前言 ​ 在第一层,您将获得网络安全渗透测试领域的基本技能.您将首先学习如何匿名连接到各种服务,例如 FTP.SMB.Telnet.Rsync 和 RDP.接下来,您将发现 Nmap 的强大功能,这是 ...

  9. JAVA调用Python脚本执行

    SpringBoot-web环境 <dependency> <groupId>org.springframework.boot</groupId> <arti ...

  10. ORA-01779: 无法修改与非键值保存表对应的列”中涉及的概念和解决方法

    什么是键值保存表(Key-Preserved Table)? 在理解什么是键值保存表之前,首先要知道 可更新的联接视图 这个概念,键值保存表只是保存了允许更新的字段信息的一张表.为什么会出现这么一张表 ...