定义

移除无用函数,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. JavaUtils - [03] 代码生成器(旧)

    题记部分 001 || 引入依赖 <!-- Code Generator --> <dependency> <groupId>com.baomidou</gr ...

  2. Go1.24版本终于来了!各位开发者,准备好迎接这些激动人心的新功能了吗?让我们一起来探讨下Go1.24中有哪些精彩的亮点?

    前言 Gopher们,Go 1.24.0 正式发布了!与 Go 1.23.0 相比,这个版本带来了众多改进.让我们一同看看 Go 1.24.0 都有哪些新变化吧! 在 Windows 下,请在 htt ...

  3. 导出和导入word样式模板

    对于自己配置过之后常用的word样式可以导出作为样式模板, 可以重复使用. 举例说一下哪些是常用的word样式, 例如: (常见的): 中文的内容的样式, 中英文分别设置不同的样式 (比较高级的)多级 ...

  4. Nginx 之fastcgi常用配置项说明

    在LNMP环境中,我们都知道nginx如果要解析php脚本语言,就必须通过配置fastcgi模块来提供对php支持,那么在配置fastcgi的时候,关于fastcgi配置项的值应该怎么设置才能让其发挥 ...

  5. C#实现自己的Json解析器(LALR(1)+miniDFA)

    C#实现自己的Json解析器(LALR(1)+miniDFA) Json是一个用处广泛.文法简单的数据格式.本文介绍如何用bitParser(拥有自己的解析器(C#实现LALR(1)语法解析器和min ...

  6. 唐僧,一名合格的IT项目经理

    唐僧, 家喻户晓的唐三藏是也, 他是参悟佛法的大唐高僧,他还是大话西游的男一号, 可是有谁知道,他曾经是一名杰出的项目经理.他所领导的项目是是当时最庞大的IT项目--西天之行求取真经;他所领导的项目团 ...

  7. selinux中Enforcing, Permissive 和Disable这三种模式的区别

    1.如果要马上拒绝运行SELinux:[root@localhost ~]# setenforce 0[root@localhost ~]# getenforcePermissive这条命令会把SEL ...

  8. 使用Docker部署服务

    一.Docker概念 1.操作系统层面的虚拟化技术 2.隔离的进程独立于宿主和其它的隔离的进程 - 容器 3.GO语言开发 4.特点:高效的利用系统资源:快速的启动时间:一致的运行环境:持续交付和部署 ...

  9. 可视化|MapBoxGL

    注册Proton Mail 用户名 密码 人机验证 昵称 设置恢复方法-选择稍后再说-确定 注册MapBoxGL 填写后 Finish creating your account 一开始之前记得选择U ...

  10. ThreeJs-16智慧城市项目(重磅以及未来发展ai)

    ![GIF](https://img2023.cnblogs.com/blog/2680817/202503/2680817-20250303164902745-1619665311.gif) 项目源 ...