xref: /aosp_15_r20/external/pytorch/android/README.md (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1*da0073e9SAndroid Build Coastguard Worker# Android
2*da0073e9SAndroid Build Coastguard Worker
3*da0073e9SAndroid Build Coastguard Worker## Demo applications and tutorials
4*da0073e9SAndroid Build Coastguard Worker
5*da0073e9SAndroid Build Coastguard WorkerDemo applications with code walk-through can be find in [this github repo](https://github.com/pytorch/android-demo-app).
6*da0073e9SAndroid Build Coastguard Worker
7*da0073e9SAndroid Build Coastguard Worker## Publishing
8*da0073e9SAndroid Build Coastguard Worker
9*da0073e9SAndroid Build Coastguard Worker##### Release
10*da0073e9SAndroid Build Coastguard WorkerRelease artifacts are published to jcenter:
11*da0073e9SAndroid Build Coastguard Worker
12*da0073e9SAndroid Build Coastguard Worker```groovy
13*da0073e9SAndroid Build Coastguard Workerrepositories {
14*da0073e9SAndroid Build Coastguard Worker    jcenter()
15*da0073e9SAndroid Build Coastguard Worker}
16*da0073e9SAndroid Build Coastguard Worker
17*da0073e9SAndroid Build Coastguard Worker# lite interpreter build
18*da0073e9SAndroid Build Coastguard Workerdependencies {
19*da0073e9SAndroid Build Coastguard Worker    implementation 'org.pytorch:pytorch_android_lite:1.10.0'
20*da0073e9SAndroid Build Coastguard Worker    implementation 'org.pytorch:pytorch_android_torchvision_lite:1.10.0'
21*da0073e9SAndroid Build Coastguard Worker}
22*da0073e9SAndroid Build Coastguard Worker
23*da0073e9SAndroid Build Coastguard Worker# full jit build
24*da0073e9SAndroid Build Coastguard Workerdependencies {
25*da0073e9SAndroid Build Coastguard Worker    implementation 'org.pytorch:pytorch_android:1.10.0'
26*da0073e9SAndroid Build Coastguard Worker    implementation 'org.pytorch:pytorch_android_torchvision:1.10.0'
27*da0073e9SAndroid Build Coastguard Worker}
28*da0073e9SAndroid Build Coastguard Worker```
29*da0073e9SAndroid Build Coastguard Worker
30*da0073e9SAndroid Build Coastguard Worker##### Nightly
31*da0073e9SAndroid Build Coastguard Worker
32*da0073e9SAndroid Build Coastguard WorkerNightly(snapshots) builds are published every night from `master` branch to [nexus sonatype snapshots repository](https://oss.sonatype.org/#nexus-search;quick~pytorch_android)
33*da0073e9SAndroid Build Coastguard Worker
34*da0073e9SAndroid Build Coastguard WorkerTo use them repository must be specified explicitly:
35*da0073e9SAndroid Build Coastguard Worker```groovy
36*da0073e9SAndroid Build Coastguard Workerrepositories {
37*da0073e9SAndroid Build Coastguard Worker    maven {
38*da0073e9SAndroid Build Coastguard Worker        url "https://oss.sonatype.org/content/repositories/snapshots"
39*da0073e9SAndroid Build Coastguard Worker    }
40*da0073e9SAndroid Build Coastguard Worker}
41*da0073e9SAndroid Build Coastguard Worker
42*da0073e9SAndroid Build Coastguard Worker# lite interpreter build
43*da0073e9SAndroid Build Coastguard Workerdependencies {
44*da0073e9SAndroid Build Coastguard Worker    ...
45*da0073e9SAndroid Build Coastguard Worker    implementation 'org.pytorch:pytorch_android_lite:1.12.0-SNAPSHOT'
46*da0073e9SAndroid Build Coastguard Worker    implementation 'org.pytorch:pytorch_android_torchvision_lite:1.12.0-SNAPSHOT'
47*da0073e9SAndroid Build Coastguard Worker    ...
48*da0073e9SAndroid Build Coastguard Worker}
49*da0073e9SAndroid Build Coastguard Worker
50*da0073e9SAndroid Build Coastguard Worker# full jit build
51*da0073e9SAndroid Build Coastguard Workerdependencies {
52*da0073e9SAndroid Build Coastguard Worker    ...
53*da0073e9SAndroid Build Coastguard Worker    implementation 'org.pytorch:pytorch_android:1.12.0-SNAPSHOT'
54*da0073e9SAndroid Build Coastguard Worker    implementation 'org.pytorch:pytorch_android_torchvision:1.12.0-SNAPSHOT'
55*da0073e9SAndroid Build Coastguard Worker    ...
56*da0073e9SAndroid Build Coastguard Worker}
57*da0073e9SAndroid Build Coastguard Worker```
58*da0073e9SAndroid Build Coastguard WorkerThe current nightly(snapshots) version is the value of `VERSION_NAME` in `gradle.properties` in current folder, at this moment it is `1.8.0-SNAPSHOT`.
59*da0073e9SAndroid Build Coastguard Worker
60*da0073e9SAndroid Build Coastguard Worker## Building PyTorch Android from Source
61*da0073e9SAndroid Build Coastguard Worker
62*da0073e9SAndroid Build Coastguard WorkerIn some cases you might want to use a local build of pytorch android, for example you may build custom libtorch binary with another set of operators or to make local changes.
63*da0073e9SAndroid Build Coastguard Worker
64*da0073e9SAndroid Build Coastguard WorkerFor this you can use `./scripts/build_pytorch_android.sh` script.
65*da0073e9SAndroid Build Coastguard Worker```bash
66*da0073e9SAndroid Build Coastguard Workergit clone https://github.com/pytorch/pytorch.git
67*da0073e9SAndroid Build Coastguard Workercd pytorch
68*da0073e9SAndroid Build Coastguard Workergit submodule update --init --recursive
69*da0073e9SAndroid Build Coastguard Workerbash ./scripts/build_pytorch_android.sh
70*da0073e9SAndroid Build Coastguard Worker```
71*da0073e9SAndroid Build Coastguard Worker
72*da0073e9SAndroid Build Coastguard WorkerThe workflow contains several steps:
73*da0073e9SAndroid Build Coastguard Worker
74*da0073e9SAndroid Build Coastguard Worker1\. Build libtorch for android for all 4 android abis (armeabi-v7a, arm64-v8a, x86, x86_64)
75*da0073e9SAndroid Build Coastguard Worker
76*da0073e9SAndroid Build Coastguard Worker2\. Create symbolic links to the results of those builds:
77*da0073e9SAndroid Build Coastguard Worker`android/pytorch_android/src/main/jniLibs/${abi}` to the directory with output libraries
78*da0073e9SAndroid Build Coastguard Worker`android/pytorch_android/src/main/cpp/libtorch_include/${abi}` to the directory with headers. These directories are used to build `libpytorch.so` library that will be loaded on android device.
79*da0073e9SAndroid Build Coastguard Worker
80*da0073e9SAndroid Build Coastguard Worker3\. And finally run `gradle` in `android/pytorch_android` directory with task `assembleRelease`
81*da0073e9SAndroid Build Coastguard Worker
82*da0073e9SAndroid Build Coastguard WorkerScript requires that Android SDK, Android NDK and gradle are installed.
83*da0073e9SAndroid Build Coastguard WorkerThey are specified as environment variables:
84*da0073e9SAndroid Build Coastguard Worker
85*da0073e9SAndroid Build Coastguard Worker`ANDROID_HOME` - path to [Android SDK](https://developer.android.com/studio/command-line/sdkmanager.html)
86*da0073e9SAndroid Build Coastguard Worker
87*da0073e9SAndroid Build Coastguard Worker`ANDROID_NDK` - path to [Android NDK](https://developer.android.com/studio/projects/install-ndk). It's recommended to use NDK 21.x.
88*da0073e9SAndroid Build Coastguard Worker
89*da0073e9SAndroid Build Coastguard Worker`GRADLE_HOME` - path to [gradle](https://gradle.org/releases/)
90*da0073e9SAndroid Build Coastguard Worker
91*da0073e9SAndroid Build Coastguard Worker
92*da0073e9SAndroid Build Coastguard WorkerAfter successful build you should see the result as aar file:
93*da0073e9SAndroid Build Coastguard Worker
94*da0073e9SAndroid Build Coastguard Worker```bash
95*da0073e9SAndroid Build Coastguard Worker$ find pytorch_android/build/ -type f -name *aar
96*da0073e9SAndroid Build Coastguard Workerpytorch_android/build/outputs/aar/pytorch_android.aar
97*da0073e9SAndroid Build Coastguard Workerpytorch_android_torchvision/build/outputs/aar/pytorch_android.aar
98*da0073e9SAndroid Build Coastguard Worker```
99*da0073e9SAndroid Build Coastguard Worker
100*da0073e9SAndroid Build Coastguard WorkerIt can be used directly in android projects, as a gradle dependency:
101*da0073e9SAndroid Build Coastguard Worker```groovy
102*da0073e9SAndroid Build Coastguard Workerallprojects {
103*da0073e9SAndroid Build Coastguard Worker    repositories {
104*da0073e9SAndroid Build Coastguard Worker        flatDir {
105*da0073e9SAndroid Build Coastguard Worker            dirs 'libs'
106*da0073e9SAndroid Build Coastguard Worker        }
107*da0073e9SAndroid Build Coastguard Worker    }
108*da0073e9SAndroid Build Coastguard Worker}
109*da0073e9SAndroid Build Coastguard Worker
110*da0073e9SAndroid Build Coastguard Workerdependencies {
111*da0073e9SAndroid Build Coastguard Worker    implementation(name:'pytorch_android', ext:'aar')
112*da0073e9SAndroid Build Coastguard Worker    implementation(name:'pytorch_android_torchvision', ext:'aar')
113*da0073e9SAndroid Build Coastguard Worker    ...
114*da0073e9SAndroid Build Coastguard Worker    implementation 'com.facebook.soloader:nativeloader:0.10.5'
115*da0073e9SAndroid Build Coastguard Worker    implementation 'com.facebook.fbjni:fbjni-java-only:0.2.2'
116*da0073e9SAndroid Build Coastguard Worker}
117*da0073e9SAndroid Build Coastguard Worker```
118*da0073e9SAndroid Build Coastguard WorkerWe also have to add all transitive dependencies of our aars.
119*da0073e9SAndroid Build Coastguard WorkerAs `pytorch_android` [depends](https://github.com/pytorch/pytorch/blob/master/android/pytorch_android/build.gradle#L76-L77) on `'com.facebook.soloader:nativeloader:0.10.5'` and `'com.facebook.fbjni:fbjni-java-only:0.2.2'`, we need to add them.
120*da0073e9SAndroid Build Coastguard Worker(In case of using maven dependencies they are added automatically from `pom.xml`).
121*da0073e9SAndroid Build Coastguard Worker
122*da0073e9SAndroid Build Coastguard WorkerYou can check out [test app example](https://github.com/pytorch/pytorch/blob/master/android/test_app/app/build.gradle) that uses aars directly.
123*da0073e9SAndroid Build Coastguard Worker
124*da0073e9SAndroid Build Coastguard Worker## Linking to prebuilt libtorch library from gradle dependency
125*da0073e9SAndroid Build Coastguard Worker
126*da0073e9SAndroid Build Coastguard WorkerIn some cases, you may want to use libtorch from your android native build.
127*da0073e9SAndroid Build Coastguard WorkerYou can do it without building libtorch android, using native libraries from PyTorch android gradle dependency.
128*da0073e9SAndroid Build Coastguard WorkerFor that, you will need to add the next lines to your gradle build.
129*da0073e9SAndroid Build Coastguard Worker```groovy
130*da0073e9SAndroid Build Coastguard Workerandroid {
131*da0073e9SAndroid Build Coastguard Worker...
132*da0073e9SAndroid Build Coastguard Worker    configurations {
133*da0073e9SAndroid Build Coastguard Worker       extractForNativeBuild
134*da0073e9SAndroid Build Coastguard Worker    }
135*da0073e9SAndroid Build Coastguard Worker...
136*da0073e9SAndroid Build Coastguard Worker    compileOptions {
137*da0073e9SAndroid Build Coastguard Worker        externalNativeBuild {
138*da0073e9SAndroid Build Coastguard Worker            cmake {
139*da0073e9SAndroid Build Coastguard Worker                arguments "-DANDROID_STL=c++_shared"
140*da0073e9SAndroid Build Coastguard Worker            }
141*da0073e9SAndroid Build Coastguard Worker        }
142*da0073e9SAndroid Build Coastguard Worker    }
143*da0073e9SAndroid Build Coastguard Worker...
144*da0073e9SAndroid Build Coastguard Worker    externalNativeBuild {
145*da0073e9SAndroid Build Coastguard Worker        cmake {
146*da0073e9SAndroid Build Coastguard Worker            path "CMakeLists.txt"
147*da0073e9SAndroid Build Coastguard Worker        }
148*da0073e9SAndroid Build Coastguard Worker    }
149*da0073e9SAndroid Build Coastguard Worker}
150*da0073e9SAndroid Build Coastguard Worker
151*da0073e9SAndroid Build Coastguard Workerdependencies {
152*da0073e9SAndroid Build Coastguard Worker    extractForNativeBuild('org.pytorch:pytorch_android:1.10.0')
153*da0073e9SAndroid Build Coastguard Worker}
154*da0073e9SAndroid Build Coastguard Worker
155*da0073e9SAndroid Build Coastguard Workertask extractAARForNativeBuild {
156*da0073e9SAndroid Build Coastguard Worker    doLast {
157*da0073e9SAndroid Build Coastguard Worker        configurations.extractForNativeBuild.files.each {
158*da0073e9SAndroid Build Coastguard Worker            def file = it.absoluteFile
159*da0073e9SAndroid Build Coastguard Worker            copy {
160*da0073e9SAndroid Build Coastguard Worker                from zipTree(file)
161*da0073e9SAndroid Build Coastguard Worker                into "$buildDir/$file.name"
162*da0073e9SAndroid Build Coastguard Worker                include "headers/**"
163*da0073e9SAndroid Build Coastguard Worker                include "jni/**"
164*da0073e9SAndroid Build Coastguard Worker            }
165*da0073e9SAndroid Build Coastguard Worker        }
166*da0073e9SAndroid Build Coastguard Worker    }
167*da0073e9SAndroid Build Coastguard Worker}
168*da0073e9SAndroid Build Coastguard Worker
169*da0073e9SAndroid Build Coastguard Workertasks.whenTaskAdded { task ->
170*da0073e9SAndroid Build Coastguard Worker  if (task.name.contains('externalNativeBuild')) {
171*da0073e9SAndroid Build Coastguard Worker    task.dependsOn(extractAARForNativeBuild)
172*da0073e9SAndroid Build Coastguard Worker  }
173*da0073e9SAndroid Build Coastguard Worker}
174*da0073e9SAndroid Build Coastguard Worker```
175*da0073e9SAndroid Build Coastguard Worker
176*da0073e9SAndroid Build Coastguard Workerpytorch_android aar contains headers to link in `headers` folder and native libraries in `jni/$ANDROID_ABI/`.
177*da0073e9SAndroid Build Coastguard WorkerAs PyTorch native libraries use `ANDROID_STL` - we should use `ANDROID_STL=c++_shared` to have only one loaded binary of STL.
178*da0073e9SAndroid Build Coastguard Worker
179*da0073e9SAndroid Build Coastguard WorkerThe added task will unpack them to gradle build directory.
180*da0073e9SAndroid Build Coastguard Worker
181*da0073e9SAndroid Build Coastguard WorkerIn your native build you can link to them adding these lines to your CMakeLists.txt:
182*da0073e9SAndroid Build Coastguard Worker
183*da0073e9SAndroid Build Coastguard Worker
184*da0073e9SAndroid Build Coastguard Worker```cmake
185*da0073e9SAndroid Build Coastguard Worker# Relative path of gradle build directory to CMakeLists.txt
186*da0073e9SAndroid Build Coastguard Workerset(build_DIR ${CMAKE_SOURCE_DIR}/build)
187*da0073e9SAndroid Build Coastguard Worker
188*da0073e9SAndroid Build Coastguard Workerfile(GLOB PYTORCH_INCLUDE_DIRS "${build_DIR}/pytorch_android*.aar/headers")
189*da0073e9SAndroid Build Coastguard Workerfile(GLOB PYTORCH_LINK_DIRS "${build_DIR}/pytorch_android*.aar/jni/${ANDROID_ABI}")
190*da0073e9SAndroid Build Coastguard Worker
191*da0073e9SAndroid Build Coastguard Workerset(BUILD_SUBDIR ${ANDROID_ABI})
192*da0073e9SAndroid Build Coastguard Workertarget_include_directories(${PROJECT_NAME} PRIVATE
193*da0073e9SAndroid Build Coastguard Worker  ${PYTORCH_INCLUDE_DIRS}
194*da0073e9SAndroid Build Coastguard Worker)
195*da0073e9SAndroid Build Coastguard Worker
196*da0073e9SAndroid Build Coastguard Workerfind_library(PYTORCH_LIBRARY pytorch_jni
197*da0073e9SAndroid Build Coastguard Worker  PATHS ${PYTORCH_LINK_DIRS}
198*da0073e9SAndroid Build Coastguard Worker  NO_CMAKE_FIND_ROOT_PATH)
199*da0073e9SAndroid Build Coastguard Worker
200*da0073e9SAndroid Build Coastguard Workerfind_library(FBJNI_LIBRARY fbjni
201*da0073e9SAndroid Build Coastguard Worker  PATHS ${PYTORCH_LINK_DIRS}
202*da0073e9SAndroid Build Coastguard Worker  NO_CMAKE_FIND_ROOT_PATH)
203*da0073e9SAndroid Build Coastguard Worker
204*da0073e9SAndroid Build Coastguard Workertarget_link_libraries(${PROJECT_NAME}
205*da0073e9SAndroid Build Coastguard Worker  ${PYTORCH_LIBRARY})
206*da0073e9SAndroid Build Coastguard Worker  ${FBJNI_LIBRARY})
207*da0073e9SAndroid Build Coastguard Worker
208*da0073e9SAndroid Build Coastguard Worker```
209*da0073e9SAndroid Build Coastguard WorkerIf your CMakeLists.txt file is located in the same directory as your build.gradle, `set(build_DIR ${CMAKE_SOURCE_DIR}/build)` should work for you. But if you have another location of it, you may need to change it.
210*da0073e9SAndroid Build Coastguard Worker
211*da0073e9SAndroid Build Coastguard WorkerAfter that, you can use libtorch C++ API from your native code.
212*da0073e9SAndroid Build Coastguard Worker```cpp
213*da0073e9SAndroid Build Coastguard Worker#include <string>
214*da0073e9SAndroid Build Coastguard Worker#include <ATen/NativeFunctions.h>
215*da0073e9SAndroid Build Coastguard Worker#include <torch/script.h>
216*da0073e9SAndroid Build Coastguard Workernamespace pytorch_testapp_jni {
217*da0073e9SAndroid Build Coastguard Workernamespace {
218*da0073e9SAndroid Build Coastguard Worker    struct JITCallGuard {
219*da0073e9SAndroid Build Coastguard Worker      c10::InferenceMode guard;
220*da0073e9SAndroid Build Coastguard Worker      torch::jit::GraphOptimizerEnabledGuard no_optimizer_guard{false};
221*da0073e9SAndroid Build Coastguard Worker    };
222*da0073e9SAndroid Build Coastguard Worker}
223*da0073e9SAndroid Build Coastguard Worker
224*da0073e9SAndroid Build Coastguard Workervoid loadAndForwardModel(const std::string& modelPath) {
225*da0073e9SAndroid Build Coastguard Worker  JITCallGuard guard;
226*da0073e9SAndroid Build Coastguard Worker  torch::jit::Module module = torch::jit::load(modelPath);
227*da0073e9SAndroid Build Coastguard Worker  module.eval();
228*da0073e9SAndroid Build Coastguard Worker  torch::Tensor t = torch::randn({1, 3, 224, 224});
229*da0073e9SAndroid Build Coastguard Worker  c10::IValue t_out = module.forward({t});
230*da0073e9SAndroid Build Coastguard Worker}
231*da0073e9SAndroid Build Coastguard Worker}
232*da0073e9SAndroid Build Coastguard Worker```
233*da0073e9SAndroid Build Coastguard Worker
234*da0073e9SAndroid Build Coastguard WorkerTo load torchscript model for mobile we need some special setup which is placed in `struct JITCallGuard` in this example. It may change in future, you can track the latest changes keeping an eye in our [pytorch android jni code]([https://github.com/pytorch/pytorch/blob/master/android/pytorch_android/src/main/cpp/pytorch_jni_jit.cpp#L28)
235*da0073e9SAndroid Build Coastguard Worker
236*da0073e9SAndroid Build Coastguard Worker[Example of linking to libtorch from aar](https://github.com/pytorch/pytorch/tree/master/android/test_app)
237*da0073e9SAndroid Build Coastguard Worker
238*da0073e9SAndroid Build Coastguard Worker## PyTorch Android API Javadoc
239*da0073e9SAndroid Build Coastguard Worker
240*da0073e9SAndroid Build Coastguard WorkerYou can find more details about the PyTorch Android API in the [Javadoc](https://pytorch.org/javadoc/).
241