Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【从零开始学深度学习编译器】六,TVM的编译流程详解

【从零开始学深度学习编译器】六,TVM的编译流程详解

作者头像
BBuf
发布于 2021-07-01 08:31:07
发布于 2021-07-01 08:31:07
2.1K00
代码可运行
举报
文章被收录于专栏:GiantPandaCVGiantPandaCV
运行总次数:0
代码可运行

一. 前言

上一篇文章对TVM Relay和Pass进行了介绍,但还没有介绍整体的编译流程。这一篇文章将继续介绍一下TVM的编译流程,即TVM是如何将深度学习框架的模型转换成Relay IR之后进一步编译和优化为硬件可以执行的IR,再将这个底层IR和运行时库以及模型参数打包为一个tvm.Module返回。关于为什么要将底层IR和运行时库以及模型参数打包,根据官方文档可以知道这样是为了可以更方便的保存底层IR和运行时库,做到一次编译,可持久化推理。

二. TVM编译流程详解

TVM的编译流程在Python端的调用方式非常简单:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
with tvm.transform.PassContext(opt_level=10):
    lib = relay.build(func, "llvm", params=params)

这里的with tvm.transform.PassContext(opt_level=10)是指定Pass的优化等级,在【从零开始学深度学习编译器】五,TVM Relay以及Pass简介 已经介绍了。这里就跟进一下lib = relay.build(func, "llvm", params=params)这行代码来看一下TVM的编译流程。

首先这里的funcparams分别代表模型的图结构以及权重参数relay.build这个函数定义在tvm/python/tvm/relay/build_module.py这个函数中,入口代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@register_func("tvm.relay.build")
def _build_module_no_factory(mod, target=None, target_host=None, params=None, mod_name="default"):
    """A wrapper around build which discards the Python GraphFactoryRuntime.
    This wrapper is suitable to be used from other programming languages as
    the runtime::Module can be freely passed between language boundaries.
    """
    target, target_host = Target.check_and_update_host_consist(target, target_host)
    return build(mod, target, params=params, mod_name=mod_name).module

对于上面调用的例子targetllvm代表这个模型会被TVM编译成CPU的可执行程序。Target.check_and_update_host_consist这个函数应该是用来检查目标设备类型targer以及target对应的host端是否指定正确的,如果指定正确则将这两个参数合并到一个Target类中并返回。Target这个类的实现在tvm/python/tvm/target/target.py这里,是用来管理TVM支持的设备后端的。

接着就来到了build这个函数,代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
def build(ir_mod, target=None, target_host=None, params=None, mod_name="default"):
    # fmt: off
    # pylint: disable=line-too-long
    """一个将Relay Function编译成可执行程序的函数

    参数
    ----------
    ir_mod : :py:class:`~tvm.IRModule`
        要编译的IR Module. 不推荐使用relay.Function

    target : str, :any:`tvm.target.Target`, or dict of str(i.e. device/context name) to str/tvm.target.Target, optional
        对于异构编译,它是一个指示context到target映射的字典。 对于同构编译,它是一个编译target。 

    target_host : str or :any:`tvm.target.Target`, optional
        主机编译target,如果target是device。 当 TVM 编译 CUDA 等device特定程序时,我们还需要主机(CPU)端代码与驱动程序交互,正确设置维度和参数。target_host 用于指定主机端代码生成target。 默认情况下,如果启用 llvm,则使用 llvm,否则使用 stackvm 解释器。 

    params : dict of str to NDArray
        在推理阶段不会更改的Graph的权重参数,用于常量折叠。 

    mod_name: Optional[str]
        The module name we will build

    Returns
    -------
    graph_json : str
        The json string that can be accepted by graph executor.

    mod : tvm.Module
        The module containing necessary libraries.

    params : dict
        The parameters of the final graph.
    """
    # pylint: enable=line-too-long
    # fmt: on
    if not isinstance(ir_mod, (IRModule, _function.Function)):
        raise ValueError("Type of input parameter mod must be tvm.IRModule")

    if isinstance(ir_mod, _function.Function):
        if params:
            ir_mod = bind_params_by_name(ir_mod, params)
        ir_mod = IRModule.from_expr(ir_mod)
        warnings.warn(
            "Please use input parameter mod (tvm.IRModule) "
            "instead of deprecated parameter mod (tvm.relay.function.Function)",
            DeprecationWarning,
        )
    target = _update_target(target)
    if isinstance(target_host, (str, Target)):
        target_host = Target(target_host)
    elif target_host:
        raise ValueError("target host must be the type of str, " + "tvm.target.Target, or None")

    target, target_host = Target.check_and_update_host_consist(
        target, target_host, target_is_dict_key=False
    )

    # If current dispatch context is fallback context (the default root context),
    # then load pre-tuned parameters from TopHub
    if isinstance(autotvm.DispatchContext.current, autotvm.FallbackContext):
        tophub_context = autotvm.tophub.context(list(target.values()))
    else:
        tophub_context = autotvm.utils.EmptyContext()

    with tophub_context:
        bld_mod = BuildModule()
        graph_json, runtime_mod, params = bld_mod.build(mod=ir_mod, target=target, params=params)
        executor_factory = _graph_executor_factory.GraphExecutorFactoryModule(
            ir_mod, target, graph_json, runtime_mod, mod_name, params
        )
        return executor_factory

在上面的函数中,首先将relay.Functionparams组织成一个IRModule待用,并且再次检查和更新目标设备类型targettarget对应的host端类型。接下来,Relay会寻找是否有AutoTVM预先Fintune的记录,如果没有那么就使用autotvm.FallbackContext这个环境上下文信息,如果有那么接下来的所有操作都在tophub_context 的 scope 之下(with tophub_context:)。值得一提的是 Relay考虑了异构情景下的代码生成,用户可以指定多个生成代码的目标(target)。

with tophub_context:中,创建了一个BuildModule对象bld_mod,然后调用了bld_mod对象的build函数生成一个硬件可以执行的更底层的IR,以及包含各种必需运行时库的tvm.Module和优化后的计算图的参数。这里还有一个_graph_executor_factory.GraphExecutorFactoryModule函数,它的功能就是将上面的IR,运行时库以及参数打包成一个tvm.Module,这样用户只需要把这个tvm.Module存下来,下次就可以省去编译过程直接在硬件上执行了。

继续深入代码,我们现在知道TVM编译Relay IR的核心实现应该就是BuildModule类中的build函数了,我们接着分析:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class BuildModule(object):
    """Build an IR module to run on TVM graph executor. This class is used
    to expose the `RelayBuildModule` APIs implemented in C++.
    """

    def __init__(self):
        self.mod = _build_module._BuildModule()
        self._get_graph_json = self.mod["get_graph_json"]
        self._get_module = self.mod["get_module"]
        self._build = self.mod["build"]
        self._optimize = self.mod["optimize"]
        self._set_params_func = self.mod["set_params"]
        self._get_params_func = self.mod["get_params"]

    def build(self, mod, target=None, target_host=None, params=None):
        """
        Parameters
        ----------
        mod : :py:class:`~tvm.IRModule`
            The IRModule to build.

        target : str, :any:`tvm.target.Target`, or dict of str(i.e.
        device/context name) to str/tvm.target.Target, optional
            For heterogeneous compilation, it is a dictionary indicating context
            to target mapping. For homogeneous compilation, it is a build target.

        target_host : str or :any:`tvm.target.Target`, optional
            Host compilation target, if target is device.
            When TVM compiles device specific program such as CUDA,
            we also need host(CPU) side code to interact with the driver
            to setup the dimensions and parameters correctly.
            target_host is used to specify the host side codegen target.
            By default, llvm is used if it is enabled,
            otherwise a stackvm intepreter is used.

        params : dict of str to NDArray
            Input parameters to the graph that do not change
            during inference time. Used for constant folding.

        Returns
        -------
        factory_module : tvm.relay.backend.graph_executor_factory.GraphExecutorFactoryModule
            The runtime factory for the TVM graph executor.
        """
        target = _update_target(target)
        target, target_host = Target.check_and_update_host_consist(
            target, target_host, target_is_dict_key=False
        )

        # Setup the params.
        if params:
            self._set_params(params)

        # Build the IR module. If auto_scheduler is not enabled,
        # then use the TOPI-defined schedule.
        use_auto_scheduler = PassContext.current().config.get(
            "relay.backend.use_auto_scheduler", False
        )

        # Turn off AutoTVM config not found warnings if auto_scheduler is enabled.
        old_autotvm_silent = autotvm.GLOBAL_SCOPE.silent
        autotvm.GLOBAL_SCOPE.silent = use_auto_scheduler

        self._build(mod, target, target_host)
        autotvm.GLOBAL_SCOPE.silent = old_autotvm_silent

        # Get artifacts
        graph_json = self.get_json()
        mod = self.get_module()
        params = self.get_params()

        return graph_json, mod, params

首先在__init__函数中,通过self._build = self.mod["build"]这行代码可以获取对应的C++函数,这是怎么做到的呢?首先看,self.mod = _build_module._BuildModule()这里的_BuildModule()是C++中注册到环境中的一个函数,实现在:tvm/src/relay/backend/build_module.cc。这里实现了一个RelayBuildModule类,这个类中有一个GetFunction函数,这个函数会通过名字查询要使用的函数,打包成PackedFunc返回,这个函数和上面__init__中的self.mod[“build”]等建立了映射关系。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class RelayBuildModule : public runtime::ModuleNode {
 public:
  /*!
   * \brief Get member function to front-end
   * \param name The name of the function.
   * \param sptr_to_self The pointer to the module node.
   * \return The corresponding member function.
   */
  PackedFunc GetFunction(const std::string& name, const ObjectPtr<Object>& sptr_to_self) final {
    if (name == "get_graph_json") {
      return PackedFunc(
          [sptr_to_self, this](TVMArgs args, TVMRetValue* rv) { *rv = this->GetGraphJSON(); });
    } else if (name == "get_module") {
      return PackedFunc(
          [sptr_to_self, this](TVMArgs args, TVMRetValue* rv) { *rv = this->GetModule(); });
    } else if (name == "build") {
      return PackedFunc([sptr_to_self, this](TVMArgs args, TVMRetValue* rv) {
        ICHECK_EQ(args.num_args, 3);
        this->Build(args[0], args[1], args[2]);
      });
    } else if (name == "list_params") {
      return PackedFunc(
          [sptr_to_self, this](TVMArgs args, TVMRetValue* rv) { *rv = this->ListParamNames(); });
    } else if (name == "get_params") {
      return PackedFunc(
          [sptr_to_self, this](TVMArgs args, TVMRetValue* rv) { *rv = this->GetParams(); });
    } else if (name == "set_params") {
      return PackedFunc([sptr_to_self, this](TVMArgs args, TVMRetValue* rv) {
        Map<String, Constant> params = args[0];
        for (const auto& kv : params) {
          this->SetParam(kv.first, kv.second->data);
        }
      });
    } else if (name == "get_irmodule") {
      return PackedFunc([sptr_to_self, this](TVMArgs args, TVMRetValue* rv) {
        *rv = this->graph_codegen_->GetIRModule();
      });
    } else if (name == "get_external_modules") {
      return PackedFunc([sptr_to_self, this](TVMArgs args, TVMRetValue* rv) {
        *rv = this->graph_codegen_->GetExternalModules();
      });
    } else if (name == "optimize") {
      return PackedFunc([sptr_to_self, this](TVMArgs args, TVMRetValue* rv) {
        ICHECK_EQ(args.num_args, 2);
        *rv = this->Optimize(args[0], args[1], this->params_);
      });
    } else {
      LOG(FATAL) << "Unknown packed function: " << name;
      return PackedFunc([sptr_to_self, name](TVMArgs args, TVMRetValue* rv) {});
    }
  }

PackedFunc是TVM中提供的Python的一个接口,任何函数都可以封装成PackedFunc,并给Python调用,当然Python的函数也可以伪装成PackedFunc提供给C++调用。对这个感兴趣的同学可以看一下这篇博客:https://hjchen2.github.io/2020/01/10/TVM-PackedFunc%E5%AE%9E%E7%8E%B0%E6%9C%BA%E5%88%B6/

继续跟进代码我们发现上面的self.mod["build"]在C++实现中主要就运行了BuildRelay这个函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
void BuildRelay(IRModule relay_module,
                  const std::unordered_map<std::string, tvm::runtime::NDArray>& params) {
    Target target_host = GetTargetHost();
    // If no target_host has been set, we choose a default one, which is
    // llvm if "codegen.LLVMModuleCreate" is accessible.
    const runtime::PackedFunc* pf = runtime::Registry::Get("codegen.LLVMModuleCreate");
    if (!target_host.defined()) target_host = (pf != nullptr) ? Target("llvm") : Target("stackvm");

    // Update all the targets in the targets_ TargetsMap
    CheckAndUpdateHostConsistency(&targets_, &target_host);

    // Relay IRModule -> IRModule optimizations.
    relay_module = Optimize(relay_module, targets_, params);
    // Get the updated function.
    auto func = Downcast<Function>(relay_module->Lookup("main"));

    // Generate code for the updated function.
    graph_codegen_ = std::unique_ptr<GraphCodegen>(new GraphCodegen());
    graph_codegen_->Init(nullptr, targets_);
    graph_codegen_->Codegen(func);

    ret_.graph_json = graph_codegen_->GetJSON();
    ret_.params = graph_codegen_->GetParams();

    auto lowered_funcs = graph_codegen_->GetIRModule();

    // Generate a placeholder function that attaches linked params as its arguments.
    if (target_host->GetAttr<Bool>("link-params").value_or(Bool(false))) {
      CHECK(pf != nullptr) << "Unable to link-params with no target_host and no llvm codegen.";
      auto param_ids = graph_codegen_->GetParamIds();
      auto link_params = Map<String, tir::LinkedParam>();
      for (auto param : ret_.params) {
        link_params.Set(param.first, tir::LinkedParam(param_ids[param.first], param.second));
      }

      Map<String, ObjectRef> dict;
      dict.Set(tvm::tir::attr::kLinkedParams, link_params);
      dict.Set(tvm::attr::kGlobalSymbol, String(::tvm::runtime::symbol::tvm_lookup_linked_param));
      DictAttrs attrs{dict};
      auto prim = tir::PrimFunc(Array<tir::Var>(), tir::SeqStmt(Array<tir::Stmt>()), VoidType(),
                                Map<tir::Var, tir::Buffer>(), attrs);
      if (lowered_funcs.find(target_host->str()) == lowered_funcs.end()) {
        lowered_funcs.Set(target_host->str(), IRModule(Map<GlobalVar, BaseFunc>({})));
      }
      lowered_funcs[target_host->str()]->Add(
          GlobalVar(::tvm::runtime::symbol::tvm_lookup_linked_param), prim);
    }

    // When there is no lowered_funcs due to reasons such as optimization.
    if (lowered_funcs.size() == 0) {
      if (target_host.defined() && target_host->kind->name == "llvm") {
        // If we can decide the target is LLVM, we then create an empty LLVM module.
        ret_.mod = (*pf)(target_host->str(), "empty_module");
      } else {
        // If we cannot decide the target is LLVM, we create an empty CSourceModule.
        // The code content is initialized with ";" to prevent complaining
        // from CSourceModuleNode::SaveToFile.
        ret_.mod = tvm::codegen::CSourceModuleCreate(";", "", Array<String>{});
      }
    } else {
      ret_.mod = tvm::build(lowered_funcs, target_host_);
    }

    auto ext_mods = graph_codegen_->GetExternalModules();
    ret_.mod = tvm::codegen::CreateMetadataModule(ret_.params, ret_.mod, ext_mods, GetTargetHost());
  }

在这个函数是编译流程的主要代码,可以看到它包含了Optimize,Codegen两个过程。而Optimize就是我们上一节讲过的Pass了,Codegen主要实现了内存分配以及指定设备上的代码生成。这里面还有很多细节,但本篇文章只是讲编译流程,所以Codegen相关细节不在这里继续展开。

三,总结

这篇文章跟进源码介绍了一下TVM的编译流程,可以看到TVM通过Relay IR来对接深度学习框架的模型并通过编译流程将Relay IR编译成了硬件可以执行的IR,再将这个底层IR和运行时库以及模型参数打包为一个tvm.Module返回。关于为什么要将底层IR和运行时库以及模型参数打包,根据官方文档可以知道这样是为了可以方便的保存TVM的计算图和运行时库,可以做到一次编译,可持久化推理。

四,同系列文章

五,参考

  • https://zhuanlan.zhihu.com/p/91283238
  • https://zhuanlan.zhihu.com/p/338550499

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GiantPandaCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【从零开始学深度学习编译器】九,TVM的CodeGen流程
【GiantPandaCV导语】这里主要是走读了一下TVM的Codegen流程,从Relay的前端一直梳理到了Graph节点的内存分配,Relay IR到TIR节点的转换,TIR图节点的Schedule优化以及Lower function发生在哪里。这篇文章只是关注了调用链,一些具体的操作比如Schedule的优化,IR到TIR节点的转化以及Lower Function没有具体解释,后面会结合更多实例去尝试理解。
BBuf
2021/07/23
2K0
【从零开始学深度学习编译器】番外二,在Jetson Nano上玩TVM
【GiantPandaCV导语】这篇文章主要是讲解了如何给Jetson Nano装机,以及在Jetson Nano上如何配置TVM并将MxNet的ResNet18跑起来获取分类结果,最后我们还体验了一下使用AutoTVM来提升ResNet50在Jetson Nano上的推理效率,AutoTune了一个Task(一共需要AutoTune 20个Task)之后可以将ResNet50的推理速度做到150ms跑完一张图片(224x224x3),从上面的BenchMark可以看到TensorRT在FP32的时候大概能做到50-60ms推理一张图片(224x224x3)。本文所有实验代码均可以在这里找到:https://github.com/BBuf/tvm_learn/blob/main/relay ,如果你对学习TVM感兴趣可以考虑点个star。
BBuf
2021/07/01
1.9K0
【从零开始学深度学习编译器】番外二,在Jetson Nano上玩TVM
【从零开始学深度学习编译器】十,TVM的整体把握
大概4个月前开始接触TVM,虽然是0经验开始看,但目前对TVM的IR以及Pass,Codegen,Scheduler等也有了一些基础的认识。所以这篇文章的目的是梳理一下TVM的整体架构,复盘一下自己学到了什么,以及为想学习TVM的小伙伴们提供一个整体思路。「从零开始学深度学习编译器」这个专题的文章和实验代码都被我汇总放到了https://github.com/BBuf/tvm_learn这个仓库中,当然是希望「大力点一下Star了」,感激不尽。仓库目录如下:
BBuf
2021/08/19
1.5K0
【从零开始学深度学习编译器】五,TVM Relay以及Pass简介
【GiantPandaCV导语】这篇文章主要介绍了一下TVM的Relay并介绍了如何基于Relay构建一个Conv+BN+ReLU的小网络,然后介绍了一下TVM中的Pass的工作机制,并较为详细的介绍了RemoveUnusedFunctions,ToBasicBlockNormalForm,EliminateCommonSubexpr三种Pass。其中Relay部分的详细介绍大部分引用自官方文档:https://tvm.apache.org/docs/tutorials/get_started/introduction.html。
BBuf
2021/07/01
1.7K1
【从零开始学深度学习编译器】五,TVM Relay以及Pass简介
TVM 学习指南(个人版)
最近粗略的看完了天奇大佬的MLC课程(顺便修了一些语法和拼写错误,也算是做了微弱的贡献hh),对TVM的近期发展有了一些新的认识。之前天奇大佬在《新一代深度学习编译技术变革和展望》一文中(链接:https://zhuanlan.zhihu.com/p/446935289)讲解了TVM Unify也即统一多层抽象的概念。这里的统一多层抽象具体包括AutoTensorization用来解决硬件指令声明和张量程序对接,TVM FFI(PackedFunc)机制使得我们可以灵活地引入任意的算子库和运行库函数并且在各个编译模块和自定义模块里面相互调用。TensorIR负责张量级别程序和硬件张量指令的整合。Relax (Relax Next) 引入relay的进一步迭代,直接引入first class symbolic shape的支持 (摘抄自《新一代深度学习编译技术变革和展望》一文)。然后这些抽象可以相互交互和联合优化来构造深度学习模型对应的最终部署形式。我个人感觉TVM Unify类似于MLIR的Dialect,但是这几个抽象的直接交互能力相比于MLIR的逐级lower我感觉是更直观方便的,毕竟是Python First(这个只是我最近看MLC课程的一个感觉)。对这部分内容感兴趣的读者请查看天奇大佬的TVM Unify介绍原文以及MLC课程。
BBuf
2022/09/28
3.9K0
TVM 学习指南(个人版)
【从零开始学深度学习编译器】一,深度学习编译器及TVM 介绍
大家好呀,在过去的半年到一年时间里,我分享了一些算法解读,算法优化,模型转换相关的一些文章。这篇文章是自己开启学习深度学习编译器的第一篇文章,后续也会努力更新这个系列。这篇文章是开篇,所以我不会太深入讲解TVM的知识,更多的是介绍一下深度学习编译器和TVM是什么?以及为什么我要选择学习TVM,最后我也会给出一个让读者快速体验TVM效果的一个开发环境搭建的简要教程以及一个简单例子。
BBuf
2021/03/25
2.5K0
【从零开始学深度学习编译器】七,万字长文入门TVM Pass
这篇文章基于TVM 0.8.0.dev版本。在【从零开始学深度学习编译器】五,TVM Relay以及Pass简介 这篇推文中已经简单介绍了Relay和Pass机制。但对Pass的基础设施(Pass Infrastructure)和Relay树结构都没有详细介绍,所以这篇文章主要介绍一下Pass Infrastructure和Relay树结构,再基于这些关键的基础知识详细了解一下Constant Folding Pass,相信读者读完这篇文章会对TVM的Pass有更深的理解,并且在阅读其它Pass和实现自定义Pass时可以很Relax。
BBuf
2021/07/01
1K0
TVM 加速模型,优化推断
TVM 是一个开源深度学习编译器,可适用于各类 CPUs, GPUs 及其他专用加速器。它的目标是使得我们能够在任何硬件上优化和运行自己的模型。不同于深度学习框架关注模型生产力,TVM 更关注模型在硬件上的性能和效率。
GoCoding
2022/05/27
7800
TVM 加速模型,优化推断
【从零开始学深度学习编译器】八,TVM的算符融合以及如何使用TVM Pass Infra自定义Pass
上篇文章系统的介绍了TVM Pass Infra,并解析了Relay树结构以及Constant Folding Pass的具体做法。这一节,我想先补充一下TVM Pass Infra的用法,接着介绍一下TVM算符融合需要用到的支配树这个数据结构,最后再深入分析TVM中的一个非常重要的Pass即算符融合。
BBuf
2021/07/01
2.3K0
【从零开始学深度学习编译器】八,TVM的算符融合以及如何使用TVM Pass Infra自定义Pass
一步一步解读神经网络编译器TVM(二)——利用TVM完成C++端的部署
在上一篇文章中<一步一步解读神经网络编译器TVM(一)——一个简单的例子>,我们简单介绍了什么是TVM以及如何利用Relay IR去编译网络权重然后并运行起来。
老潘
2023/10/19
1.4K0
一步一步解读神经网络编译器TVM(二)——利用TVM完成C++端的部署
【从零开始学TVM】三,基于ONNX模型结构了解TVM的前端
【GiantPandaCV导语】本文基于Pytorch导出的ONNX模型对TVM前端进行了详细的解析,具体解答了TVM是如何将ONNX模型转换为Relay IR的,最后还给出了一个新增自定义OP的示例。其实在TVM中支持编译多种目前主流的深度学习框架如TensorFlow,Pytorch,MxNet等,其实它们的前端交互过程和本文介绍的ONNX也大同小异,希望对TVM感兴趣的读者在阅读这篇文章之后对新增OP,或者说在TVM中支持一种新的DL框架有一个整体把握。本文实验相关的代码在https://github.com/BBuf/tvm_learn。
BBuf
2021/04/30
2.2K0
使用TVM优化PyTorch模型实现快速CPU推理
Apache TVM 是一个相对较新的 Apache 项目,以深度学习模型推理的性能大幅改进为目标。它属于一种叫做模型编译器(model compilers) 的新技术: 它以高级框架(如 PyTorch 或 TensorFlow)中编写的模型作为输入,生成一个为在特定硬件平台上运行而优化的二进制包作为输出。
McGL
2021/07/07
2.3K0
PyTorch模型转TVM模型全流程记录
PyTorch1.3以后添加了对移动端的支持,我曾尝试过将模型转入移动端,花了很多功夫,把检测+识别的所有代码都转成TorchScript之后,放到移动端运行,却发现在移动端的推理速度比PC慢了好几倍,不得不放弃这个方案。
带萝卜
2020/10/23
2.4K0
【从零开始学深度学习编译器】二,TVM中的scheduler
在【从零开始学深度学习编译器】一,深度学习编译器及TVM 介绍我们已经知道TVM可以将各种深度学习训练框架的模型(计算图)转化为内部的Graph IR(Relay),然后通过TVM提供的指令生成模块将Graph IR翻译成特定硬件可执行的指令或者代码。总的来说的TVM的思想可以总结为表示和调度分离,所谓表示就是IR,调度就是scheduler。同时,在高性能计算方面TVM提供了多种调度源语(scheduler),包含了大多数常见的优化手段如算子融合,读写缓存,分块计算,并行计算等等,这些计算方法都可以通过scheduler进行实现。所以这一节,我们就一起来探索一下TVM中的scheduler。
BBuf
2021/04/16
2K0
一步一步解读神经网络编译器TVM(一)——一个简单的例子
这是一个TVM教程系列,计划从TVM的使用说明,再到TVM的内部源码,为大家大致解析一下TVM的基本工作原理。因为TVM的中文资料比较少,也希望贡献一下自己的力量,如有描述方面的错误,请及时指出。
老潘
2023/10/19
6.9K0
一步一步解读神经网络编译器TVM(一)——一个简单的例子
【从零开始学深度学习编译器】十二,MLIR Toy Tutorials学习笔记一
MLIR提供了一种Toy语言来说明MLIR的定义和执行的流程。Toy语言是一种基于张量的语言,我们可以使用它来定义函数,执行一些数学计算以及输出结果。下面要介绍的例子中限制Tensor的维度是<=2的,并且Toy语言中唯一的数据类型是64位浮点类型,对应C语言中的"double"。另外Values是不可以重写的,即每个操作都会返回一个新分配的值,并自动管理释放。直接看下面这个例子:
BBuf
2021/11/02
1.2K0
【从零开始学深度学习编译器】十二,MLIR Toy Tutorials学习笔记一
TVM 从入门到精通 | 安装 TVM (Part 1)
内容一览:TVM 共有三种安装方法:从源码安装、使用 Docker 镜像安装和 NNPACK Contrib 安装。本文重点介绍如何通过源码安装 TVM。
HyperAI超神经
2023/02/27
3.9K0
TVM 从入门到精通 | 安装 TVM (Part 1)
关于深度学习编译器,这些知识你需要知道
近年来,以机器学习、深度学习为核心的AI技术得到迅猛发展,深度神经网络在各行各业得到广泛应用:
AI科技大本营
2021/03/12
1.5K0
关于深度学习编译器,这些知识你需要知道
【从零开始学深度学习编译器】十五,MLIR Toy Tutorials学习笔记之Lowering到LLVM IR
在上一节中,我们将Toy Dialect的部分Operation Lowering到Affine Dialect,MemRef Dialect和Standard Dialect,而toy.print操作保持不变,所以又被叫作部分Lowering。通过这个Lowering可以将Toy Dialect的Operation更底层的实现逻辑表达出来,以寻求更多的优化机会,得到更好的MLIR表达式。这一节,我们将在上一节得到的混合型MLIR表达式完全Lowering到LLVM Dialect上,然后生成LLVM IR,并且我们可以使用MLIR的JIT编译引擎来运行最终的MLIR表达式并输出计算结果。
BBuf
2021/11/19
1.3K0
使用 LLVM 实现一个简单编译器
作者:tomoyazhang,腾讯 PCG 后台开发工程师 1. 目标 这个系列来自 LLVM 的Kaleidoscope 教程,增加了我对代码的注释以及一些理解,修改了部分代码。现在开始我们要使用 LLVM 实现一个编译器,完成对如下代码的编译运行。 # 斐波那契数列函数定义 def fib(x)     if x < 3 then         1     else         fib(x - 1) + fib(x - 2) fib(40) # 函数声明 extern sin(arg)
腾讯技术工程官方号
2021/09/18
3.2K0
推荐阅读
相关推荐
【从零开始学深度学习编译器】九,TVM的CodeGen流程
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档