TVM交叉编译和远程RPC
TVM交叉编译和远程RPC
本文介绍了TVM中使用RPC的交叉编译和远程设备执行。
使用交叉编译和RPC,可以在本地计算机上编译程序,然后在远程设备上运行它。当远程设备资源受到限制时(如Raspberry Pi和移动平台),此功能很有用。本文将使用Raspberry Pi作为CPU示例,并使用Firefly-RK3399作为OpenCL示例。
在设备上构建TVM运行时
第一步是在远程设备上构建TVM运行时。
本文所有指令都应在目标设备(例如Raspberry Pi)上执行。假设目标正在运行Linux。
由于在本地计算机上进行编译,因此远程设备仅用于运行生成的代码。只需要在远程设备上构建TVM运行时。
- git clone --recursive https://github.com/apache/tvm tvm
- cd tvm
- make runtime -j2
成功构建运行时后,需要在~/.bashrc文件中设置环境变量。可以~/.bashrc 使用进行编辑并添加以下行(假设TVM目录位于):vi
~/.bashrc~/tvm
- export PYTHONPATH=$PYTHONPATH:~/tvm/python
要更新环境变量,执行。source
~/.bashrc
在设备上设置RPC服务器
要启动RPC服务器,在远程设备上运行以下命令(在本示例中为Raspberry Pi)。
- python -m tvm.exec.rpc_server --host 0.0.0.0 --port=9090
如果看到下面的行,则表明RPC服务器已在设备上成功启动。
- INFO:root:RPCServer: bind to 0.0.0.0:9090
在本地计算机上声明并交叉编译内核
现在,返回安装了完整TVM(带有LLVM)的本地计算机。
将在本地计算机上声明一个简单的内核:
- import numpy as np
- import tvm
- from tvm import te
- from tvm import rpc
- from tvm.contrib import utils
- n = tvm.runtime.convert(1024)
- A = te.placeholder((n,), name="A")
- B = te.compute((n,), lambda i: A[i] + 1.0, name="B")
- s = te.create_schedule(B.op)
然后交叉编译内核。对于Raspberry Pi 3B,目标应该是'llvm -mtriple = armv7l-linux-gnueabihf',在这里使用'llvm'来使本文可在网页构建服务器上运行。参见以下块中的详细说明。
- local_demo = True
- if local_demo:
- target = "llvm"
- else:
- target = "llvm -mtriple=armv7l-linux-gnueabihf"
- func = tvm.build(s, [A, B], target=target, name="add_one")
- # save the lib at a local temp folder
- temp = utils.tempdir()
- path = temp.relpath("lib.tar")
- func.export_library(path)
Readme
要运行这个教程与真正的远程设备,更改local_demo 为False,并取代target在build与三联供设备适当的目标。目标三元组对于不同的设备可能有所不同。例如,它适用 于Raspberry Pi 3B和 RK3399。'llvm
-mtriple=armv7l-linux-gnueabihf''llvm
-mtriple=aarch64-linux-gnu'
可以通过在设备上运行并查询以 ()开头的行)来查询目标(尽管可能仍然是宽松的配置。)gcc
-vTarget:
此外-mtriple,还可以设置别的编译选项,例如:
- -mcpu = <cpuname>
在当前架构中指定要为其生成代码的特定芯片。默认情况下,这是从目标三元组推断出来的,并自动检测到当前体系结构。
- -mattr = a1,+ a2,-a3,...
覆盖或控制目标的特定属性,例如是否启用SIMD操作。默认属性集由当前CPU设置。要获取可用属性的列表,可以执行以下操作:
- llc -mtriple=<your device target triple> -mattr=help
这些选项与llc一致。建议设置目标三元组和功能集以包含可用的特定功能,充分利用开发板的功能。可以从《交叉编译的LLVM指南》中找到有关交叉编译属性的更多详细信息 。
通过RPC远程运行CPU内核
展示了如何在远程设备上运行生成的CPU内核。首先,从远程设备获取RPC会话。
- if local_demo:
- remote = rpc.LocalSession()
- else:
- # The following is my environment, change this to the IP address of your target device
- host = "10.77.1.162"
- port = 9090
- remote = rpc.connect(host, port)
将库上传到远程设备,然后调用设备本地编译器以重新链接。现在func是一个远程模块对象。
- remote.upload(path)
- func = remote.load_module("lib.tar")
- # create arrays on the remote device
- ctx = remote.cpu()
- a = tvm.nd.array(np.random.uniform(size=1024).astype(A.dtype), ctx)
- b = tvm.nd.array(np.zeros(1024, dtype=A.dtype), ctx)
- # the function will run on the remote device
- func(a, b)
- np.testing.assert_equal(b.asnumpy(), a.asnumpy() + 1)
当要评估远程设备上内核的性能时,避免网络开销很重要。 time_evaluator将返回一个远程函数,该函数多次运行该函数,测量该远程设备上的每次运行成本,并返回测得的成本。排除网络开销。
- time_f = func.time_evaluator(func.entry_name, ctx, number=10)
- cost = time_f(a, b).mean
- print("%g secs/op" % cost)
输出:
- 1.161e-07 secs/op
通过RPC远程运行OpenCL内核
对于远程OpenCL设备,工作流程与上面的工作流程几乎相同。可以定义内核,上传文件并通过RPC运行。
Raspberry Pi不支持OpenCL,以下代码在Firefly-RK3399上进行了测试。可以按照本文 为RK3399设置操作系统和OpenCL驱动程序。
另外,需要在rk3399板上启用OpenCL来构建运行时。在TVM根目录中,执行
- cp cmake/config.cmake .
- sed -i "s/USE_OPENCL OFF/USE_OPENCL ON/" config.cmake
- make runtime -j4
以下函数显示了如何远程运行OpenCL内核
- def run_opencl():
- # NOTE: This is the setting for my rk3399 board. You need to modify
- # them according to your environment.
- target_host = "llvm -mtriple=aarch64-linux-gnu"
- opencl_device_host = "10.77.1.145"
- opencl_device_port = 9090
- # create schedule for the above "add one" compute declaration
- s = te.create_schedule(B.op)
- xo, xi = s[B].split(B.op.axis[0], factor=32)
- s[B].bind(xo, te.thread_axis("blockIdx.x"))
- s[B].bind(xi, te.thread_axis("threadIdx.x"))
- func = tvm.build(s, [A, B], "opencl", target_host=target_host)
- remote = rpc.connect(opencl_device_host, opencl_device_port)
- # export and upload
- path = temp.relpath("lib_cl.tar")
- func.export_library(path)
- remote.upload(path)
- func = remote.load_module("lib_cl.tar")
- # run
- ctx = remote.cl()
- a = tvm.nd.array(np.random.uniform(size=1024).astype(A.dtype), ctx)
- b = tvm.nd.array(np.zeros(1024, dtype=A.dtype), ctx)
- func(a, b)
- np.testing.assert_equal(b.asnumpy(), a.asnumpy() + 1)
- print("OpenCL test passed!")
概括
本文提供了TVM中的交叉编译和RPC功能的演练。
- 在远程设备上设置RPC服务器。
- 设置目标设备配置以交叉编译本地计算机上的内核。
- 通过RPC API远程上载和运行内核。
TVM交叉编译和远程RPC的更多相关文章
- rabbitmq学习(四):利用rabbitmq实现远程rpc调用
一.rabbitmq实现rpc调用的原理 ·rabbitmq实现rpc的原理是:客户端向一个队列中发送消息,并注册一个回调的队列用于接收服务端返回的消息,该消息需要声明一个叫做correaltionI ...
- go语言net包rpc远程调用的使用
一.基于http的RPC 服务端: package main; import ( "net/rpc" "net/http" "log" ) ...
- 用TVM在硬件平台上部署深度学习工作负载的端到端 IR 堆栈
用TVM在硬件平台上部署深度学习工作负载的端到端 IR 堆栈 深度学习已变得无处不在,不可或缺.这场革命的一部分是由可扩展的深度学习系统推动的,如滕索弗洛.MXNet.咖啡和皮托奇.大多数现有系统针对 ...
- TVM:一个端到端的用于开发深度学习负载以适应多种硬件平台的IR栈
TVM:一个端到端的用于开发深度学习负载以适应多种硬件平台的IR栈 本文对TVM的论文进行了翻译整理 深度学习如今无处不在且必不可少.这次创新部分得益于可扩展的深度学习系统,比如 TensorFlo ...
- 游戏编程系列[1]--游戏编程中RPC协议的使用[3]--体验
运行环境,客户端一般编译为.Net 3.5 Unity兼容,服务端因为用了一些库,所以一般为4.0 或往上.同一份代码,建立拥有2个项目.客户端引用: WindNet.Client服务端引用: OpL ...
- 基于Netty打造RPC服务器设计经验谈
自从在园子里,发表了两篇如何基于Netty构建RPC服务器的文章:谈谈如何使用Netty开发实现高性能的RPC服务器.Netty实现高性能RPC服务器优化篇之消息序列化 之后,收到了很多同行.园友们热 ...
- RPC框架性能基本比较测试
RPC框架:gRPC.Thrift.Wildfly.Dubbo 原文链接:http://www.open-open.com/lib/view/open1426302068107.html gRPC是G ...
- RabbitMQ 原文译06--Remote procedure call(RPC)
在第三篇文章中, 我们学习了怎么使用队列在多了消息消费者当中进行耗时任务轮询. 但是如果我们想要在远程电脑上运行一个方法,然后等待其执行结果,这就是一个不同的场景,这种就是我们一般讲的RPC(远程过程 ...
- man statd(rpc.statd中文手册)
本人译作集合:http://www.cnblogs.com/f-ck-need-u/p/7048359.html rpc.statd程序主要实现NFS锁相关内容,如普通的文件锁(NLM.NSM).文件 ...
随机推荐
- 04- 移动APP功能测试要点以及具体业务流程测试
5.离线测试: 离线是应用程序在本地的客户端会缓存一部分数据以供程序下次调用. 1.对于一些程序,需要在登录进来后,这是没有网络的情况下可以浏览本地数据. 2.对于无网络时,刷新获取新数据时,不能获取 ...
- git平时用到的仓库
github茫茫仓库 若水三千,取一瓢饮 doocs/technical-books doocs/leetcode lepture/editor pandao/editor.md 未完..待续!!积累 ...
- try catch 用法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 解决在Vim中鼠标右键不能粘贴问题
最近维护一台服务器,使用putty登录后,用vim时,鼠标右键不能 粘贴而是进入了visual模式.网上查找一番找到了解决方法: 方 法一:在普通模式下键入" :set mouse-=a&q ...
- Andrew Ng机器学习算法入门((五):矩阵和向量
矩阵定义 数学上,一个m×n的矩阵是一个由m行n列元素排列成的矩形阵列 使用Aij来获取矩阵中第i行j列的数据 向量的定义 向量就是n行1列的特殊矩阵 由于向量仅仅只有1行,那么通过一个变量i来指定获 ...
- Unity动态构建mesh绘制多边形算法流程分析和实践
前言 先说一下,写这篇博文的动机,原文的博主代码写的十分潇洒,以至于代码说明和注释都没有,最近恰逢看到,所以以此博文来分析其中的算法和流程 参考博文:https://blog.csdn.net/lin ...
- HTML中的JavaScript
HTML中的JavaScript 1.<script>元素 defer:可选.表示脚本可以延迟到文档完全被解析和显示之后再执行.只对外部脚本文件有效. 脚本会被延迟到整个页面都解析完毕后再 ...
- Sping AOP
Sping AOP 1.什么是AOP 面向切面编程(AOP) 是 面向对象编程的补充(OOP) 传统的业务处理代码中,通常会惊醒事务处理.日志处理等操作.虽然可以使用OOP的组合或继承来实现代码重用, ...
- Mybatis学习之自定义持久层框架(六) 自定义持久层框架:完善CRUD方法并进行测试
前言 没想到会等到半年以后才来写这篇文章,我已经不记得当初自己想要在这篇文章中写什么了,还好有一些零散的笔记留着,就对照着上一篇文章及零散的笔记,把内容给补充完吧. 完善CRUD方法 完善Defaul ...
- 技术博客:Azure 认知服务
Azure 认知服务 1.概述 微软认知服务(Microsoft Cognitive Services)集合了多种智能API以及知识API,使每个开发人员无需具备机器学习的专业知识就能接触到 AI ...