Help us understand the problem. What is going on with this article?

libtensorflow_inference r1.15 を Android 向けにビルドするメモ

背景

  • C/C++ で, 既存 r1.x 系の Tensorflow(C binding) 推論アプリを Android でも動かしたい
    • 速度はそんなに問わないし, そもそも tflite では動かないモデルがある
    • Java レイヤーは使わない

tensorflow + Android で検索するとだいたい tflite がヒットしてしまいますが, ここでは本来の(?)libtensorflow を Android 向けにビルドしてみます.

モバイルでは tflite 推奨で, libtensorflow のモバイル向けビルドは非推奨となっています.
とはいえ, そもそも tflite では動かないケースが多いので(特に RNN とか使っていたりする音声系), 頑張って libtensorflow を動かしてみます.

libtensorflow on Android では, CPU のみの対応になります.
現状 C++ API のみのようです. また, 使える C++ API には制約があります
(C API は根本からビルドを変えないといけないことが分かりましたので, 現状無理(or Bazel ファイルを頑張って解析&改修する必要がある))

TensorFlow は r2.x が出ていますが, ここでは r1.15 を使います.

ビルド方法(Bazel)

TensorFlow の ./configure で, Android WORKSPACE の作成を yes にしておきます.

今回は ndk r21, Android API level 26, Android SDK tool 29 あたりを使いました.
(2020 年 02 月 12 日での概ね最新)

https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tools/ci_build/builds/android_full.sh

を参考にビルドします.

    bazel build --config=monolithic --cpu=arm64-v8a \
        --compilation_mode=opt --cxxopt=-std=c++11 \
        --crosstool_top=//external:android/crosstool \
        --host_crosstool_top=@bazel_tools//tools/cpp:toolchain \
        //tensorflow/core:android_tensorflow_lib \
        //tensorflow/tools/android/inference_interface:libtensorflow_inference.so \
        //tensorflow/examples/android:libtensorflow_demo.so \
        //tensorflow/tools/benchmark:benchmark_model

という感じで .so までビルドできるはずです. ビルドには, Threadripper 1950X で 10 分ほど時間かかります. libtensorflow_inference.so まででよくて, 最後のほうは動作確認用などとしてお好みで.

C++ std は, tf のバージョンによって変わります. v1.15.2 では c++11 でした. v2 では c++14 でした.

benchmark_model までビルドしている場合, benchmark_model/data/local/tmp などに adb push して走らせて動くかどう確認しましょう

https://github.com/tensorflow/tensorflow/tree/r1.15/tensorflow/tools/benchmark

自前アプリに組み込む

TensorFlow C++(libtensorflow_cc.so) で推論アプリを CMake でビルドする(r1.8 対象)
https://qiita.com/syoyo/items/c102611ff63a6bbadc80

を参考に, ヘッダファイルへパスを通し(eigen, protobuf, absl は bazel のビルドディレクトリにあるものへパスを通す), libtensorflow_inference.so と, bazel-genfiles/external/com_google_protobuf あたりにある libprotobuf.pic.a, libprotobuf_lite.pic.a をリンクすればいけるはずです!

(libprotobuf と libprotobuf_lite の関係性は不明だが, 両方をリンクしないとうまくいかない).

もし, 他にリンク時にシンボルが見つからないエラーがでるようであれば,

Linux で, 複数 .a, .so のどこに C++ シンボルが定義されているか調べる
https://qiita.com/syoyo/items/cac44f37832b5f0e2bac

や, bazel のビルドログ表示(--subcommands or -s)でどのライブラリとリンクすればいいのかチェックしてみましょう.

NDK のバージョンは, libtensorflow_inference をビルドしたときのものと合わせておきましょう
(そうでないと, 特に protobuf 周りでエラーが出る)

C API ?

Android プロジェクトであればあまり ABI などでのリンクエラーは出ないと思うので, TF の呼び出しを C++ で書いてもいいと思いますが, Windows での TF アプリとコードを一緒にしたい(Windows では C API でないといろいろリンクエラーなど出てめんどいため)などで, C API を使いたいときもあります.

Android の libtensorflow_inference.so 用 Bazel BUILD ファイルでは, C API のライブラリは含まれていませんでした.

自前で tensorflow/c にある c_api.cc あたりのファイルをアプリに取り込んでビルドする必要がありそうですが, 現状足りないシンボルエラーが出てきてうまくいきません.

libtensorflow_inference.so を作る時点で, 足りない(private になっている?) ソースコードを追加しないとダメそうです. いろいろ調べるのがめんどいので, 現状は C++ API で頑張りましょう.

TODO

  • C API interface の .so を作る.
  • Makefile ベースのビルドを試す(tensorflow/contrib/makefile)
  • TensorFlow r2.x で試す
  • java バインディング含んだ prebuilt .so が C++ アプリにそのままつかえるか試す(ヘッダファイルを .so の tf version と合わせればいけそう)
  • 相変わらず bazel + protobuf 周りでエラー出たりで tensorflow 辛すぎるので, はやく libtorch mobile に移行して幸せになりたい
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
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした