DE10-NanoにTVM VTAのRPC Serverを導入する


Terasic DE10-NanoにTVM VTAのRPC Serverを導入したので作業メモ。

DE10-Nanoセットアップに従う

必要なもの

  • DE10-Nano
  • microSDカード
    • 8GB以上推奨、microSDXC非対応な気がするので注意
  • microUSBケーブル
    • シリアル通信に必要
  • LANケーブル
    • ネットワークに繋ぐのに必要

DE10-Nanoのセットアップ

まずはTerasicのページからAngstrom Linuxイメージをダウンロードする。

  • de10-nano-image-Angstrom-v2016.12.socfpga-sdimg.2017.03.31.tgz

ダウンロードしたファイルをmicroSDに書き込む。Win32DiskImagerを使用。

DE10-Nanoに電源ケーブルを接続、microSDをDE10-Nanoに挿入、microUSBケーブルでDE10-NanoとPCを接続する。

PC上でターミナルエミュレータでDE10-Nanoに接続する。TeraTermを使用。

ユーザ名:root、パスワードなしでログインする。

以降はDE10-Nano上で実行する。

パッケージ導入

システムパッケージをアップデートし、必要なパッケージを導入する。

opkg update
opkg upgrade
opkg install cmake coreutils

Python導入

Angstrom Linuxに入っているPythonは古すぎるので、Pythonソースビルドする。

ソースコードをダウンロードし、ビルド、インストールする。

mkdir ~/workspace
cd ~/workspace
curl -O https://www.python.org/ftp/python/3.8.8/Python-3.8.8.tgz
tar xvf Python-3.8.8.tgz
cd Python-3.8.8
./configure
make
make install

pythonpython3コマンドのシンボリックリンクを導入したPythonに置き換える。

rm /usr/bin/python
ln -s /usr/local/bin/python3.8 /usr/bin/python
rm /usr/bin/python3
ln -s /usr/local/bin/python3.8 /usr/bin/python3

pipを最新バージョンに更新する。

/usr/local/bin/python3 -m pip install --upgrade pip

Git導入

Angstrom Linuxから導入できるGitはバージョンが古いので、これもソースビルドする。

opkg install tcl gettext perl-module-pod-man
cd ~/workspace
git clone https://github.com/git/git
cd git
make configure
./configure --prefix=/usr
make all
make install

TVMのRPC Serverをビルド

TVMの

cd ~/workspace
git clone --recursive https://github.com/apache/tvm tvm
cd tvm
mkdir build
cp cmake/config.cmake build
echo 'set(USE_VTA_FPGA ON)' >> build/config.cmake
cp 3rdparty/vta-hw/config/de10nano_sample.json 3rdparty/vta-hw/config/vta_config.json
cd build
cmake ..
make clean
make runtime vta -j2
pip3 install numpy

TVMのRPC Serverを起動する。

cd ~/workspace/tvm
./apps/vta_rpc/start_rpc_server.sh

ホストPCとの通信に必要になるため、ipコマンドなどでDE10-NanoのIPアドレスをメモしておく。

以下のような出力であればOK。

INFO:root:RPCServer: bind to 0.0.0.0:9091

動作確認

RPCサーバーの動作確認をする。以下はホストPCで実行する。

RPC ServerのIPアドレスとポート番号を環境変数に設定する。

export VTA_RPC_HOST=192.168.10.110
export VTA_RPC_PORT=9091

テストスクリプトを実行する。

cd ~/workspace/tvm
cp 3rdparty/vta-hw/config/de10nano_sample.json 3rdparty/vta-hw/config/vta_config.json
python vta/tests/python/de10nano/test_program_rpc.py
python vta/tests/python/integration/test_benchmark_topi_conv2d.py

ホストPCでは以下のような標準出力。途中からエラーを吐いているが、とりあえず動いてそう。

Conv2DWorkload(batch=1, height=56, width=56, in_filter=64, out_filter=64, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)  
CPU CONV2D TEST PASSED: Time cost = 0.201243 sec/op, 1.14892 GOPS  
Conv2DWorkload(batch=1, height=56, width=56, in_filter=64, out_filter=128, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)  
CPU CONV2D TEST PASSED: Time cost = 0.0930569 sec/op, 1.24231 GOPS  
Conv2DWorkload(batch=1, height=56, width=56, in_filter=64, out_filter=128, hkernel=1, wkernel=1, hpad=0, wpad=0, hstride=2, wstride=2)  
CPU CONV2D TEST PASSED: Time cost = 0.0126302 sec/op, 1.01701 GOPS  
Conv2DWorkload(batch=1, height=28, width=28, in_filter=128, out_filter=128, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)  
CPU CONV2D TEST PASSED: Time cost = 0.194179 sec/op, 1.19071 GOPS  
Conv2DWorkload(batch=1, height=28, width=28, in_filter=128, out_filter=256, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)  
CPU CONV2D TEST PASSED: Time cost = 0.0934884 sec/op, 1.23658 GOPS  
Conv2DWorkload(batch=1, height=28, width=28, in_filter=128, out_filter=256, hkernel=1, wkernel=1, hpad=0, wpad=0, hstride=2, wstride=2)  
CPU CONV2D TEST PASSED: Time cost = 0.0121611 sec/op, 1.05624 GOPS  
Conv2DWorkload(batch=1, height=14, width=14, in_filter=256, out_filter=256, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)  
CPU CONV2D TEST PASSED: Time cost = 0.186729 sec/op, 1.23822 GOPS  
Conv2DWorkload(batch=1, height=14, width=14, in_filter=256, out_filter=512, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=2, wstride=2)  
CPU CONV2D TEST PASSED: Time cost = 0.11122 sec/op, 1.03943 GOPS  
Conv2DWorkload(batch=1, height=14, width=14, in_filter=256, out_filter=512, hkernel=1, wkernel=1, hpad=0, wpad=0, hstride=2, wstride=2)  
CPU CONV2D TEST PASSED: Time cost = 0.0136669 sec/op, 0.939866 GOPS  
Conv2DWorkload(batch=1, height=7, width=7, in_filter=512, out_filter=512, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)  
CPU CONV2D TEST PASSED: Time cost = 0.223079 sec/op, 1.03645 GOPS  
Conv2DWorkload(batch=1, height=56, width=56, in_filter=64, out_filter=64, hkernel=3, wkernel=3, hpad=1, wpad=1, hstride=1, wstride=1)  
Traceback (most recent call last):  
File "vta/tests/python/integration/test_benchmark_topi_conv2d.py", line 311, in <module>  
test_conv2d(device="vta")  
File "vta/tests/python/integration/test_benchmark_topi_conv2d.py", line 306, in test_conv2d  
vta.testing.run(_run)  
File "/home/ubuntu/workspace/tvm/vta/python/vta/testing/utils.py", line 74, in run  
run_func(env, remote)  
File "vta/tests/python/integration/test_benchmark_topi_conv2d.py", line 304, in _run  
run_conv2d(env, remote, wl, target)  
File "vta/tests/python/integration/test_benchmark_topi_conv2d.py", line 234, in run_conv2d  
data_arr = tvm.nd.array(data_np, ctx)  
File "/home/ubuntu/workspace/tvm/python/tvm/runtime/ndarray.py", line 518, in array  
return empty(arr.shape, arr.dtype, ctx).copyfrom(arr)  
File "/home/ubuntu/workspace/tvm/python/tvm/runtime/ndarray.py", line 292, in empty  
arr = _ffi_api.TVMArrayAllocWithScope(shape_ptr, ndim, dtype, ctx, mem_scope)  
File "tvm/_ffi/_cython/./packed_func.pxi", line 322, in tvm._ffi._cy3.core.PackedFuncBase._call_  
File "tvm/_ffi/_cython/./packed_func.pxi", line 267, in tvm._ffi._cy3.core.FuncCall  
File "tvm/_ffi/_cython/./base.pxi", line 160, in tvm._ffi._cy3.core.CALL  
tvm.error.RPCError: Traceback (most recent call last):  
\[bt\] (8) /home/ubuntu/workspace/tvm/build/libtvm.so(tvm::runtime::NDArray::Empty(std::vector<long, std::allocator<long> >, DLDataType, DLContext, tvm::runtime::Optional<tvm::runtime::String>)+0x124) \[0x7f1a9ab04024\]  
\[bt\] (7) /home/ubuntu/workspace/tvm/build/libtvm.so(tvm::runtime::RPCDeviceAPI::AllocDataSpace(DLContext, int, long const\*, DLDataType, tvm::runtime::Optional<tvm::runtime::String>)+0x89) \[0x7f1a9ab30c59\]  
\[bt\] (6) /home/ubuntu/workspace/tvm/build/libtvm.so(tvm::runtime::RPCClientSession::AllocDataSpace(DLContext, int, long const\*, DLDataType, tvm::runtime::Optional<tvm::runtime::String>)+0x155) \[0x7f1a9ab3ad45\]  
\[bt\] (5) /home/ubuntu/workspace/tvm/build/libtvm.so(+0x164fc14) \[0x7f1a9ab34c14\]  
\[bt\] (4) /home/ubuntu/workspace/tvm/build/libtvm.so(tvm::runtime::RPCEndpoint::HandleUntilReturnEvent(bool, std::function<void (tvm::runtime::TVMArgs)>)+0x37b) \[0x7f1a9ab31a5b\]  
\[bt\] (3) /home/ubuntu/workspace/tvm/build/libtvm.so(tvm::runtime::RPCEndpoint::EventHandler::HandleNextEvent(bool, bool, std::function<void (tvm::runtime::TVMArgs)>)+0x1b8) \[0x7f1a9ab35238\]  
\[bt\] (2) /home/ubuntu/workspace/tvm/build/libtvm.so(tvm::runtime::RPCEndpoint::EventHandler::HandleProcessPacket(std::function<void (tvm::runtime::TVMArgs)>)+0xe7) \[0x7f1a9ab362b7\]  
\[bt\] (1) /home/ubuntu/workspace/tvm/build/libtvm.so(tvm::runtime::RPCEndpoint::EventHandler::HandleReturn(tvm::runtime::RPCCode, std::function<void (tvm::runtime::TVMArgs)>)+0xc9) \[0x7f1a9ab38029\]  
\[bt\] (0) /home/ubuntu/workspace/tvm/build/libtvm.so(dmlc::LogMessageFatal::~LogMessageFatal()+0x6c) \[0x7f1a99beb06c\]

DE10-Nanoでは以下のような標準出力。

INFO:root:Loading VTA library: /home/root/workspace/tvm/vta/python/vta/../../../build/libvta.so  
INFO:RPCServer:load_module /tmp/tmpjpvsqhpe/conv2d.o  
INFO:root:Loading VTA library: /home/root/workspace/tvm/vta/python/vta/../../../build/libvta.so  
INFO:root:Loading VTA library: /home/root/workspace/tvm/vta/python/vta/../../../build/libvta.so  
INFO:root:Loading VTA library: /home/root/workspace/tvm/vta/python/vta/../../../build/libvta.so  
・・・省略・・・
INFO:root:Loading VTA library: /home/root/workspace/tvm/vta/python/vta/../../../build/libvta.so  
Process Process-1:2:  
Traceback (most recent call last):  
File "/usr/local/lib/python3.8/multiprocessing/process.py", line 315, in _bootstrap  
self.run()  
File "/usr/local/lib/python3.8/multiprocessing/process.py", line 108, in run  
self._target(\*self._args, \*\*self._kwargs)  
File "/home/root/workspace/tvm/python/tvm/rpc/server.py", line 118, in _serve_loop  
_ffi_api.ServerLoop(sockfd)  
File "/home/root/workspace/tvm/python/tvm/_ffi/_ctypes/packed_func.py", line 237, in _call_  
raise get_last_ffi_error()  
AttributeError: Traceback (most recent call last):  
4: TVMFuncCall  
3: std::_Function_handler<void (tvm::runtime::TVMArgs, tvm::runtime::TVMRetValue\*), tvm::runtime::{lambda(tvm::runtime::TVMArgs, tvm::runtime::TVMRetValue\*)#2}>::_M_invoke(std::_Any_data const&, tvm::runtime::TVMArgs&&, tvm::runtime::TVMRetValue\*&&)  
2: tvm::runtime::RPCServerLoop(int)  
1: tvm::runtime::RPCEndpoint::ServerLoop()  
0: std::_Function_handler<void (tvm::runtime::TVMArgs, tvm::runtime::TVMRetValue\*), TVMFuncCreateFromCFunc::{lambda(tvm::runtime::TVMArgs, tvm::runtime::TVMRetValue\*)#2}>::_M_invoke(std::_Any_data const&, tvm::runtime::TVMArgs&&, tvm::runtime::TVMRetValue\*&&)  
File "/home/root/workspace/tvm/python/tvm/_ffi/_ctypes/packed_func.py", line 81, in cfun  
rv = local_pyfunc(\*pyargs)  
File "/home/root/workspace/tvm/vta/python/vta/exec/rpc_server.py", line 84, in server_shutdown  
runtime_dll\[0\].VTARuntimeShutdown()  
File "/usr/local/lib/python3.8/ctypes/_init_.py", line 386, in _getattr_  
func = self._getitem_(name)  
File "/usr/local/lib/python3.8/ctypes/_init_.py", line 391, in _getitem_  
func = self._FuncPtr((name_or_ordinal, self))  
AttributeError: /home/root/workspace/tvm/vta/python/vta/../../../build/libvta.so: undefined symbol: VTARuntimeShutdown