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”, 74 “libhexagon_nn_skel_v66.so” 75 * [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”, 181 “libhexagon_nn_skel_v66.so” 182 * [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(¶ms); 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