tvm1介绍/ubuntu安装/向量加法转置举例

author author     2022-12-08     202

关键词:


文章目录

  • ​​什么是TVM​​
  • ​​一.TVM安装​​
  • ​​1.1 需要安装的软件​​
  • ​​1.2 安装​​
  • ​​1.3 python环境​​
  • ​​1.4 C++ test​​
  • ​​1.5 python链接tvm​​
  • ​​1.6 测试(显示下面表示成功了,因为这里只需要CPU代码优化, 因此只使用了LLVM)​​
  • ​​二. TVM 例子​​
  • ​​2.1 测试可用​​
  • ​​2.2 compute 和 schedule分离​​
  • ​​2.3 tvm的数据类型​​
  • ​​2.4 变化的形状​​
  • ​​2.5 矩阵转置​​

什么是TVM

网上搜索一大堆一个看一遍, 把共性的东西了解一下就明白了

  • 该工具使用的是C++的后端,python作为前端直接调用TVM包进行代码优化
  • TVM是一套完整的stack,包括神经网络图优化(比如op fusion)和单个operation优化等部分
  • 不同后端设备上实现现有的operation
  • TVM可以优化的训练好的模型,并将你的模型打包好,然后你可以将这个优化好的模型放在任何平台去运行

一.TVM安装

环境
win10子系统
Ubuntu18
​llvm安装链接​​

1.1 需要安装的软件

llvm-as -version # 6.0.1, llvm安装需要用到博客内容
clang -v # 6.0.1
cmake -version # 3.10.2
gcc/g++ -v # 7.5.0

环境中包含python2, python3, 同时安装conda自带python, 目前使用的是conda自带的python

1.2 安装

  • 下载
git clone --recursive https://github.com/apache/incubator-tvm tvm && cd tvm
# 上面的仓库已经保存到了国内仓库gitee中, 可用下面的代替
git clone https://gitee.com/nwu_zjq/tvm.git && cd tvm
# 下面的命令式添加子模块
git submodule init
git submodule update
  • cmake编译
mkdir build
cp cmake/config.cmake build/
cd build/
vim config.cmake # 这里设置打开llvm,debug等重要工具
# set(USE_MICRO ON)
# set(USE_CPP_RPC ON)
# set(USE_GRAPH_RUNTIME_DEBUG ON)
# set(USE_MICRO_STANDALONE_RUNTIME ON)
# set(USE_LLVM ON)
cmake ..
make -j4
# 这里完成后会生成libtvm.so

1.3 python环境

  • 创建名称为tvm,python版本为3.6的环境
conda create -n tvm python=3.6
source activate tvm # 进入搭建的环境中
pip install tornado psutil xgboost mxnet tensorflow==2.0.0 # 安装包
sudo vi ~/.bashrc # 将刚编译好的tvm放到系统环境变量中
# 插入下面
# export TVM_HOME="/mnt/e/00_TVM/tvm"
# export PYTHONPATH=$TVM_HOME/python:$PYTHONPATH

1.4 C++ test

git clone https://github.com/google/googletest
cd googletest
mkdir build
cd build
cmake ..
make
sudo make install

1.5 python链接tvm

# cd /mnt/E:\\00_TVM\\tvm\\python
python setup.py install

1.6 测试(显示下面表示成功了,因为这里只需要CPU代码优化, 因此只使用了LLVM)

TVM1

二. TVM 例子

2.1 测试可用

import tvm
n = 1024
A = tvm.te.placeholder((n,), name=A)
B = tvm.te.placeholder((n,), name=B)
C = tvm.te.compute(A.shape, lambda i: A[i] + B[i], name="C")
print(type(C)) #<class tvm.te.tensor.Tensor>
print(C)
<class tvm.te.tensor.Tensor>
Tensor(shape=[1024], op.name=C)

2.2 compute 和 schedule分离

  • Halide项目将所有operation的程序做了拆解,认为所有程序由两部分组成:compute和schedule。而将compute和schedule相分离也是一个里程碑式的重要想法,为自动代码生成提供了可能。
# 代码1
for(int i = 0; i < 10; i ++)
for(int j = 0; j < 10; j++)
b[i][j] = a[i][j];

# 代码2
for(int i = 0; i < 10; i ++)
for(int j = 0; j < 10; j++)
b[j][i] = a[j][i];

  • 代码1和代码2的compute一样
  • 显然性能是不一样的(考虑cache的命中率等等),这些涉及具体实现的因素就是schedule:嵌套循环之间的顺序就是schedule的一种,除此之外还有更复杂的schedule:比如在GPU上,哪些数组要放到share memory,某个block到底负责处理那些数据,某个循环是否要展开等等。
# 这是一个向量加法的实例
# placeholder是一种特殊的tensor可以理解为任意维度的数组, 和pytorch一样

import tvm
# https://blog.csdn.net/Tao_758/article/details/108046094
# 发现新版本的tvm里,var、placeholder等都移到了 tvm.te下,因此改为tvm.te.*即可

# 这部分定义了compute
n = 1024
A = tvm.te.placeholder((n,), name=A) # 声明维度为(1024,),命名为A
B = tvm.te.placeholder((n,), name=B)
C = tvm.te.compute((n,), lambda i: A[i] + B[i], name="C")
print(type(C)) #<class tvm.te.tensor.Tensor>
print(C)
<class tvm.te.tensor.Tensor>
Tensor(shape=[1024], op.name=C)
# 这部分定义了schedule部分
s = tvm.te.create_schedule(C.op)
print(s)
schedule(0x2698500)
# 默认执行设计
code_default = tvm.lower(s, [A, B, C], simple_mode=True)
print("默认生成的代码是:\\n",code_default)
默认生成的代码是:
#[version = "0.0.5"]
primfn(A_1: handle, B_1: handle, C_1: handle) -> ()
attr = "global_symbol": "main", "tir.noalias": True
buffers = A: Buffer(A_2: Pointer(float32), float32, [1024], []),
C: Buffer(C_2: Pointer(float32), float32, [1024], []),
B: Buffer(B_2: Pointer(float32), float32, [1024], [])
buffer_map = A_1: A, B_1: B, C_1: C
for (i: int32, 0, 1024)
C_2[i] = ((float32*)A_2[i] + (float32*)B_2[i])

2.3 tvm的数据类型

# 使用tvm.build操作将定义好的计算和设计编译成可执行模块

import tvm
import numpy as np

n = 100

# Defined in file: ./chapter_expression/vector_add.md
def eval_mod(mod, *inputs, out):
"""Evaluate a TVM module, and save results in out.
"""
# Convert all numpy arrays to tvm arrays
tvm_args = [tvm.nd.array(x) if isinstance(x, np.ndarray)
else x for x in inputs + (out,)]
mod(*tvm_args)
# If out is a tvm array, then its value has already been inplaced.
# Otherwise, explicitly copy the results.
if isinstance(out, np.ndarray):
np.copyto(out, tvm_args[-1].asnumpy())


def tvm_vector_add(dtype):
A = tvm.te.placeholder((n,), dtype=dtype)
B = tvm.te.placeholder((n,), dtype=dtype)
C = tvm.te.compute(A.shape, lambda i: A[i] + B[i])
s = tvm.te.create_schedule(C.op)
return tvm.build(s, [A, B, C])

mod = tvm_vector_add(int32)

def test_mod(mod, dtype):
# you can use astype to convert data type
a, b = (np.random.normal(size=100).astype(dtype) for _ in range(2))
c = np.empty(100, dtype=dtype)
eval_mod(mod, a, b, out=c)
print("data type of c: ".format(c.dtype))
np.testing.assert_equal(c, a + b)

test_mod(mod, int32)

for dtype in [float16, float64, int8, int16, int64]:
mod = tvm_vector_add(dtype)
test_mod(mod, dtype)
data type of c: int32
data type of c: float16
data type of c: float64
data type of c: int8
data type of c: int16
data type of c: int64

2.4 变化的形状

在定义计算时,可能对于输入的形状是未知的,可以通过tvm.var定义一个变量来指定形状,然后在具体调用时,传入具体值即可,如对于定义A、B、C三个占位符时,如果不知道输入的维度,可以使用变量n来创建任意长度数组:

import numpy as np
import tvm
np.random.seed(0)
def eval_mod(mod, *inputs, out):
tvm_args = [tvm.nd.array(x) if isinstance(x, np.ndarray) else x for x in inputs + (out,)]
mod(*tvm_args)
if isinstance(out, np.ndarray):
np.copyto(out, tvm_args[-1].asnumpy())

n = tvm.te.var(name=n)
print(type(n), n.dtype)

A = tvm.te.placeholder((n,), name=a)
B = tvm.te.placeholder((n,), name=b)
C = tvm.te.compute(A.shape, lambda i: A[i] + B[i])
s = tvm.te.create_schedule(C.op)
print("原始生成\\n",tvm.lower(s, [A, B, C], simple_mode=True))

def test_mod(mod, size):
a, b = (np.random.normal(size=size).astype(float32) for _ in range(2))
c = np.empty(size, dtype=float32)
print("c shape: ".format(c.shape))
eval_mod(mod, a, b, out=c)
np.testing.assert_equal(c, a + b)

mod = tvm.build(s, [A, B, C])
test_mod(mod, 5)
test_mod(mod, 1000)

def tvm_vector_add(ndim):
A = tvm.te.placeholder([tvm.te.var() for _ in range(ndim)])
B = tvm.te.placeholder(A.shape)
C = tvm.te.compute(A.shape, lambda *i: A[i] + B[i])
s = tvm.te.create_schedule(C.op)
return tvm.build(s, [A, B, C])

mod = tvm_vector_add(2)
test_mod(mod, (2, 2))

mod = tvm_vector_add(4)
test_mod(mod, (2, 3, 4, 5))
<class tvm.tir.expr.Var> int32
原始生成
#[version = "0.0.5"]
primfn(a_1: handle, b_1: handle, compute_1: handle) -> ()
attr = "global_symbol": "main", "tir.noalias": True
buffers = compute: Buffer(compute_2: Pointer(float32), float32, [n: int32], [stride: int32], type="auto"),
a: Buffer(a_2: Pointer(float32), float32, [n], [stride_1: int32], type="auto"),
b: Buffer(b_2: Pointer(float32), float32, [n], [stride_2: int32], type="auto")
buffer_map = a_1: a, b_1: b, compute_1: compute
for (i: int32, 0, n)
compute_2[(i*stride)] = ((float32*)a_2[(i*stride_1)] + (float32*)b_2[(i*stride_2)])

2.5 矩阵转置

# 矩阵转置
import tvm
n = tvm.te.var("n")
m = tvm.te.var("n")

A = tvm.te.placeholder((n,m), name=A)
B = tvm.te.compute((m,n), lambda i,j:A[j,i], "B")
s = tvm.te.create_schedule(B.op)
tvm.lower(s,[A,B], simple_mode=True)
#[version = "0.0.5"]
primfn(A_1: handle, B_1: handle) -> ()
attr = "global_symbol": "main", "tir.noalias": True
buffers = B: Buffer(B_2: Pointer(float32), float32, [n: int32, n_1: int32], [stride: int32, stride_1: int32], type="auto"),
A: Buffer(A_2: Pointer(float32), float32, [n_1, n], [stride_2: int32, stride_3: int32], type="auto")
buffer_map = A_1: A, B_1: B
for (i: int32, 0, n)
for (j: int32, 0, n_1)
B_2[((i*stride) + (j*stride_1))] = (float32*)A_2[((j*stride_2) + (i*stride_3))]


ref:

​利用Pytorch导出Onnx模型进行模型优化例子​

​​利用tutorials子文件测试图像识别例子​​

​​TVM代码库演练示例​​

​知乎例子​


GLM:如何转置向量?

】GLM:如何转置向量?【英文标题】:GLM:Howtotransposeavector?【发布时间】:2012-03-2520:43:34【问题描述】:也许我只是在文档中遗漏了一些东西,但GLM似乎不可能对向量进行转置。我也看不到mat3x1或mat1x3类型。glm::transpose也不适用... 查看详情

矩阵和向量相乘

...阵A的转置表示为A?,定义如下            向量可以看作是只有一列的矩阵。对应地,向量的转置可以看作是只有一行的矩阵。    标量可以看作是只有一个元素的矩阵。因此,标量的转置等于它本身,a=a?。 查看详情

线性代数回顾(linearalgebrareview)

3.1 矩阵和向量3.2 加法和标量乘法3.3 矩阵向量乘法3.4 矩阵乘法3.5 矩阵乘法的性质3.6 逆、转置    3.1 矩阵和向量  查看详情

数学二维向量(加法减法模点乘叉乘)

二维向量加法二维向量减法二维向量的模点乘叉乘 查看详情

LLVM 中的向量加法程序

】LLVM中的向量加法程序【英文标题】:VectorAdditionPrograminLLVM【发布时间】:2013-06-0716:51:40【问题描述】:我正在尝试在LLVM中编写一个5元素向量加法程序,但不知道如何返回整个结果向量。我的代码如下,错误是LLVM错误:提供... 查看详情

三元组顺序表表示的稀疏矩阵的转置和加法运算的实现

#include<stdio.h>#include<math.h>#include<stdlib.h>#include<conio.h>#include<malloc.h>#include<string.h>#defineMAXSIZE100#defineMAXMU25typedefstruct{inti,j;intv;}Tr 查看详情

将相关矩阵转置为 SAS 中的一个长向量

】将相关矩阵转置为SAS中的一个长向量【英文标题】:TransposeacorrelationmatrixintoonelongvectorinSAS【发布时间】:2019-04-3017:14:43【问题描述】:我正在尝试将相关矩阵转换为一个长列向量,以便我具有以下结构datawant;input_name1_$_name2_$_c... 查看详情

上采样下采样以及pytorch中的卷积与反卷积(转置卷积)方法介绍(conv2d和convtranspose2d)(代码片段)

文章目录1.上采样与下采样1.1上采样1.2下采样2.卷积函数——Conv2d2.1卷积函数说明2.2卷积操作可视化与举例(1)举例一:padding=0,stride=1,kernel_size=3(2)举例二:padding=2,stride=1,kernel_size& 查看详情

2一个向量乘它的转置,其几何意义是什么?

参考:https://www.zhihu.com/question/40049682/answer/1420483558分两种情况:一、行X列就是它长度的平方。二、列X行通常对它进行一下处理(归一化):对任意一个向量b,它投影到a上的向量一定是:关于列X行的投影 查看详情

使用 AVX2 对 2 个短整型向量进行向量加法

】使用AVX2对2个短整型向量进行向量加法【英文标题】:Vectorisedadditionfor2shortintvectorsusingAVX2【发布时间】:2018-03-1423:52:31【问题描述】:我在使用AVX2指令集对2个短(16位整数)向量类型执行加法运算时遇到问题。我已经构建了... 查看详情

如何在 Matplotlib 中绘制向量加法?

】如何在Matplotlib中绘制向量加法?【英文标题】:HowtoplotvectoradditioninMatplotlib?【发布时间】:2021-12-3004:13:09【问题描述】:我正在尝试绘制矢量加法,但没有得到预期的结果,我对3D绘图完全陌生,我需要认真的帮助我的情节是... 查看详情

三元组顺序表表示的稀疏矩阵的转置和加法运算的实现----《数据结构》

#include<stdio.h>#include<malloc.h>#include<stdlib.h>#include<string.h>#defineMAXSIZE225#defineN9typedefstruct{ inti,j; inte;}Triple;typedefstruct{ Tripledata[MAXSIZE+1]; intmu 查看详情

C ++中的向量加法并不完全正确[重复]

】C++中的向量加法并不完全正确[重复]【英文标题】:VectoradditioninC++isnotcomingoutexactlyright[duplicate]【发布时间】:2014-05-0413:04:57【问题描述】:我正在尝试在我的C++程序中将一个向量添加到另一个向量,但结果不准确。这是矢量... 查看详情

AAch64 高级 SIMD 向量加法

】AAch64高级SIMD向量加法【英文标题】:AAch64AdvancedSIMDvectoraddition【发布时间】:2016-02-0319:22:21【问题描述】:我正在尝试在我的汇编代码中添加两个高级SIMD向量。在这里,我有两个向量v0和v1,我想将v0的上半部分与v1的下半部分... 查看详情

使用 Cuda 进行 128 位向量加法,性能问题

】使用Cuda进行128位向量加法,性能问题【英文标题】:128-bitvectoradditionwithCuda,performanceissue【发布时间】:2020-08-2503:42:47【问题描述】:我想添加带有进位的128位向量。我的128位版本(下面代码中的addKernel128)比基本的32位版本... 查看详情

图像的代数运算(代码片段)

目录一.加法运算1.加法运算的定义2.主要应用举例3.各种噪声说明4.C++代码二.减法运算1.减法运算的定义2.主要应用举例三.乘法运算1.乘法运算的定义2.主要应用举例四.与运算1.与运算的定义2.主要应用举例五.非运算1.非的定... 查看详情

r语言矩阵向量操作(矩阵乘法,向量内积外积(叉乘),矩阵转置,矩阵的逆)(代码片段)

文章目录前言求矩阵、向量转置矩阵乘法求矩阵、向量内积求向量外积(叉乘)求矩阵的逆前言创建两个四维矩阵A与B,A按列填充,B按行填充:A<-matrix(1:16,4,4,byrow=FALSE)B<-matrix(1:16,4,4,byrow=TRUE)创建两... 查看详情

线性代数导论向量介绍

参考资料:《Introductiontolinearalgebra》4theditionbyGilbertStrang网易公开课:http://open.163.com/special/opencourse/daishu.html  麻省理工公开课:线性代数思考:(一)相似矩阵是同一个线性变换的不同描述矩阵(二)对象的变换等价于坐标系... 查看详情