Raspberry Pi4 で TensorFlow Lite GPU Delegate (OpenGLES) を試す

1. はじめに

 ラズパイ4の OpenGLES はリリース当初 ver 3.0 でしたが、2020/1月に ver 3.1 にアップデートされました
 OpenGLES 3.1 になると、ComputeShader が使えるようになります。超うれしいアップデートです。

 一方 TensorFlow Lite には、推論にかかる演算処理を CPUからGPU にオフロードする GPU Delegate という機能があります。
この GPU Delegate には、さらに V1(OpenGLES)V2(OpenCL/OpenGLES) とがあり、OpenGLES 3.1 が使える環境であれば動かすことができます。

 本記事は、ラズパイ4の OpenGLES 3.1 環境で TensorFlow Lite GPU Delegate V1 (OpenGLES) を動かす方法についてまとめたものです。
 記事の通りにコマンド入力すればどなたでも動かせることを目標に書いています。

 なお、題材は Posenet を用い、結果表示も OpenGLES で行います。
gl2posenet_m.png

 ■(ご参考)
  ・Coral Edge TPU Dev Board で TensorFlow Lite GPU Delegate V1(OpenGLES) を試す
  ・Coral Edge TPU Dev Board で TensorFlow Lite GPU Delegate V2 (OpenCL) を試す

2. 作業手順

 ラズパイで TFLite GPU Delegate アプリを動かすまでの手順として、大きく2つのステップを踏みます。
 ・(step1) 最初にホストPCで TFLite GPUDelegate ライブラリを armv7l クロスビルドし、それをラズパイ実機にコピー
 ・(step2) ラズパイでサンプルアプリをコンパイル、上記 TFLite GPUDelegate ライブラリをリンク、実行

 以下、このステップごとに説明します。

2.1 ホストPCでの作業

 ホストPCとして x86_64 Ubuntu 18.04 で作業しました。
 ラズパイで使うための TensorFlow Lite ライブラリをビルドします。

2.1.1 (前準備) Bazelのインストール

 あらかじめ Bazel をインストールしておきます。
 今回は TensorFlow 2.0 をベースに作業を行うため、Bazel 0.26.1 をインストールします。

# (前準備) Bazel 0.26.1 のインストール
$ wget https://github.com/bazelbuild/bazel/releases/download/0.26.1/bazel-0.26.1-installer-linux-x86_64.sh
$ chmod 755 bazel-0.26.1-installer-linux-x86_64.sh
$ sudo ./bazel-0.26.1-installer-linux-x86_64.sh

2.1.2 TFLite GPUDelegate ライブラリのビルド

 GPUDelegateを有効にした状態で TFLiteライブラリをビルドするのはいろいろと面倒 (詳細を知りたい方はこちら) なので、コマンド一発でビルドできるようなスクリプトを用意しています。

# GPUDelegate 有効版 TensorFlow Lite ライブラリをビルド
$ cd ~/work 

# TFLiteライブラリビルド用のスクリプトをGitHubから取得
$ git clone https://github.com/terryky/tflite_gles_app.git

# TFLiteライブラリビルド実行
$ ./tflite_gles_app/tools/scripts/tf2.0/build_libtflite_r2.0_with_gpu_delegate_rpi.sh

 スクリプトを実行すると、しばらくして、configure コマンドによるプロンプト待ちになります。
 デフォルト設定で大丈夫だと思いますので、Enterを連射してください。
 ビルドログの抜粋は下記のとおりです。最後に、libtensorflow-lite.a が出来上がるはずです。

Cloning into '/home/terryky/work/tensorflow_r2.0'...
remote: Enumerating objects: 11, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 817557 (delta 2), reused 9 (delta 0), pack-reused 817546
Receiving objects: 100% (817557/817557), 469.27 MiB | 5.79 MiB/s, done.
Resolving deltas: 100% (661446/661446), done.
Checking out files: 100% (19378/19378), done.
Branch 'r2.0' set up to track remote branch 'r2.0' from 'origin'.
Switched to a new branch 'r2.0'
patching file tensorflow/lite/delegates/gpu/gl/gl_buffer.cc
patching file tensorflow/lite/delegates/gpu/gl/gl_call.h
patching file tensorflow/lite/delegates/gpu/gl/gl_errors.cc
patching file tensorflow/lite/delegates/gpu/gl/gl_program.cc
patching file tensorflow/lite/delegates/gpu/gl/gl_shader.cc
patching file tensorflow/lite/delegates/gpu/gl/gl_sync.cc
patching file tensorflow/lite/delegates/gpu/gl/gpu_info.cc
patching file tensorflow/lite/delegates/gpu/gl/kernels/conv.cc
patching file tensorflow/lite/delegates/gpu/gl_delegate.cc
patching file tensorflow/lite/tools/make/Makefile
Starting local Bazel server and connecting to it...
INFO: Options provided by the client:
  Inherited 'common' options: --isatty=1 --terminal_columns=161
INFO: Reading rc options for 'clean' from /home/terryky/work/tensorflow_r2.0/.bazelrc:
  Inherited 'build' options: --apple_platform_type=macos --define framework_shared_object=true --define open_source_build=true --define=use_fast_cpp_protos=true --define=allow_oversize_protos=true --spawn_strategy=standalone -c opt --announce_rc --define=grpc_no_ares=true --define=PREFIX=/usr --define=LIBDIR=$(PREFIX)/lib --define=INCLUDEDIR=$(PREFIX)/include --copt=-w --config=v2
INFO: Found applicable config definition build:v2 in file /home/terryky/work/tensorflow_r2.0/.bazelrc: --define=tf_api_version=2 --action_env=TF2_BEHAVIOR=1
INFO: Starting clean (this may take a while). Consider using --async if the clean takes more than several minutes.
----------------------------------------------------
 (configure) press ENTER-KEY several times.
----------------------------------------------------
WARNING: Running Bazel server needs to be killed, because the startup options are different.
WARNING: Waiting for server process to terminate (waited 5 seconds, waiting at most 60)
WARNING: --batch mode is deprecated. Please instead explicitly shut down your Bazel server using the command "bazel shutdown".
You have bazel 0.26.1 installed.
Please specify the location of python. [Default is /usr/bin/python]:

★ここでEnterを数回押してください★

(略)

----------------------------------------------------
 build success.
----------------------------------------------------
合計 28696
-rw-rw-r-- 1 terryky terryky 19761050  2月  1 15:45 benchmark-lib.a
-rw-rw-r-- 1 terryky terryky  9618448  2月  1 15:45 libtensorflow-lite.a

2.1.3 ビルドできたTFLiteライブラリをラズパイ実機へコピー

2.1.2 で作った libtensorflow-lite.a を ラズパイ実機へ scp します。
とりあえずラズパイ実機上のホーム直下にコピーしておきます。

$ scp ~/work/tensorflow_r2.0/tensorflow/lite/tools/make/gen/rpi_armv7l/lib/libtensorflow-lite.a pi@192.168.11.11:/home/pi/

2.2 ラズパイ実機での作業

 ここからはラズパイ実機上での作業となります。
 ホストPCで作った libtensorflow-lite.a を使ってアプリをビルドしていきます。

2.2.1 (前準備) OpenGLES ライブラリの更新

 ラズパイにインストールされている OpenGLES ライブラリが ver 3.0 のままだと GPUDelegate は動かせないので、最新版に更新します。

$ sudo apt install libgles2-mesa-dev libegl1-mesa-dev xorg-dev
$ sudo apt update
$ sudo apt upgrade

 念のため、OpenGLES 3.1 が使える状態になっていることを確認しておきましょう。

# サンプルアプリのソースをGitHubから取得
$ cd ~/work
$ git clone https://github.com/terryky/tflite_gles_app.git
$ cd tflite_gles_app/list_egl_configs
$ make TARGET_ENV=raspi4
$ ./list_egl_config

()
============================================
    GL INFO
============================================
GL_VERSION      : OpenGL ES 3.1 Mesa 19.3.2   # OpenGLES 3.1 が使える!
GL_SL_VERSION   : OpenGL ES GLSL ES 3.10
GL_VENDOR       : Broadcom
GL_RENDERER     : V3D 4.2
()

2.2.2 TFLiteヘッダファイルの取得

 アプリでTFLite の C++ APIを叩くために必要なヘッダファイルをダウンロードします。
 今回のサンプルアプリは、これらのヘッダが $HOME/work/tensorflow 以下にダウンロードされている前提で Makefile が書かれているのでご注意ください。

# GitHub から TensorFlow のソースコードを取得
$ cd ~/work
$ git clone https://github.com/tensorflow/tensorflow.git
$ cd tensorflow

# r2.0 ブランチを使う
$ git checkout r2.0

# 依存ライブラリのヘッダをダウンロード
$ ./tensorflow/lite/tools/make/download_dependencies.sh

2.2.3 TFLiteサンプルアプリのビルド

 いよいよアプリのビルドです。

# サンプルアプリのソースをGitHubから取得
$ cd ~/work
$ git clone https://github.com/terryky/tflite_gles_app.git
$ cd tflite_gles_app/gl2posenet

# ホストPCでビルドした TFLite ライブラリをアプリと同じディレクトリにコピー
$ cp ~/libtensorflow-lite.a .

# ラズパイ4用にGPUDelegate有効にしてアプリをビルド
$ make clean
$ make TARGET_ENV=raspi4 TFLITE_DELEGATE=GL_DELEGATE

# アプリ実行
$ ./gl2posenet

2.2.4 実行結果

アプリを実行すると、下記のようなウィンドウが表示されると思います。
GPUDelegate 有効にした状態で、posenet の推論にかかる処理時間は 1544[ms] でした。

(ご参考)
 もしUSBカメラがささっていればその映像で姿勢認識するように作っています。
 ただ、対応ピクセルフォーマットが YUYV (YUV422) 決め打ちなので、カメラによっては動かないかもしれません。
 その場合は USBカメラぬいてください。すみません。

rpi4_tflite_gpudelegate.png

2.2.5 (ご参考) GPUDelegate 使わない場合

 アプリビルド時に、TFLITE_DELEGATE を指定せずに make すると GPUDelegateを使わないバージョンとしてアプリをビルドすることができます。

# ラズパイ4用にアプリをビルド (GPUDelegateなし)
$ make clean
$ make TARGET_ENV=raspi4

# アプリ実行
$ ./gl2posenet

 GPUDelegate を使わない場合のスクリーンキャプチャはこちら。
 推論にかかる処理時間は 214[ms] でした。ラズパイ4だと、GPUDelegate 使わないほうが速いようです。
rpi4_tflite.png

3. 最後に

 ラズパイ4で TFLite GPU Delegate を動かす具体的な手順について書きました。
 
 ラズパイとして初となる OpenGLES 3.1 Compute Shader がハングせずに動いたことは素直に感動しましたが、残念ながらその速度性能はCPUより7倍も遅いという残念な結果となりました。

 ラズパイの Compute Shader 性能については、ラズパイ用OpenGLESライブラリの開発者と思われる方の興味深い発言がありましたので引用しておきます。

https://blogs.igalia.com/itoral/2020/01/17/raspberry-pi-4-v3d-driver-gets-opengl-es-3-1-conformance/
rpi_gles3.1.png

Jochen:「TFLite GPU delegate が CPU より3~4倍も遅いんだけど」
Iago Toral:「(現状OpenGLESの実装は) WorkItemが1個しか動かないようにハードコーディングしてるよ。この数を増やして並列度を高めれば性能あがるだろうから、そのうち調べないとね」

 開発者の方も OpenGLES の性能チューニングの必要性を認識されているとのこと。期待して待とうと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account