定义

移除无用函数,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. Win10、Win11老游戏运行补丁(cnc-ddraw),适用于红色警戒、帝国时代等经典游戏

    Win11.Win10老游戏运行补丁(cnc-ddraw),适用广泛,红色警戒(红警),直接复制到游戏目录,然后即可畅玩.再也不需要修改:管理员运行,兼容性运行,更改DPI.cnc-ddraw 可以修 ...

  2. C# 图形界面编程之 FlowLayoutPanel 界面闪烁问题解决

    公司需要我写几个GUI程序,让虚拟机(guest)内部可以控制虚拟机(host)外部的硬件. 控制外部的硬件的方法就是开一个串口,这样虚拟机与宿主机就可以相互通讯,此时就可以让虚拟机发送命令,宿主机执 ...

  3. WSL2 - Ubuntu 22.04使用记录

    1 安装 搭配Windows Terminal使用为佳,在微软商店可下载: 然后依照官网描述即可. 命令行中运行wsl --install即可.不过由于想自行指定发行版,于是: wsl --list ...

  4. 【Logisim】带有初始化功能的寄存器

    属于是拾人牙慧 子电路外观 子电路逻辑 描述: Q端 Counter + MUX : 实现初始化.初始时MUX选择init,待时钟第一个上升沿后,Counter([Data Bit]:1bit,[Ac ...

  5. go 结构体根据某个字段进行排序

    前言 在任何编程语言中,关乎到数据的排序都会有对应的策略,我们来看下 Golang 是怎样对数据进行排序,以及我们如何优化处理使用 go 排序 go 可以针对任何对象排序,虽然很多情况下是一个 sli ...

  6. Golang 入门 : 变量声明

    变量声明 在Go中,变量是包含值的一块存储.可以使用变量声明为变量命名.只需使用var关键字,后跟所需的名称以及变量将保存的值的类型. 一旦你声明了一个变量,就可以用=为它分配该类型的任何值: qua ...

  7. 朱朝兵《Web前端开发之HTML5+CSS3快速入门》课程资料在线学习

    <Web前端开发之HTML5+CSS3快速入门> [课程简介]本课程由一直专注前端技术与Discuz模板设计与制作!DZ起点网创始人朱朝兵出品,通过本课程学习,即可掌握html5的基本结构 ...

  8. SpringSecurity5(10-动态权限管理)

    授权流程 SpringSecurity 的授权流程如下: 拦截请求,已认证用户访问受保护的 web 资源将被 SecurityFilterChain 中的 FilterSecurityIntercep ...

  9. 使用`forEach`方法前后的代码逐步简化过程

    简化前的完整循环代码 首先,我们使用传统的for-each循环遍历HashMap: import java.util.HashMap; import java.util.Map; public cla ...

  10. .ocx注册失败以及IE使用获取不到.ocx方法的解决办法

    小伙伴写了个.ocx给我,来实现在IE里用<object>获取,并用js调用.ocx的方法去控制XX硬件 Error[1],.ocx注册失败,提示如下: 解决[1]如下: 首先需要下载个工 ...