1# TensorFlow Lite Hexagon delegate
2
3This document explains how to use the TensorFlow Lite Hexagon Delegate in your
4application using the Java and/or C API. The delegate leverages the Qualcomm
5Hexagon library to execute quantized kernels on the DSP. Note that the delegate
6is intended to *complement* NNAPI functionality, particularly for devices where
7NNAPI DSP acceleration is unavailable (e.g., on older devices, or devices that
8don’t yet have a DSP NNAPI driver).
9
10Note: This delegate is in experimental (beta) phase.
11
12**Supported devices:**
13
14Currently most
15[Qualcomm SoCs](https://en.wikipedia.org/wiki/List_of_Qualcomm_Snapdragon_systems-on-chip)
16are supported, including:
17
18*   Snapdragon 835 (682 DSP)
19*   Snapdragon 660/820/821 (680 DSP)
20*   Snapdragon 710/845 (685 DSP)
21*   Snapdragon 8150/855 (690 DSP)
22
23**Supported models:**
24
25The Hexagon delegate supports all models that conform to our
26[8-bit symmetric quantization spec](https://www.tensorflow.org/lite/performance/quantization_spec),
27including those generated using
28[post-training integer quantization](https://www.tensorflow.org/lite/performance/post_training_integer_quant).
29UInt8 models trained with the legacy
30[quantization-aware training](https://github.com/tensorflow/tensorflow/tree/r1.13/tensorflow/contrib/quantize)
31path are also supported, for e.g.,
32[these quantized versions](https://www.tensorflow.org/lite/guide/hosted_models#quantized_models)
33on our Hosted Models page.
34
35## Hexagon delegate Java API
36
37```java
38public class HexagonDelegate implements Delegate, Closeable {
39
40  /*
41   * Creates a new HexagonDelegate object given the current 'context'.
42   * Throws UnsupportedOperationException if Hexagon DSP delegation is not
43   * available on this device.
44   */
45  public HexagonDelegate(Context context) throws UnsupportedOperationException
46
47
48  /**
49   * Frees TFLite resources in C runtime.
50   *
51   * User is expected to call this method explicitly.
52   */
53  @Override
54  public void close();
55}
56```
57
58### Example usage
59
60#### Step 1. Edit app/build.gradle to use the nightly Hexagon delegate AAR
61
62```
63dependencies {
64  ...
65  implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly-SNAPSHOT'
66  implementation 'org.tensorflow:tensorflow-lite-hexagon:0.0.0-nightly-SNAPSHOT'
67}
68```
69
70#### Step 2. Add Hexagon libraries to your Android app
71
72*   Download and run hexagon_nn_skel.run. It should provide 3 different shared
73    libraries “libhexagon_nn_skel.so”, “libhexagon_nn_skel_v65.so”,
74libhexagon_nn_skel_v66.so75    *   [v1.10.3](https://storage.cloud.google.com/download.tensorflow.org/tflite/hexagon_nn_skel_1_10_3_1.run)
76    *   [v1.14](https://storage.cloud.google.com/download.tensorflow.org/tflite/hexagon_nn_skel_v1.14.run)
77    *   [v1.17](https://storage.cloud.google.com/download.tensorflow.org/tflite/hexagon_nn_skel_v1.17.0.0.run)
78    *   [v1.20](https://storage.cloud.google.com/download.tensorflow.org/tflite/hexagon_nn_skel_v1.20.0.0.run)
79
80Note: You will need to accept the license agreement.
81
82Note: As of 07/22/2020 you should use v1.20.
83
84Note: You must use the hexagon_nn libraries with the compatible version of
85interface library. Interface library is part of the AAR and fetched by bazel
86through the
87[config](https://github.com/tensorflow/tensorflow/blob/master/third_party/hexagon/workspace.bzl)
88The version in the bazel config is the version you should use.
89
90*   Include all 3 in your app with other shared libraries. See
91    [How to add shared library to your app](#how-to-add-shared-library-to-your-app).
92    The delegate will automatically pick the one with best performance depending
93    on the device.
94
95Note: If your app will be built for both 32 and 64-bit ARM devices, then you
96will need to add the Hexagon shared libs to both 32 and 64-bit lib folders.
97
98#### Step 3. Create a delegate and initialize a TensorFlow Lite Interpreter
99
100```java
101import org.tensorflow.lite.HexagonDelegate;
102
103// Create the Delegate instance.
104try {
105  hexagonDelegate = new HexagonDelegate(activity);
106  tfliteOptions.addDelegate(hexagonDelegate);
107} catch (UnsupportedOperationException e) {
108  // Hexagon delegate is not supported on this device.
109}
110
111tfliteInterpreter = new Interpreter(tfliteModel, tfliteOptions);
112
113// Dispose after finished with inference.
114tfliteInterpreter.close();
115if (hexagonDelegate != null) {
116  hexagonDelegate.close();
117}
118```
119
120## Hexagon delegate C API
121
122```c
123struct TfLiteHexagonDelegateOptions {
124  // This corresponds to the debug level in the Hexagon SDK. 0 (default)
125  // means no debug.
126  int debug_level;
127  // This corresponds to powersave_level in the Hexagon SDK.
128  // where 0 (default) means high performance which means more power
129  // consumption.
130  int powersave_level;
131  // If set to true, performance information about the graph will be dumped
132  // to Standard output, this includes cpu cycles.
133  // WARNING: Experimental and subject to change anytime.
134  bool print_graph_profile;
135  // If set to true, graph structure will be dumped to Standard output.
136  // This is usually beneficial to see what actual nodes executed on
137  // the DSP. Combining with 'debug_level' more information will be printed.
138  // WARNING: Experimental and subject to change anytime.
139  bool print_graph_debug;
140};
141
142// Return a delegate that uses Hexagon SDK for ops execution.
143// Must outlive the interpreter.
144TfLiteDelegate*
145TfLiteHexagonDelegateCreate(const TfLiteHexagonDelegateOptions* options);
146
147// Do any needed cleanup and delete 'delegate'.
148void TfLiteHexagonDelegateDelete(TfLiteDelegate* delegate);
149
150// Initializes the DSP connection.
151// This should be called before doing any usage of the delegate.
152// "lib_directory_path": Path to the directory which holds the
153// shared libraries for the Hexagon NN libraries on the device.
154void TfLiteHexagonInitWithPath(const char* lib_directory_path);
155
156// Same as above method but doesn't accept the path params.
157// Assumes the environment setup is already done. Only initialize Hexagon.
158Void TfLiteHexagonInit();
159
160// Clean up and switch off the DSP connection.
161// This should be called after all processing is done and delegate is deleted.
162Void TfLiteHexagonTearDown();
163```
164
165### Example usage
166
167#### Step 1. Edit app/build.gradle to use the nightly Hexagon delegate AAR
168
169```
170dependencies {
171  ...
172  implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly-SNAPSHOT'
173  implementation 'org.tensorflow:tensorflow-lite-hexagon:0.0.0-nightly-SNAPSHOT'
174}
175```
176
177#### Step 2. Add Hexagon libraries to your Android app
178
179*   Download and run hexagon_nn_skel.run. It should provide 3 different shared
180    libraries “libhexagon_nn_skel.so”, “libhexagon_nn_skel_v65.so”,
181libhexagon_nn_skel_v66.so182    *   [v1.10.3](https://storage.cloud.google.com/download.tensorflow.org/tflite/hexagon_nn_skel_1_10_3_1.run)
183    *   [v1.14](https://storage.cloud.google.com/download.tensorflow.org/tflite/hexagon_nn_skel_v1.14.run)
184    *   [v1.17](https://storage.cloud.google.com/download.tensorflow.org/tflite/hexagon_nn_skel_v1.17.0.0.run)
185    *   [v1.20](https://storage.cloud.google.com/download.tensorflow.org/tflite/hexagon_nn_skel_v1.20.0.0.run)
186
187Note: You will need to accept the license agreement.
188
189Note: As of 07/22/2020 you should use v1.20.
190
191Note: You must use the hexagon_nn libraries with the compatible version of
192interface library. Interface library is part of the AAR and fetched by bazel
193through the
194[config](https://github.com/tensorflow/tensorflow/blob/master/third_party/hexagon/workspace.bzl).
195The version in the bazel config is the version you should use.
196
197*   Include all 3 in your app with other shared libraries. See
198    [How to add shared library to your app](#how-to-add-shared-library-to-your-app).
199    The delegate will automatically pick the one with best performance depending
200    on the device.
201
202Note: If your app will be built for both 32 and 64-bit ARM devices, then you
203will need to add the Hexagon shared libs to both 32 and 64-bit lib folders.
204
205#### Step 3. Include the C header
206
207*   The header file "hexagon_delegate.h" can be downloaded from
208    [GitHub](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/delegates/hexagon/hexagon_delegate.h)
209    or extracted from the Hexagon delegate AAR.
210
211#### Step 4. Create a delegate and initialize a TensorFlow Lite Interpreter
212
213*   In your code, ensure the native Hexagon library is loaded. This can be done
214    by calling `System.loadLibrary("tensorflowlite_hexagon_jni");` \
215    in your Activity or Java entry-point.
216
217*   Create a delegate, example:
218
219```c
220#include "tensorflow/lite/delegates/hexagon/hexagon_delegate.h"
221
222// Assuming shared libraries are under "/data/local/tmp/"
223// If files are packaged with native lib in android App then it
224// will typically be equivalent to the path provided by
225// "getContext().getApplicationInfo().nativeLibraryDir"
226const char[] library_directory_path = "/data/local/tmp/";
227TfLiteHexagonInitWithPath(library_directory_path);  // Needed once at startup.
228::tflite::TfLiteHexagonDelegateOptions params = {0};
229// 'delegate_ptr' Need to outlive the interpreter. For example,
230// If use case will need to resize input or anything that can trigger
231// re-applying delegates then 'delegate_ptr' need to outlive the interpreter.
232auto* delegate_ptr = ::tflite::TfLiteHexagonDelegateCreate(&params);
233Interpreter::TfLiteDelegatePtr delegate(delegate_ptr,
234  [](TfLiteDelegate* delegate) {
235    ::tflite::TfLiteHexagonDelegateDelete(delegate);
236  });
237interpreter->ModifyGraphWithDelegate(delegate.get());
238// After usage of delegate.
239TfLiteHexagonTearDown();  // Needed once at end of app/DSP usage.
240```
241
242## Add the shared library to your app
243
244*   Create folder “app/src/main/jniLibs”, and create a directory for each target
245    architecture. For example,
246    *   ARM 64-bit: `app/src/main/jniLibs/arm64-v8a`
247    *   ARM 32-bit: `app/src/main/jniLibs/armeabi-v7a`
248*   Put your .so in the directory that match the architecture.
249
250Note: If you're using App Bundle for publishing your Application, you might want
251to set android.bundle.enableUncompressedNativeLibs=false in the
252gradle.properties file.
253
254## Feedback
255
256For issues, please create a
257[GitHub](https://github.com/tensorflow/tensorflow/issues/new?template=50-other-issues.md)
258issue with all the necessary repro details, including the phone model and board
259used (`adb shell getprop ro.product.device` and `adb shell getprop
260ro.board.platform`).
261
262## FAQ
263
264*   Which ops are supported by the delegate?
265    *   See the current list of
266        [supported ops and constraints](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/delegates/hexagon/README.md)
267*   How can I tell that the model is using the DSP when I enable the delegate?
268    *   Two log messages will be printed when you enable the delegate - one to
269        indicate if the delegate was created and another to indicate how many
270        nodes are running using the delegate. \
271        `Created TensorFlow Lite delegate for Hexagon.` \
272        `Hexagon delegate: X nodes delegated out of Y nodes.`
273*   Do I need all Ops in the model to be supported to run the delegate?
274    *   No, the Model will be partitioned into subgraphs based on the supported
275        ops. Any unsupported ops will run on the CPU.
276*   How can I build the Hexagon delegate AAR from source?
277    *   Use `bazel build -c opt --config=android_arm64
278        tensorflow/lite/delegates/hexagon/java:tensorflow-lite-hexagon`.
279*   Why does Hexagon delegate fail to initialize although my Android device has
280    a supported SoC?
281    *   Verify if your device indeed has a supported SoC. Run `adb shell cat
282        /proc/cpuinfo | grep Hardware` and see if it returns something like
283        "Hardware : Qualcomm Technologies, Inc MSMXXXX".
284    *   Some phone manufacturers use different SoCs for the same phone model.
285        Therefore, Hexagon delegate may only work on some but not all devices of
286        the same phone model.
287    *   Some phone manufactures intentionally restrict the use of Hexagon DSP
288        from non-system Android apps, making the Hexagon delegate unable to
289        work.
290