2023年5月7日日曜日

TensorFlow Lite + XNNPACKをRISC-V Vector Extension Intrinsics を有効にしてクロスコンパイルしてみる

 目的


TensorFlow LiteをRISC-Vターゲットにクロスコンパイルしてみる。

TensorFlow Liteに組み込まれているXNNPACKは、RISC-VターゲットにRISC-V Vector Extension Intrinsicsをサポートしている。RISC-V Vector Extension IntrinsicsはGCCはバージョン13から、LLVMも14あたりからRISC-V Vector Extension Intrinsics(rvv-intrinsics)をサポートしている。

今回は、GCC 13でクロスコンパイラのツールチェインをビルドし、TensorFlow Lite + XNNPACKをrvv-intrinsicsを有効としてクロスコンパイルできることを確認する。
GCC 13で対応しているrvv-intrinsicsはv0.11である。

なお、LLVMはバージョン16でないとビルドできないようである(XNNPACKで使用されるRVVのAPI名による)。LLVMを用いたクロスコンパイルは別の機会とする。

ビルドできることまでを確認として、実機やエミュレーターによる確認は別の機会とする。


環境


ホスト
  • WSL 2のUbuntu 22.04

ツールチェイン

TensorFlow Lite + XNNPACK


ビルド


TensorFlow Lite + XNNPACKをクロスコンパイルする。
大まかな手順としては、
  1. GCC 13としたRISC-V GNU Compiler Toolchainをビルド
  2. TensorFlow Lite + XNNPACKのビルド(libtensorflow-lite.a、benchmark_model)


クロスコンパイラのビルド


RISC-V GNU Compiler Toolchainのリポジトリをcloneし、必要なパッケージをインストールする。
必要なパッケージはリポジトリのREADMEに記載されている。
$ sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build
$ mkdir ${HOME}/riscv
$ git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git
$ cd riscv-gnu-toolchain

git submoduleをcloneし、GCCを13.1にbump upする。
$ git submodule update --init --recursive
$ cd gcc
$ git checkout releases/gcc-13.1.0
$ cd ..

ツールチェインをビルドする。
ビルドが成功した場合、${HOME}/riscv/toolchainにインストールされる。
$ ./configure --prefix=${HOME}/riscv/toolchain $ make linux -j$(nproc)
$ ls ${HOME}/riscv/toolchain
bin  include  lib  libexec  riscv64-unknown-linux-gnu  share  sysroot

これでRISC-Vのクロスコンパイラが用意できた。


TensorFlow Liteのビルド


次にTensorFlow Liteをビルドする。

リポジトリをcloneする。
$ cd ${HOME}/riscv
$ git clone https://github.com/tensorflow/tensorflow.git

一部ソースを修正する。
$ git diff tensorflow/lite/kernels/internal/spectrogram.cc
diff --git a/tensorflow/lite/kernels/internal/spectrogram.cc b/tensorflow/lite/kernels/internal/spectrogram.cc
index a832962a38d..3ee2d036dd4 100644
--- a/tensorflow/lite/kernels/internal/spectrogram.cc
+++ b/tensorflow/lite/kernels/internal/spectrogram.cc
@@ -17,6 +17,7 @@ limitations under the License.

 #include <assert.h>
 #include <math.h>
+#include <cstdint>

 #include "third_party/fft2d/fft.h"

修正しない場合、以下のビルドエラーが発生してしまう。
spectrogram.cc:46:22: error: 'uint32_t' was not declared in this scope
   46 | inline int Log2Floor(uint32_t n) {

あとはcmakeでconfigure後、ビルドすればよい。
(rvv-intrinsicをサポートしていないGCCの場合、XNNPACKのビルドでエラーとなってしまう)

TensorFlow Lite(libtensorflow-lite.a)のビルド
$ mkdir tflite_build && cd tflite_build
$ cmake \
    -DCMAKE_C_COMPILER=${HOME}/riscv/toolchain/bin/riscv64-unknown-linux-gnu-gcc \
    -DCMAKE_CXX_COMPILER=${HOME}/riscv/toolchain/bin/riscv64-unknown-linux-gnu-g++ \
    -DCMAKE_SYSROOT=${HOME}/riscv/toolchain/sysroot/ \
    -DCMAKE_SYSTEM_PROCESSOR="riscv64" \
    -DCMAKE_C_FLAGS="-march=rv64gcv" \
    -DCMAKE_CXX_FLAGS="-march=rv64gcv" \
    -DCMAKE_VERBOSE_MAKEFILE=ON \
    -DCMAKE_SYSTEM_NAME=Linux \
    ../tensorflow/tensorflow/lite/
$ cmake --build . -j$(nproc)
$ ls libtensorflow-lite.a
libtensorflow-lite.a

TensorFlow Lite Benchmark Tool(benchmark_model)のビルド
$ cmake --build . -j$(nproc) -t benchmark_model
$ ls tools/benchmark/benchmark_model
tools/benchmark/benchmark_model

libtensorflow-lite.a と benchmark_model がビルドできた。


最後に


Yoctoのmeta-tensorflow-liteのビルドエラーの際にXNNPACK_ENABLE_RISCV_VECTORフラグを知ってからようやく、ビルドができるようになった。
ただ、rvv-intrinsicsを有効としてみてどの程度違いがあるのかはよくわからない。
現在(2023.05時点)、個人が入手可能な利用できる実機もない気もする。。。
まずは、エミュレーターで動作確認してみる。


参考