【TVM教程】转换

TVM部署TensorFlow模型 本文是对TVM官方关于如何使用TVM编译TensorFlow模型文档的翻译整理,并记录了实现时遇到的小坑。 TVM部署TensorFlow模型 本文介绍如何使用TVM部署TensorFlow模型。 在开始之前,首先需要安装TensorFlow的Python包。 Python及TensorFlow环境 以下例程需要Python3.5以上的环境才能运行,请使用3.5以上Python的版本。 我在使用P... 阅读详情

TVM 现已更新到 0.21.0 版本,TVM 中文文档已经和新版本对齐。

Apache TVM 是一个深度的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。

在线运行 TVM 学习教程→go.hyper.ai/PEh1Q

本节我们将深入介绍 Relax 程序的转换。转换是编译流程中实现优化和对接硬件后端的关键环节之一。

我们首先像上一节那样,创建一个简单的 Relax 程序。

import tvm
from tvm import IRModule, relax
from tvm.relax.frontend import nn


class NNModule(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 128)
        self.relu1 = nn.ReLU()
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu1(x)
        x = self.fc2(x)
        return x


origin_mod, params = NNModule().export_tvm(
    {"forward": {"x": nn.spec.Tensor(("n", 784), "float32")}}
)
origin_mod.show()

输出:

# from tvm.script import ir as I
# from tvm.script import tir as T
# from tvm.script import relax as R

@I.ir_module
class Module:
    @R.function
    def forward(x: R.Tensor(("n", 784), dtype="float32"), fc1_weight: R.Tensor((128, 784), dtype="float32"), fc1_bias: R.Tensor((128,), dtype="float32"), fc2_weight: R.Tensor((10, 128), dtype="float32"), fc2_bias: R.Tensor((10,), dtype="float32")) -> R.Tensor(("n", 10), dtype="float32"):
        n = T.int64()
        R.func_attr({"num_input": 1})
        with R.dataflow():
            permute_dims: R.Tensor((784, 128), dtype="float32") = R.permute_dims(fc1_weight, axes=None)
            matmul: R.Tensor((n, 128), dtype="float32") = R.matmul(x, permute_dims, out_dtype="void")
            add: R.Tensor((n, 128), dtype="float32") = R.add(matmul, fc1_bias)
            relu: R.Tensor((n, 128), dtype="float32") = R.nn.relu(add)
            permute_dims1: R.Tensor((128, 10), dtype="float32") = R.permute_dims(fc2_weight, axes=None)
            matmul1: R.Tensor((n, 10), dtype="float32") = R.matmul(relu, permute_dims1, out_dtype="void")
            add1: R.Tensor((n, 10), dtype="float32") = R.add(matmul1, fc2_bias)
            gv: R.Tensor((n, 10), dtype="float32") = add1
            R.output(gv)
        return gv

应用转换

在 Relax 中,Pass 是应用程序转换的主要方式。我们可以通过应用 Pass 来改变程序的形式。首先,我们应用一个内置 LegalizeOps,它会将高层操作符(High-level Operators)转换为低层操作符。

mod = tvm.relax.transform.LegalizeOps()(origin_mod)
mod.show()

输出:

# from tvm.script import ir as I
# from tvm.script import tir as T
# from tvm.script import relax as R

@I.ir_module
class Module:
    @T.prim_func(private=True)
    def add(var_matmul: T.handle, fc1_bias: T.Buffer((T.int64(128),), "float32"), var_T_add: T.handle):
        T.func_attr({"tir.noalias": True})
        n = T.int64()
        matmul = T.match_buffer(var_matmul, (n, T.int64(128)))
        T_add = T.match_buffer(var_T_add, (n, T.int64(128)))
        # with T.block("root"):
        for ax0, ax1 in T.grid(n, T.int64(128)):
            with T.block("T_add"):
                v_ax0, v_ax1 = T.axis.remap("SS", [ax0, ax1])
                T.reads(matmul[v_ax0, v_ax1], fc1_bias[v_ax1])
                T.writes(T_add[v_ax0, v_ax1])
                T_add[v_ax0, v_ax1] = matmul[v_ax0, v_ax1] + fc1_bias[v_ax1]

    @T.prim_func(private=True)
    def add1(var_matmul1: T.handle, fc2_bias: T.Buffer((T.int64(10),), "float32"), var_T_add: T.handle):
        T.func_attr({"tir.noalias": True})
        n = T.int64()
        matmul1 = T.match_buffer(var_matmul1, (n, T.int64(10)))
        T_add = T.match_buffer(var_T_add, (n, T.int64(10)))
        # with T.block("root"):
        for ax0, ax1 in T.grid(n, T.int64(10)):
            with T.block("T_add"):
                v_ax0, v_ax1 = T.axis.remap("SS", [ax0, ax1])
                T.reads(matmul1[v_ax0, v_ax1], fc2_bias[v_ax1])
                T.writes(T_add[v_ax0, v_ax1])
                T_add[v_ax0, v_ax1] = matmul1[v_ax0, v_ax1] + fc2_bias[v_ax1]

    @T.prim_func(private=True)
    def matmul(var_x: T.handle, permute_dims: T.Buffer((T.int64(784), T.int64(128)), "float32"), var_matmul: T.handle):
        T.func_attr({"tir.noalias": True})
        n = T.int64()
        x = T.match_buffer(var_x, (n, T.int64(784)))
        matmul = T.match_buffer(var_matmul, (n, T.int64(128)))
        # with T.block("root"):
        for i0, i1, k in T.grid(n, T.int64(128), T.int64(784)):
            with T.block("matmul"):
                v_i0, v_i1, v_k = T.axis.remap("SSR", [i0, i1, k])
                T.reads(x[v_i0, v_k], permute_dims[v_k, v_i1])
                T.writes(matmul[v_i0, v_i1])
                with T.init():
                    matmul[v_i0, v_i1] = T.float32(0.0)
                matmul[v_i0, v_i1] = matmul[v_i0, v_i1] + x[v_i0, v_k] * permute_dims[v_k, v_i1]

    @T.prim_func(private=True)
    def matmul1(var_relu: T.handle, permute_dims1: T.Buffer((T.int64(128), T.int64(10)), "float32"), var_matmul: T.handle):
        T.func_attr({"tir.noalias": True})
        n = T.int64()
        relu = T.match_buffer(var_relu, (n, T.int64(128)))
        matmul = T.match_buffer(var_matmul, (n, T.int64(10)))
        # with T.block("root"):
        for i0, i1, k in T.grid(n, T.int64(10), T.int64(128)):
            with T.block("matmul"):
                v_i0, v_i1, v_k = T.axis.remap("SSR", [i0, i1, k])
                T.reads(relu[v_i0, v_k], permute_dims1[v_k, v_i1])
                T.writes(matmul[v_i0, v_i1])
                with T.init():
                    matmul[v_i0, v_i1] = T.float32(0.0)
                matmul[v_i0, v_i1] = matmul[v_i0, v_i1] + relu[v_i0, v_k] * permute_dims1[v_k, v_i1]

    @T.prim_func(private=True)
    def relu(var_add: T.handle, var_compute: T.handle):
        T.func_attr({"tir.noalias": True})
        n = T.int64()
        add = T.match_buffer(var_add, (n, T.int64(128)))
        compute = T.match_buffer(var_compute, (n, T.int64(128)))
        # with T.block("root"):
        for i0, i1 in T.grid(n, T.int64(128)):
            with T.block("compute"):
                v_i0, v_i1 = T.axis.remap("SS", [i0, i1])
                T.reads(add[v_i0, v_i1])
                T.writes(compute[v_i0, v_i1])
                compute[v_i0, v_i1] = T.max(add[v_i0, v_i1], T.float32(0.0))

    @T.prim_func(private=True)
    def transpose(fc1_weight: T.Buffer((T.int64(128), T.int64(784)), "float32"), T_transpose: T.Buffer((T.int64(784), T.int64(128)), "float32")):
        T.func_attr({"tir.noalias": True})
        # with T.block("root"):
        for ax0, ax1 in T.grid(T.int64(784), T.int64(128)):
            with T.block("T_transpose"):
                v_ax0, v_ax1 = T.axis.remap("SS", [ax0, ax1])
                T.reads(fc1_weight[v_ax1, v_ax0])
                T.writes(T_transpose[v_ax0, v_ax1])
                T_transpose[v_ax0, v_ax1] = fc1_weight[v_ax1, v_ax0]

    @T.prim_func(private=True)
    def transpose1(fc2_weight: T.Buffer((T.int64(10), T.int64(128)), "float32"), T_transpose: T.Buffer((T.int64(128), T.int64(10)), "float32")):
        T.func_attr({"tir.noalias": True})
        # with T.block("root"):
        for ax0, ax1 in T.grid(T.int64(128), T.int64(10)):
            with T.block("T_transpose"):
                v_ax0, v_ax1 = T.axis.remap("SS", [ax0, ax1])
                T.reads(fc2_weight[v_ax1, v_ax0])
                T.writes(T_transpose[v_ax0, v_ax1])
                T_transpose[v_ax0, v_ax1] = fc2_weight[v_ax1, v_ax0]

    @R.function
    def forward(x: R.Tensor(("n", 784), dtype="float32"), fc1_weight: R.Tensor((128, 784), dtype="float32"), fc1_bias: R.Tensor((128,), dtype="float32"), fc2_weight: R.Tensor((10, 128), dtype="float32"), fc2_bias: R.Tensor((10,), dtype="float32")) -> R.Tensor(("n", 10), dtype="float32"):
        n = T.int64()
        R.func_attr({"num_input": 1})
        cls = Module
        with R.dataflow():
            permute_dims = R.call_tir(cls.transpose, (fc1_weight,), out_sinfo=R.Tensor((784, 128), dtype="float32"))
            matmul = R.call_tir(cls.matmul, (x, permute_dims), out_sinfo=R.Tensor((n, 128), dtype="float32"))
            add = R.call_tir(cls.add, (matmul, fc1_bias), out_sinfo=R.Tensor((n, 128), dtype="float32"))
            relu = R.call_tir(cls.relu, (add,), out_sinfo=R.Tensor((n, 128), dtype="float32"))
            permute_dims1 = R.call_tir(cls.transpose1, (fc2_weight,), out_sinfo=R.Tensor((128, 10), dtype="float32"))
            matmul1 = R.call_tir(cls.matmul1, (relu, permute_dims1), out_sinfo=R.Tensor((n, 10), dtype="float32"))
            add1 = R.call_tir(cls.add1, (matmul1, fc2_bias), out_sinfo=R.Tensor((n, 10), dtype="float32"))
            gv: R.Tensor((n, 10), dtype="float32") = add1
            R.output(gv)
        return gv

从输出可以看到,程序中的高层操作符(即 relax.op)已被其对应的低层操作符(即 relax.call_tir)所替代。

接下来我们尝试应用算子融合(Operator Fusion),这是一种在 ML 编译器中被广泛使用的优化技术。需要注意的是,在 Relax 中,融合优化是由一系列 Pass 协作完成的,我们可以按顺序依次应用它们。

mod = tvm.ir.transform.Sequential(
    [
        tvm.relax.transform.AnnotateTIROpPattern(),
        tvm.relax.transform.FuseOps(),
        tvm.relax.transform.FuseTIR(),
    ]
)(mod)
mod.show()

输出:

# from tvm.script import ir as I
# from tvm.script import tir as T
# from tvm.script import relax as R

@I.ir_module
class Module:
    @T.prim_func(private=True)
    def fused_matmul1_add1(p_relu: T.handle, permute_dims1: T.Buffer((T.int64(128), T.int64(10)), "float32"), fc2_bias: T.Buffer((T.int64(10),), "float32"), p_output0: T.handle):
        T.func_attr({"tir.noalias": True})
        n = T.int64()
        relu = T.match_buffer(p_relu, (n, T.int64(128)))
        T_add_intermediate = T.match_buffer(p_output0, (n, T.int64(10)))
        # with T.block("root"):
        matmul_intermediate = T.alloc_buffer((n, T.int64(10)))
        for i0, i1, k in T.grid(n, T.int64(10), T.int64(128)):
            with T.block("matmul"):
                v_i0, v_i1, v_k = T.axis.remap("SSR", [i0, i1, k])
                T.reads(relu[v_i0, v_k], permute_dims1[v_k, v_i1])
                T.writes(matmul_intermediate[v_i0, v_i1])
                with T.init():
                    matmul_intermediate[v_i0, v_i1] = T.float32(0.0)
                matmul_intermediate[v_i0, v_i1] = matmul_intermediate[v_i0, v_i1] + relu[v_i0, v_k] * permute_dims1[v_k, v_i1]
        for ax0, ax1 in T.grid(n, T.int64(10)):
            with T.block("T_add"):
                v_ax0, v_ax1 = T.axis.remap("SS", [ax0, ax1])
                T.reads(matmul_intermediate[v_ax0, v_ax1], fc2_bias[v_ax1])
                T.writes(T_add_intermediate[v_ax0, v_ax1])
                T_add_intermediate[v_ax0, v_ax1] = matmul_intermediate[v_ax0, v_ax1] + fc2_bias[v_ax1]

    @T.prim_func(private=True)
    def fused_matmul_add_relu(p_x: T.handle, permute_dims: T.Buffer((T.int64(784), T.int64(128)), "float32"), fc1_bias: T.Buffer((T.int64(128),), "float32"), p_output0: T.handle):
        T.func_attr({"tir.noalias": True})
        n = T.int64()
        x = T.match_buffer(p_x, (n, T.int64(784)))
        compute_intermediate = T.match_buffer(p_output0, (n, T.int64(128)))
        # with T.block("root"):
        matmul_intermediate = T.alloc_buffer((n, T.int64(128)))
        T_add_intermediate = T.alloc_buffer((n, T.int64(128)))
        for i0, i1, k in T.grid(n, T.int64(128), T.int64(784)):
            with T.block("matmul"):
                v_i0, v_i1, v_k = T.axis.remap("SSR", [i0, i1, k])
                T.reads(x[v_i0, v_k], permute_dims[v_k, v_i1])
                T.writes(matmul_intermediate[v_i0, v_i1])
                with T.init():
                    matmul_intermediate[v_i0, v_i1] = T.float32(0.0)
                matmul_intermediate[v_i0, v_i1] = matmul_intermediate[v_i0, v_i1] + x[v_i0, v_k] * permute_dims[v_k, v_i1]
        for ax0, ax1 in T.grid(n, T.int64(128)):
            with T.block("T_add"):
                v_ax0, v_ax1 = T.axis.remap("SS", [ax0, ax1])
                T.reads(matmul_intermediate[v_ax0, v_ax1], fc1_bias[v_ax1])
                T.writes(T_add_intermediate[v_ax0, v_ax1])
                T_add_intermediate[v_ax0, v_ax1] = matmul_intermediate[v_ax0, v_ax1] + fc1_bias[v_ax1]
        for i0, i1 in T.grid(n, T.int64(128)):
            with T.block("compute"):
                v_i0, v_i1 = T.axis.remap("SS", [i0, i1])
                T.reads(T_add_intermediate[v_i0, v_i1])
                T.writes(compute_intermediate[v_i0, v_i1])
                compute_intermediate[v_i0, v_i1] = T.max(T_add_intermediate[v_i0, v_i1], T.float32(0.0))

    @T.prim_func(private=True)
    def transpose(fc1_weight: T.Buffer((T.int64(128), T.int64(784)), "float32"), T_transpose: T.Buffer((T.int64(784), T.int64(128)), "float32")):
        T.func_attr({"op_pattern": 2, "tir.noalias": True})
        # with T.block("root"):
        for ax0, ax1 in T.grid(T.int64(784), T.int64(128)):
            with T.block("T_transpose"):
                v_ax0, v_ax1 = T.axis.remap("SS", [ax0, ax1])
                T.reads(fc1_weight[v_ax1, v_ax0])
                T.writes(T_transpose[v_ax0, v_ax1])
                T_transpose[v_ax0, v_ax1] = fc1_weight[v_ax1, v_ax0]

    @T.prim_func(private=True)
    def transpose1(fc2_weight: T.Buffer((T.int64(10), T.int64(128)), "float32"), T_transpose: T.Buffer((T.int64(128), T.int64(10)), "float32")):
        T.func_attr({"op_pattern": 2, "tir.noalias": True})
        # with T.block("root"):
        for ax0, ax1 in T.grid(T.int64(128), T.int64(10)):
            with T.block("T_transpose"):
                v_ax0, v_ax1 = T.axis.remap("SS", [ax0, ax1])
                T.reads(fc2_weight[v_ax1, v_ax0])
                T.writes(T_transpose[v_ax0, v_ax1])
                T_transpose[v_ax0, v_ax1] = fc2_weight[v_ax1, v_ax0]

    @R.function
    def forward(x: R.Tensor(("n", 784), dtype="float32"), fc1_weight: R.Tensor((128, 784), dtype="float32"), fc1_bias: R.Tensor((128,), dtype="float32"), fc2_weight: R.Tensor((10, 128), dtype="float32"), fc2_bias: R.Tensor((10,), dtype="float32")) -> R.Tensor(("n", 10), dtype="float32"):
        n = T.int64()
        R.func_attr({"num_input": 1})
        cls = Module
        with R.dataflow():
            permute_dims = R.call_tir(cls.transpose, (fc1_weight,), out_sinfo=R.Tensor((784, 128), dtype="float32"))
            lv = R.call_tir(cls.fused_matmul_add_relu, (x, permute_dims, fc1_bias), out_sinfo=R.Tensor((n, 128), dtype="float32"))
            permute_dims1 = R.call_tir(cls.transpose1, (fc2_weight,), out_sinfo=R.Tensor((128, 10), dtype="float32"))
            gv = R.call_tir(cls.fused_matmul1_add1, (lv, permute_dims1, fc2_bias), out_sinfo=R.Tensor((n, 10), dtype="float32"))
            R.output(gv)
        return gv

最终可以看到,matmul、add 和 relu 等操作符被融合成一个内核(也就是一个 call_tir)。

关于所有内置 Pass 的详细信息,请参考 relax.transform。

自定义 Pass

我们也可以定义自己的 Pass。例如,我们可以将程序中的 relu 操作符重写为 gelu 操作符。

首先,我们需要编写一个 Relax IR Mutator 来执行这个替换操作。

from tvm.relax.expr_functor import PyExprMutator, mutator


@mutator
class ReluRewriter(PyExprMutator):
    def __init__(self, mod):
        super().__init__(mod)

    def visit_call_(self, call: relax.Call) -> relax.Expr:
        # 访问 relax.Call 表达式,并且只处理当操作(op)是 relax.nn.relu 的情况。
        if call.op.name == "relax.nn.relu":
            return relax.op.nn.gelu(call.args[0])

        return super().visit_call_(call)

然后我们可以编写一个 Pass,将这个 Mutator 应用于整个模块。

@tvm.transform.module_pass(opt_level=0, name="ReluToGelu")
class ReluToGelu:  # pylint: disable=too-few-public-methods
    def transform_module(self, mod: IRModule, _ctx: tvm.transform.PassContext) -> IRModule:
        """IRModule-level transformation"""
        rewriter = ReluRewriter(mod)
        for g_var, func in mod.functions_items():
            if isinstance(func, relax.Function):
                func = rewriter.visit_expr(func)
                rewriter.builder_.update_func(g_var, func)
        return rewriter.builder_.get()


mod = ReluToGelu()(origin_mod)
mod.show()

输出:

# from tvm.script import ir as I
# from tvm.script import tir as T
# from tvm.script import relax as R

@I.ir_module
class Module:
    @R.function
    def forward(x: R.Tensor(("n", 784), dtype="float32"), fc1_weight: R.Tensor((128, 784), dtype="float32"), fc1_bias: R.Tensor((128,), dtype="float32"), fc2_weight: R.Tensor((10, 128), dtype="float32"), fc2_bias: R.Tensor((10,), dtype="float32")) -> R.Tensor(("n", 10), dtype="float32"):
        n = T.int64()
        R.func_attr({"num_input": 1})
        with R.dataflow():
            permute_dims: R.Tensor((784, 128), dtype="float32") = R.permute_dims(fc1_weight, axes=None)
            matmul: R.Tensor((n, 128), dtype="float32") = R.matmul(x, permute_dims, out_dtype="void")
            add: R.Tensor((n, 128), dtype="float32") = R.add(matmul, fc1_bias)
            relu: R.Tensor((n, 128), dtype="float32") = R.nn.gelu(add)
            permute_dims1: R.Tensor((128, 10), dtype="float32") = R.permute_dims(fc2_weight, axes=None)
            matmul1: R.Tensor((n, 10), dtype="float32") = R.matmul(relu, permute_dims1, out_dtype="void")
            add1: R.Tensor((n, 10), dtype="float32") = R.add(matmul1, fc2_bias)
            gv: R.Tensor((n, 10), dtype="float32") = add1
            R.output(gv)
        return gv

从打印的输出中可以看到,relax.nn.relu 操作符被成功替换为 relax.nn.gelu 操作符。

关于 Mutator 的更多细节,请参考 relax.expr_functor.PyExprMutator。

总结

在本节中,我们展示了如何对 Relax 程序进行转换,并介绍了如何定义和应用自定义转换

TVM(端到端深度学习编译器)简介 算子编译器前后端引入 引入 2021.2.8 和振伟聊了关于HW OD的工作内容,深度上很好的方向, 目前纯OP的high level的设计,业界已经内卷了即难以进步。 torch已经很好用了社区也好,想从纯软件上进步很难。 而硬骨头OP在硬件上的优化比如GPU有前途但研发周期长,人才紧缺,还在缓慢发展中。 TVM是业界有名气的平台,HW的TBE对标TVM 要做一个接口在前端(各种框架)和后端(异构)。 有了前后端的经验,那么整个行业的Edge端都可以用到,市场很大。 ... 阅读详情

相关推荐

TVM编译Keras模型

TVM官网链接 Compile Keras Models 本文是介绍如何使用Relay部署keras模型的入门教程。 首先,应该安装keras。 还需要Tensorflow,因为它被用作keras的默认后端。 一个快速的解决方案是通过pip安装 pip install -U keras --user pip install -U tensorflow --user 或请参阅官方网站https://keras.io/#installation import tvm from tvm import te im

qq_33287871的博客 361

【TVM 教程】编写自定义 Pass

Apache TVM 是一个深度的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。更多 TVM 中文文档可访问 →https://tvm.hyper.ai/

HyperAI超神经 925

TVM编译Tensorflow模型

编译Tensorflow模型 本文是使用TVM部署Tensorflow模型的入门教程。 首先,需要安装tensorflow python模块。 请参考https://www.tensorflow.org/install # tvm,relay import tvm from tvm import relay from tvm import te #os and numpy import numpy as np import os.path # Tensorflow imports import tens

qq_33287871的博客 617

【TVM系列教程一】深度学习编译器及TVM 介绍

0x0. 介绍大家好呀,在过去的半年到一年时间里,我分享了一些算法解读,算法优化,模型转换相关的一些文章。这篇文章是自己开启学习深度学习编译器的第一篇文章,后续也会努力更新这个系列。这篇文...

算法码上来 2231

【TVM系列二】TVM介绍

文章同步更新在公众号 AIPlayer,欢迎扫码关注,共同进步 目录 一、TVM的工作流程 1、整体流程 2、关键数据结构 3、Transformations 4、搜索空间和基于机器学习的转换 5、目标代码转化 二、逻辑架构组件 三、运行TVM实例 1、交叉编译runtime 2、编译模型 3、运行模型 四、总结 一、TVM的工作流程 TVM主要由两个部分组成: (1)TVM编译器:负责编译和优化模型 (2)TVM runtime:提供目标设备上运行模型的API ..

Flying Cat 6695

【TVM系列三】算子转换调用流程

文章同步更新在公众号 AIPlayer,欢迎扫码关注,共同进步 目录 一、前言 二、TVM代码结构 三、 前端流程 四、算子relay转换 五、Relay到TOPI实现的调用过程 六、总结 一、前言 本文将从源码分析一个算子在TVM中是如何从前端到后端的转换过程。首先来看一下keras模型编译推理的一个示例。 通过pip安装好keras和tensorflow,按照TVM官方文档的示例进行一些修改,因为环境配置的不同,python包的导入以及编译target进行了修改,示例使用c..

Flying Cat 1568

TVM Compiler中文教程:TVM部署SSD模型

部署SSD模型 我们使用GluonCV预训练SSD模型和转换成Relay IR中间表示 import tvm from matplotlib import pyplot as plt from tvm.relay.testing.config import ctx_list from tvm import relay from tvm.contrib import graph_runtime f...

Mars_WH的专栏 2176

Ansys Circuit新手必看:IBIS模型导入时,Pin Import和Buffer Import到底怎么选?

本文详细解析了Ansys Circuit中IBIS模型导入时Pin Import与Buffer Import的选择策略,帮助SI/PI工程师根据仿真需求做出正确决策。通过对比两种方式的特性差异和应用场景,提供实用的选择指南和性能优化建议,提升信号完整性仿真效率。

weixin_26846533的博客 261

【TVM 教程】使用 tvmc 接口在 Adreno™ 上部署预训练模型

本文是一篇关于在 Adreno™ 上部署预训练 Keras resnet50 模型的逐步教程。 此外,您应该已经为 Android 构建了 TVM。请参阅以下说明,了解如何构建它并设置 RPC 环境。 在 Adreno GPU 上部署 登录后复制 import os import tvm import numpy as...

cnzzs的博客 949

激光定位算法竞技场:hdl_localization与Cartographer/AMCL的横向技术解剖

本文深入对比了hdl_localization、Cartographer和AMCL三种激光定位算法的技术原理与性能表现。通过UKF-NDT融合、图优化和粒子滤波等核心技术,分析了各算法在结构化环境、动态环境和大尺度场景下的适应性。实验数据表明,Cartographer在全局一致性上表现最优,而AMCL在动态环境中更具鲁棒性。文章还提供了算法选型指南和参数调优技巧,为工程实践提供参考。

weixin_29062865的博客 366

【车载开发系列】ParaSoft单元测试环境配置(一)

bdf是数据文件的一种类型,表示一种数据库文件。在ParaSoft当中,可以使用bdf文件来快速创建一个测试项目。

千月星跡 2147

如何快速上手Apache TVM:10分钟完成第一个模型编译的完整教程

Apache TVM(Tensor Virtual Machine)是一个开源的深度学习编译器框架,专门用于优化和部署机器学习模型到各种硬件后端。无论你是想将模型部署到CPU、GPU,还是移动设备或嵌入式系统,TVM都能提供高效的编译解决方案。本文将为你提供一份完整的快速入门指南,帮助你在10分钟内完成第一个模型的编译和运行。 ## 📋 准备工作:安装Apache TVM 在开始使用TVM之

gitblog_00148的博客 394

LMX2594时钟配置实战:TICS PRO从入门到寄存器导出

本文详细介绍了LMX2594时钟芯片的配置实战,重点讲解了如何使用TICS PRO调试软件简化复杂的寄存器设置过程。通过实例演示从基础频率配置到高级参数调优的全流程,并分享SPI写入的嵌入式系统移植技巧,帮助工程师快速掌握高性能时钟芯片的配置方法。

weixin_29189003的博客 552

python代码优化指南_如何利用 TVM 优化深度学习GPU op?教你用几十行Python代码实现2-3倍提升...

数天前,陈天奇团队宣布推出 TVM,在微博上表示,「我们今天发布了 TVM,和 NNVM 一起组成深度学习到各种硬件的完整优化工具链,支持手机,cuda, opencl, metal, javascript 以及其它各种后端。欢迎对于深度学习,编译原理,高性能计算,硬件加速有兴趣的同学一起加入 dmlc 推动领导开源项目社区 。」据雷锋网AI科技评论了解,大多数现有系统针对窄范围的服务器级 GPU...

weixin_39718890的博客 363

在线考试系统源码+数据库+word+ppt(高分毕业设计)

本系统通过Spring Cloud实现微服务拆分,将授权、考试、监控等功能解耦,既保证了系统的扩展性,也便于后期维护。基于OAuth2.0的单点登录,解决多服务统一认证问题;考试与练习模式分离,满足不同场景需求;集成Druid与Hystrix,保障系统监控与稳定性。

weixin_44355158的博客 737

【NTN 卫星通信】使用地面网络和卫星网络接入的终端应用场景

卫星接入有广覆盖的特点, 可以改善地面接入网覆盖或无线条件差的地区(例如多径干扰)的服务可用性。对于高速移动中需要实时业务的终端,如IMS语音/视频会议,可以通过地面接入和卫星接入同时实现与5G系统的双连接,在地面接入网不可用的情况下获得连续可靠的业务。

weixin_43603524的博客 2558

【TVM 教程】在 CPU 上部署 Hugging Face 剪枝模型

更多 TVM 中文文档可访问 →Apache TVM 是一个端到端的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。 | Apache TVM 中文站 作者:Josh Fromm 本教程演示如何采用剪枝后的模型(本例中模型是 来自 Hugging Face 的 PruneBert),并使用 TVM ...

weixin_41338054的博客 190

DolphinScheduler任务状态异常排查:从僵尸任务到数据库修复全流程

本文详细介绍了DolphinScheduler中僵尸任务的识别、诊断与修复全流程,包括数据库层面的SQL操作指南、系统恢复验证方法以及预防措施。针对任务状态异常问题,提供了从基础排查到高级源码分析的完整解决方案,帮助运维人员有效管理系统资源和工作流调度。

weixin_27966471的博客 133

TVM User Tutorial -- Optimizing Operators with Auto-scheduling

Author: Lianmin Zheng, Chengfan Jia 在本教程中,我们将展示 TVM 的自动调度功能如何在无需编写自定义模板的情况下找到最佳调度。 与基于模板的 AutoTVM 依赖手动模板来定义搜索空间不同,自动调度程序不需要任何模板。 用户只需编写计算声明,无需任何调度命令或模板。 自动调度器可以自动生成一个大的搜索空间,并在空间中找到一个好的调度。 我们在本教程中使用矩阵乘法作为示例。 请注意,本教程不会在 Windows 或最新版本的 macOS 上运行。 要让它运行,您需要将本教

zachariah2000的博客 298

基于opencv的鱼群检测和数量统计识别鱼群密度带界面

摘要:本项目利用OpenCV图像处理技术实现了视频鱼类自动检测计数系统。通过背景减除、形态学处理和轮廓检测等方法,在视频帧中标记鱼类并统计数量。系统包含视频读取、前景提取、轮廓分析、中心点跟踪等核心功能,可实时显示计数结果。适用于水产养殖、生态监测等领域,具有实用价值。未来可通过参数优化、引入深度学习和多目标跟踪技术进一步提升准确性。(147字)

1720

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

【TVM 教程】在 TVM 中使用 Bring Your Own Datatypes

​接下来使用自定义数据类型进行中间计算。使用与上面相同的输入变量x和y,但在添加x + y之前,首先通过调用将x和y转换为自定义数据类型。注意如何指定自定义数据类型:使用特殊的语法来表示。此外,注意数据类型后面的「32」:这是自定义数据类型的位宽,告诉 TVMmyfloat的每个实例都是 32 位宽。try:# 打印最后一行错误尝试生成此程序会从 TVM 引发错误。TVM 不知道如何创造性地处理所有自定义数据类型!注意,类型代码 150 目前由用户手动选择。参阅中的。

HyperAI超神经 971

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

初识 TVM

如有图像或公式显示错误,可以访问我的个人博客:https://www.wanglichun.tech/2019/11/15/tvm/ 笔者也是最近偶然的机会才开始接触TVM,使用过后发现,经过auto-tuning后的TVM模型在速度是竟然超过了TensorRT,并且笔者使用的是MXNet框架,TVM对MXNet绝对的友好,对于Pytorch等模型,可以使用ONNX,操作也一样简单,使用起来基本类...

小菜鸟的AI之路 7152

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

TVM简介

TVM软件栈 工作流程 从已有的深度学习框架中获取一个模型并将此模型转换为计算图表示(深度学习框架的前端主要是计算图表示以及自动梯度); 图中 Section 3 使用一些方法优化当前的计算图得到优化后的计算图(操作融合,可以将多个操作合并为一个kernel,以此节省存储中间结果的空间;数据布局转换,改变计算图中张量的存储方式以适应目标硬件设备并提升执行效率); 图中 Section 4 针对...

MLer 4万+

TVM Compiler中文教程:TVM调度原语(Schedule Primitives)

文章目录TVM调度原语(Schedule Primitives)分裂split平铺tile TVM调度原语(Schedule Primitives) TVM是用于高效内核代码构建的版本领域专用语言(Domain-Specialed-Language,DSL) 。 这篇教程,我们将展示通过TVM提供的各种原语怎么去调度计算。 from __future__ import absolute_impor...

Mars_WH的专栏 8660
上一篇: 在线教程|4B参数实现生图+编辑,微软开源Mage-Flow,秒级图像推理至高支持2048分辨率
下一篇: 首个面向LLM的蛋白突变排序标准化评测基准!哈佛大学团队提出PG-LLM,一次性测评13款主流模型+95种专业模型
HyperAI超神经
博客等级 码龄7年 8872粉丝 1753原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值