1. 程式人生 > >Tensorflow lite android原始碼 中編譯整合

Tensorflow lite android原始碼 中編譯整合

之前一直是在使用的是tensorflow mobile,來作為模型的執行環境。但是,tensoflow mobile的libtensorflow_inference.so有19MB,load到記憶體裡以後,會佔用較多的記憶體。。。測試看下來,大概佔用20M,加上模型佔用記憶體,導致我們的模組,記憶體佔用變大了30MB。記憶體佔用偏高,因此想優化一下。

首先想到的手段是模型裁剪。

但是,只有裁剪模型的網路結構,才能降低記憶體佔用,可是這樣做,又會導致模型的準確率降低,因此放棄。

剩下一條路,就是抱著試一試的心態,嘗試換用較新的tensorflow lite了。

網上很多教程都是用gradle,或者brzel編譯使用tensorflow lite的,但是我想在Android原始碼裡編譯使用tensorflow lite。因此無法使用gradle或者brzel編譯。查了不少資料,折騰了兩天,終於搞定了。在這裡分享給大家。

編譯出適合手機的jar和so

Build TensorFlow Lite and the demo app from source

Clone the TensorFlow repo

git clone https://github.com/tensorflow/tensorflow

Install Bazel

If bazel is not installed on your system, see Installing Bazel.

Note: Bazel does not currently support Android builds on Windows. Windows users should download the 

prebuilt binary.

Install Android NDK and SDK

The Android NDK is required to build the native (C/C++) TensorFlow Lite code. The current recommended version is 14band can be found on the NDK Archives page.

The Android SDK and build tools can be downloaded separately or used as part of Android Studio

. To build the TensorFlow Lite Android demo, build tools require API >= 23 (but it will run on devices with API >= 21).

In the root of the TensorFlow repository, update the WORKSPACE file with the api_level and location of the SDK and NDK. If you installed it with Android Studio, the SDK path can be found in the SDK manager. The default NDK path is:{SDK path}/ndk-bundle. For example:

android_sdk_repository (
    name = "androidsdk",
    api_level = 23,
    build_tools_version = "23.0.2",
    path = "/home/xxxx/android-sdk-linux/",
)

android_ndk_repository(
    name = "androidndk",
    path = "/home/xxxx/android-ndk-r10e/",
    api_level = 19,
)

Some additional details are available on the TF Lite Android App page.

Build the source code

To build the demo app, run bazel:

bazel build --cxxopt=--std=c++11 //tensorflow/contrib/lite/java/demo/app/src/main:TfLiteCameraDemo

Caution: Because of an bazel bug, we only support building the Android demo app within a Python 2 environment.

就是這個"Some additional details are available on the TF Lite Android App page.",一定要點進去看。。。

Building from Source with Bazel

    • You'll need at least SDK version 23.
    • Make sure to install the latest version of Bazel. Some distributions ship with Bazel 0.5.4, which is too old.
    • Bazel requires Android Build Tools 26.0.1 or higher.
    • Bazel is incompatible with NDK revisions 15 and above, with revision 16 being a compile-breaking change.Download an older version manually instead of using the SDK Manager.
    • You also need to install the Android Support Repository, available through Android Studio under Android SDK Manager -> SDK Tools -> Android Support Repository.

一定要按照第一步的提示“Follow the Bazel steps for the TF Demo App:”,使用NDK14的版本,才能編譯成功。:P

官網最開始寫19。。。坑啊。。。各種編譯不過。我嘗試了19,17,16。。。都失敗了。。直到最後仔細檢視每個連結。。。仔細閱讀每篇教程。。才終於找到The current recommended version is 14b, which may be found here.

Bazel

NOTE: Bazel does not currently support building for Android on Windows. Full support for gradle/cmake builds is coming soon, but in the meantime we suggest that Windows users download the prebuilt binaries instead.

Install Bazel and Android Prerequisites

Bazel is the primary build system for TensorFlow. To build with Bazel, it and the Android NDK and SDK must be installed on your system.

  1. Install the latest version of Bazel as per the instructions on the Bazel website.

  2. The Android NDK is required to build the native (C/C++) TensorFlow code. The current recommended version is 14b, which may be found here.

    • NDK 16, the revision released in November 2017, is incompatible with Bazel. See here.
  3. The Android SDK and build tools may be obtained here, or alternatively as part of Android Studio. Build tools API >= 23 is required to build the TF Android demo (though it will run on API >= 21 devices).

    • The Android Studio SDK Manager's NDK installer will install the latest revision of the NDK, which is incompatiblewith Bazel. You'll need to download an older version manually, as (2) suggests.

Edit WORKSPACE

NOTE: As long as you have the SDK and NDK installed, the ./configure script will create these rules for you. Answer "Yes" when the script asks to automatically configure the ./WORKSPACE.

The Android entries in <workspace_root>/WORKSPACE must be uncommented with the paths filled in appropriately depending on where you installed the NDK and SDK. Otherwise an error such as: "The external label '//external:android/sdk' is not bound to anything" will be reported.

Also edit the API levels for the SDK in WORKSPACE to the highest level you have installed in your SDK. This must be >= 23 (this is completely independent of the API level of the demo, which is defined in AndroidManifest.xml). The NDK API level may remain at 14.

bazel編譯環境配置好後,就可以編譯了。

官網推薦的這個

bazel build --cxxopt=--std=c++11 //tensorflow/contrib/lite/java/demo/app/src/main:TfLiteCameraDemo

只能編譯出TfLiteCameraDemo的apk,

但是我想編譯出libtensorflowlite.jar和libtensorflowlite_jni.so,方便在Android原始碼環境裡編譯整合tensorflow lite,所以,在編譯tensorflowlite的原始碼時,需要調整一下bazel的編譯命令:

bazel build --cxxopt='--std=c++11' //tensorflow/contrib/lite/java:tensorflowlite --crosstool_top=//external:android/crosstool [email protected]_tools//tools/cpp:toolchain --cpu=arm64-v8a

然後,就能成功編譯出給arm64-v8a使用的libtensorflowlite.jar和libtensorflowlite_jni.so了。

想編譯支援其他型別的機器,修改--cpu引數即可。

Android原始碼裡編譯使用tensorflowlite

下面,就是在原始碼環境裡測試一下。

首先,把TfLiteCameraDemo的原始碼拷貝到Android原始碼目錄裡,然後新增Android.mk,這兩個配置是關鍵:

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := tensorflowlite:libs/libtensorflowlite.jar

LOCAL_PREBUILT_LIBS := libtensorflowlite_jni:libs/libtensorflowlite_jni.so

以前使用tensorflow mobile的時候,libtensorflow_inference.so是需要自己手動System.loadLibrary的。

但是我看了下TfLiteCameraDemo,沒有發現System.loadLibrary的程式碼。

於是,就去檢視TensorflowLite的原始碼,發現原來libtensorflowlite_jni.so已經在TensorflowLite里加載了。(所以,我們在Android.mk裡配置的so的名字,也必須是“libtensorflowlite_jni”,否則執行時會報錯,載入so失敗)

/** Static utility methods loading the TensorFlowLite runtime. */
public final class TensorFlowLite {

  private static final String LIBNAME = "tensorflowlite_jni";

  private TensorFlowLite() {}

  /** Returns the version of the underlying TensorFlowLite runtime. */
  public static native String version();

  /**
   * Load the TensorFlowLite runtime C library.
   */
  static boolean init() {
    try {
      System.loadLibrary(LIBNAME);
      return true;
    } catch (UnsatisfiedLinkError e) {
      System.err.println("TensorFlowLite: failed to load native library: " + e.getMessage());
      return false;
    }
  }

  static {
    init();
  }
}

然後在原始碼裡make一下,就成功了。

push進手機後,TfLiteCameraDemo成功識別出了鍵盤,記憶體佔用大概20M,這是UI activity + bitmap + tensorflowlite + mobileNet一共佔用的,而以前tensorflow mobile自己就能佔用20M了。

總結

原來tensoflow mobile的libtensorflow_inference.so有19M,而libtensorflowlite_jni.so只有1.5M,因此至少在載入tensorflow需要的native so這一塊,lite比mobile就節省了不少記憶體。

特別感謝這兩篇文章,為我提供了不少思路:

相關推薦

Tensorflow lite android原始碼 編譯整合

之前一直是在使用的是tensorflow mobile,來作為模型的執行環境。但是,tensoflow mobile的libtensorflow_inference.so有19MB,load到記憶體裡以後,會佔用較多的記憶體。。。測試看下來,大概佔用20M,加上模型佔用記憶體

Android原始碼編譯aidl

為什麼要這麼做? 1、因為專案中一些功能需要呼叫系統原始碼中的一些介面,上層無法訪問。所以想一些需要呼叫系統介面的方法用原始碼編譯,然後使用aidl暴露出介面,供上層呼叫。 準備工作: 1、應用端

Android原始碼如何吧so庫打包編譯進入apk, 整合第三方庫(jar和so庫)

整合第三方so和jar包 include $(CLEAR_VARS) #jar包編譯            LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES :=securitysdk:libs/hello.jar #64和32系統選擇不同的庫 if

Android android studio 專案放在原始碼編譯

app中有些許可權在Android studio下無法實現,如關機等,雖然配置了許可權,但是還是需要app簽名,因此將app直接放在 原始碼中進行編譯 一、首先將app程式碼放在原始碼中 1.可以放在vendor 目錄下自己專案的package/app/下面 2.可以放在vendor

如何單獨編譯Android原始碼的模組

      第一次下載好Android原始碼工程後,我們通常是在Android原始碼工程目錄下執行make命令,經過漫長的等待之後,就可以得到Android系統映象system.img了。以後如果我們修改了Android原始碼中的某個模組或者在Android原始碼工程新增一個

單獨編譯Android原始碼的模組

第一次下載好Android原始碼工程後,我們通常是在Android原始碼工程目錄下執行make命令,經過漫長的等待之後,就可以得到Android系統映象system.img了。以後如果我們修改了Android原始碼中的某個模組或者在Android原始碼工程新增一個自己的模組

單獨編譯Android原始碼的某個模組

       眾所周知,編譯一個韌體要花很久時間。有時只改系統的某個模組的某個功能,如修改系統Setting原始碼的一些地方,這時就沒有必要再整個系統編譯一遍,這時就需要用到模組編譯(前提是系統已經編譯過一遍)。       下面以編譯A20平臺原始碼中的一個apk為例。

Android原始碼引用@hide類出現引用異常的問題error: cannot find symbol

    自己開發的APP在Android中使用一些系統隱藏的類         編譯的時候報錯,出現如下異常 error: cannot find symbol import android.net.EthernetM

android原始碼採用Unix Domain Socket跨程序通訊

      今天看android原始碼Zygote程序啟動流程,無意間發現使用了一種檔案描述符作為跨程序通訊的地址,於是仔細研究了一下:  從字面來理解是傳統的Socket使用,但個人覺得不應該是,特地找資料學習了一下,下面的介紹比較詳細到位。又進一步瞭解一下,使用的其實是

android studio編譯單個檔案

網上搜到比較全的是這個:https://blog.csdn.net/u011368551/article/details/51980678 另外關於gradle如何編譯單個檔案,參考 https://blog.csdn.net/xcookies/article/details/79238456,但

Android 原始碼 寫後臺應用

在Android 開機啟動的時候會有一些後臺程序跑起來,當然我麼也可以定製 在vendor 的目錄中放置 一個Android.mk檔案還有一個server.cpp,標頭檔案配置 makefile配置 # LOCAL_PATH變數。它用於在開發樹中查詢原始檔 my

Android 原始碼的設計模式

面向物件的六大原則 單一職責原則   所謂職責是指類變化的原因。如果一個類有多於一個的動機被改變,那麼這個類就具有多於一個的職責。而單一職責原則就是指一個類或者模組應該有且只有一個改變的原因。通俗的說,即一個類只負責一項職責,將一組相關性很高的函式、資料封裝到一個類中。

android原始碼的設計模式

建造者模式 建造者模式最明顯的標誌就是Build類,而在Android中最常用的就是Dialog的構建,Notification的構建也是標準的建造者模式。 建造者模式很好理解,如果一個類的構造需要很多引數,而且這些引數並不都是必須的,那麼這種情況下就比較適合Builder。 比如構建一

android 原始碼預置帶.so檔案的APK

有原始碼有.so預置apk: LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := $(call all-java-files

Android原始碼的靜態工廠方法

我們知道工廠模式有三兄弟,通常我們說的工廠模式指的是工廠方法模式,它的應用頻率最高。本篇部落格分享的簡單工廠模式是工廠方法模式的“小弟”,確切的來講它不屬於設計模式,而是一種方法。此外,工廠方法模式還有一位“大哥”——抽象工廠模式。 今天我們來分享一下簡單工廠

Android原始碼增加模組

Android build system就是編譯系統的意思  在我們需要向自己編譯的原始碼中增加模組的時候,需要一些規則,當然這個規則都是類似的。 Android.mk檔案解析  讓我們來看一個 Android.mk 檔案的樣子  Java程式碼 LOCAL_PATH := $(call my-dir)i

通過清華大學映象下載Android原始碼編譯原始碼

    之前看原始碼都是在Windows下用SourceInsight看,雖然達到了研究原始碼的效果,但終究還是有遺憾。。。趁著週末,準備在Ubuntu虛擬機器上下載編譯原始碼。     之前下原始碼時,有了解一些Android原始碼的情況。網上的教程很多也是從谷歌官網下原始碼,但是最近藍燈不好用,FQ效率有

Android Studio 編譯JDK 版本配置

RT,今天碰到的問題是我想用1.7結果預設是1.6 解決方案如下: 修改 build.gradle 檔案 android { compileSdkVersion 19 buildToolsVersion "19.0.0" defaultCo

Android原始碼怎麼編譯adb?

編譯系統是Ubuntu 16.04,64位,Android原始碼版本為5.0.2和4.4。 編譯adb不需要先把整個原始碼都編譯通過,下載到的原始碼直接就可以編出adb。 下面是編譯過程: 1. 在終端cd到Android原始碼根目錄 2. 準備編譯環境

Android原始碼編譯(4.4.2)

    今天主要為大家敘說下Android原始碼的編譯,其實一開始說起Andriod原始碼的編譯,我的心裡就沒底,有一種很懼怕的感覺,因為,我就想,那麼龐大的一個系統,如果出了問題,我該怎麼解決呢,還好,度娘和google哥哥給我提供了不少幫助(這其實得益於先驅們的貢獻),