Skip to content

[Android demo] Decouple pte file from assets and remove unused #8906

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 5, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 39 additions & 100 deletions examples/demo-apps/android/ExecuTorchDemo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,14 @@ We generate the model file for the ExecuTorch runtime in Android Demo App.
For delegating DeepLab v3 to XNNPACK backend, please do the following to export the model:

```bash
cd executorch # go to executorch root
python3 -m examples.xnnpack.aot_compiler --model_name="dl3" --delegate
mkdir -p examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/
cp dl3_xnnpack_fp32.pte examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/
```

Then push the pte file to Android device:

```bash
adb push dl3_xnnpack_fp32.pte /data/local/tmp/dl3_xnnpack_fp32.pte
```

For more detailed tutorial of lowering to XNNPACK, please see [XNNPACK backend](backends-xnnpack.md).
Expand All @@ -50,135 +55,69 @@ For more detailed tutorial of lowering to XNNPACK, please see [XNNPACK backend](

For delegating to Qualcomm Hexagon NPU, please follow the tutorial [here](backends-qualcomm.md).

After generating the model, copy the model to `assets` directory.

```bash
python -m examples.qualcomm.scripts.deeplab_v3 -b build-android -m SM8450 -s <adb_connected_device_serial>
cp deeplab_v3/dlv3_qnn.pte examples/demo-apps/android/ExecuTorchDemo/app/src/main/assets/
```

Then push the pte file to Android device:

```bash
adb push deeplab_v3/dlv3_qnn.pte /data/local/tmp/dlv3_qnn.pte
```

### Runtime

We build the required ExecuTorch runtime library to run the model.
We build the required ExecuTorch runtime library (AAR) to run the model.

#### XNNPACK

1. Build the CMake target for the library with XNNPACK backend:
1. Build the AAR target for the library with XNNPACK backend:

```bash
# go to ExecuTorch repo root
export ANDROID_NDK=<path-to-android-ndk>
export ANDROID_ABI=arm64-v8a
export ANDROID_ABIS=arm64-v8a

# Run the following lines from the `executorch/` folder
./install_executorch.sh --clean
mkdir cmake-android-out

# Build the core executorch library
cmake . -DCMAKE_INSTALL_PREFIX=cmake-android-out \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI="${ANDROID_ABI}" \
-DEXECUTORCH_BUILD_XNNPACK=ON \
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=ON \
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
-Bcmake-android-out

cmake --build cmake-android-out -j16 --target install
```

When we set `EXECUTORCH_BUILD_XNNPACK=ON`, we will build the target [`xnnpack_backend`](https://github.com/pytorch/executorch/blob/main/backends/xnnpack/CMakeLists.txt) which in turn is linked into libexecutorch_jni via [CMake](https://github.com/pytorch/executorch/blob/main/examples/demo-apps/android/jni/CMakeLists.txt).

2. Build the Android extension:

```bash

# Build the android extension
cmake extension/android \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}"/build/cmake/android.toolchain.cmake \
-DANDROID_ABI="${ANDROID_ABI}" \
-DCMAKE_INSTALL_PREFIX=cmake-android-out \
-Bcmake-android-out/extension/android

cmake --build cmake-android-out/extension/android -j16
# Build the AAR. It will include XNNPACK backend by default.
sh build/build_android_library.sh
```

`libexecutorch_jni.so` wraps up the required XNNPACK Backend runtime library from `xnnpack_backend`, and adds an additional JNI layer using fbjni. This is later exposed to Java app.
2. In ExecuTorchDemo root, create a new directory `app/libs` and copy the AAR there.
```bash
# go to ExecuTorchDemo root
mkdir -p app/libs
cp "$BUILD_AAR_DIR/executorch.aar" app/libs
````

#### Qualcomm Hexagon NPU

1. Build the CMake target for the library with Qualcomm Hexagon NPU (HTP) backend (XNNPACK also included):
1. Build the AAR target for the library with XNNPACK and QNN backend:

```bash
# go to ExecuTorch repo root
export ANDROID_NDK=<path-to-android-ndk>
export ANDROID_ABI=arm64-v8a
export QNN_SDK_ROOT=<path-to-qnn-sdk>
export ANDROID_ABIS=arm64-v8a
export QNN_SDK_ROOT=<path-to-qnn-sdk-root>

# Run the following lines from the `executorch/` folder
./install_executorch.sh --clean
mkdir cmake-android-out
cmake . -DCMAKE_INSTALL_PREFIX=cmake-android-out \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}/build/cmake/android.toolchain.cmake" \
-DANDROID_ABI="${ANDROID_ABI}" \
-DEXECUTORCH_BUILD_XNNPACK=ON \
-DEXECUTORCH_BUILD_QNN=ON \
-DQNN_SDK_ROOT="${QNN_SDK_ROOT}" \
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=ON \
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
-Bcmake-android-out

cmake --build cmake-android-out -j16 --target install
```
Similar to the XNNPACK library, with this setup, we compile `libexecutorch_jni.so` but it adds an additional static library `qnn_executorch_backend` which wraps up Qualcomm HTP runtime library and registers the Qualcomm HTP backend. This is later exposed to Java app.

`qnn_executorch_backend` is built when we turn on CMake option `EXECUTORCH_BUILD_QNN`. It will include the [CMakeLists.txt](https://github.com/pytorch/executorch/blob/main/backends/qualcomm/CMakeLists.txt) from backends/qualcomm where we `add_library(qnn_executorch_backend STATIC)`.

2. Build the Android extension:

```bash
cmake extension/android \
-DCMAKE_TOOLCHAIN_FILE="${ANDROID_NDK}"/build/cmake/android.toolchain.cmake \
-DANDROID_ABI="${ANDROID_ABI}" \
-DCMAKE_INSTALL_PREFIX=cmake-android-out \
-Bcmake-android-out/extension/android

cmake --build cmake-android-out/extension/android -j16
```

## Deploying on Device via Demo App

### Steps for Deploying Model via XNNPACK

```bash
mkdir -p examples/demo-apps/android/ExecuTorchDemo/app/src/main/jniLibs/arm64-v8a
cp cmake-android-out/extension/android/libexecutorch_jni.so \
examples/demo-apps/android/ExecuTorchDemo/app/src/main/jniLibs/arm64-v8a/libexecutorch.so
```

This allows the Android app to load ExecuTorch runtime with XNNPACK backend as a JNI library. Later, this shared library will be loaded by `NativePeer.java` in Java code.

### Steps for Deploying Model via Qualcomm's AI Engine Direct

```bash
mkdir -p ../examples/demo-apps/android/ExecuTorchDemo/app/src/main/jniLibs/arm64-v8a
# Build the AAR. It will include XNNPACK and QNN backend now.
sh build/build_android_library.sh
```

We need to push some additional Qualcomm HTP backend libraries to the app. Please refer to [Qualcomm docs](backends-qualcomm.md) here.
This is very similar to XNNPACK setup, but users now needs to define `QNN_SDK_ROOT` so that
QNN backend is built into the AAR.

2. In ExecuTorchDemo root, create a new directory `app/libs` and copy the AAR there.
```bash
cp ${QNN_SDK_ROOT}/lib/aarch64-android/libQnnHtp.so ${QNN_SDK_ROOT}/lib/hexagon-v69/unsigned/libQnnHtpV69Skel.so ${QNN_SDK_ROOT}/lib/aarch64-android/libQnnHtpV69Stub.so ${QNN_SDK_ROOT}/lib/aarch64-android/libQnnSystem.so \
examples/demo-apps/android/ExecuTorchDemo/app/src/main/jniLibs/arm64-v8a
```

Copy the core libraries:

```bash
cp cmake-android-out/extension/android/libexecutorch_jni.so \
examples/demo-apps/android/ExecuTorchDemo/app/src/main/jniLibs/arm64-v8a/libexecutorch.so
cp cmake-android-out/lib/libqnn_executorch_backend.so \
examples/demo-apps/android/ExecuTorchDemo/app/src/main/jniLibs/arm64-v8a/libqnn_executorch_backend.so
```
# go to ExecuTorchDemo root
mkdir -p app/libs
cp "$BUILD_AAR_DIR/executorch.aar" app/libs
````

## Running the App

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ dependencies {
implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha12")
implementation("com.facebook.soloader:soloader:0.10.5")
implementation("com.facebook.fbjni:fbjni:0.5.1")
implementation("org.pytorch.executorch:executorch") {
exclude("com.facebook.fbjni", "fbjni-java-only")
}
implementation(files("libs/executorch.aar"))
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
Expand All @@ -72,8 +70,8 @@ dependencies {
tasks.register("setup") {
doFirst {
exec {
commandLine("sh", "examples/demo-apps/android/LlamaDemo/setup.sh")
workingDir("../../../../../")
commandLine("sh", "setup.sh")
workingDir("../")
}
}
}
2 changes: 0 additions & 2 deletions examples/demo-apps/android/ExecuTorchDemo/app/src/main/BUCK
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ fb_android_resource(
fb_android_library(
name = "app_lib",
srcs = [
"java/com/example/executorchdemo/ClassificationActivity.java",
"java/com/example/executorchdemo/ImageNetClasses.java",
"java/com/example/executorchdemo/MainActivity.java",
"java/com/example/executorchdemo/TensorImageUtils.java",
],
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

Loading
Loading