目的
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
ツールチェイン
-
RISC-V GNU Compiler Toolchain
利用したコミットは"7f8b34c01dd806e49e0538b2d3779f753963e774"。
ただし、この時点ではGCC 12であり、rvv-intrinsicsを利用できない。
このため、GCC 13にbump upする。
bump gcc to 13.1 release #1239のPRも参照。
TensorFlow Lite + XNNPACK
-
TensorFlow Lite
利用したコミットは"60f733b8935c910fef466e44afe0c7f6c984e1ab"。
ビルドエラーが発生するため、一部コードを修正する(後述)。 - XNNPACK
-
TensorFlow Liteで指定のコミットがgit cloneされる。
https://github.com/tensorflow/tensorflow/blob/60f733b8935c910fef466e44afe0c7f6c984e1ab/tensorflow/lite/tools/cmake/modules/xnnpack.cmake#L26 -
CMakeLists.txtには「XNNPACK_ENABLE_RISCV_VECTOR」フラグがある。
フラグのコメント:"Build XNNPACK with RISC-V Vector micro-kernels"
これにより、rvv-intrinsicsが有効なコードをビルド対象としている。
なお、デフォルトはONであるため、未サポートのコンパイラ等の場合、フラグをOFFにする必要がある。
https://github.com/google/XNNPACK/blob/b9d4073a6913891ce9cbd8965c8d506075d2a45a/CMakeLists.txt#L81 -
対象のコードはスクリプトにより生成されているようだ。
例)
https://github.com/google/XNNPACK/blob/ccfee7043a30babb9e3aec70b342fcc743a260d2/scripts/generate-f32-vclamp.sh#L29
ビルド
TensorFlow Lite + XNNPACKをクロスコンパイルする。
大まかな手順としては、
- GCC 13としたRISC-V GNU Compiler Toolchainをビルド
- 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時点)、個人が入手可能な利用できる実機もない気もする。。。
まずは、エミュレーターで動作確認してみる。
参考
-
GCC 13 Release Series Changes, New Features, and Fixes
-
RISC-V Vector Extension Intrinsic Document v0.11.x
-
ExCALIBUR H&ES RISC-V testbed - Toolchains & Cross-debugging
-
riscv-v-spec-japanese - RISC-V "V" ベクトル拡張
Configure the CMake build with -DXNN_ENABLE_RISCV_VECTOR=OFF or Bazel build with --define xnn_enable_riscv_vector=false to disable building microkernels for the RISC-V "V" extension
— Marat Dukhan (@MaratDukhan) March 6, 2023