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 =
在當前架構中指定要為其生成代碼的特定芯片。默認情況下,這是從目標三元組推斷出來的,并自動檢測到當前體系結構。
? -mattr = a1,+ a2,-a3,…
覆蓋或控制目標的特定屬性,例如是否啟用SIMD操作。默認屬性集由當前CPU設置。要獲取可用屬性的列表,可以執行以下操作:
llc -mtriple= -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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自动生成低精度深度学习算子
- 下一篇: 使用Relay部署编译ONNX模型