ArmNN
 21.02
delegate/BuildGuideNative.md
Go to the documentation of this file.
1 # Delegate build guide introduction
2 
3 The Arm NN Delegate can be found within the Arm NN repository but it is a standalone piece of software. However,
4 it makes use of the Arm NN library. For this reason we have added two options to build the delegate. The first option
5 allows you to build the delegate together with the Arm NN library, the second option is a standalone build
6 of the delegate.
7 
8 This tutorial uses an Aarch64 machine with Ubuntu 18.04 installed that can build all components
9 natively (no cross-compilation required). This is to keep this guide simple.
10 
11 **Table of content:**
12 - [Delegate build guide introduction](#delegate-build-guide-introduction)
13 - [Dependencies](#dependencies)
14  * [Build Tensorflow for C++](#build-tensorflow-for-c--)
15  * [Build Flatbuffers](#build-flatbuffers)
16  * [Build the Arm Compute Library](#build-the-arm-compute-library)
17  * [Build the Arm NN Library](#build-the-arm-nn-library)
18 - [Build the TfLite Delegate (Stand-Alone)](#build-the-tflite-delegate--stand-alone-)
19 - [Build the Delegate together with Arm NN](#build-the-delegate-together-with-arm-nn)
20 - [Integrate the Arm NN TfLite Delegate into your project](#integrate-the-arm-nn-tflite-delegate-into-your-project)
21 
22 
23 # Dependencies
24 
25 Build Dependencies:
26  * Tensorflow and Tensorflow Lite. This guide uses version 2.3.1 . Other versions might work.
27  * Flatbuffers 1.12.0
28  * Arm NN 20.11 or higher
29 
30 Required Tools:
31  * Git. This guide uses version 2.17.1 . Other versions might work.
32  * pip. This guide uses version 20.3.3 . Other versions might work.
33  * wget. This guide uses version 1.17.1 . Other versions might work.
34  * zip. This guide uses version 3.0 . Other versions might work.
35  * unzip. This guide uses version 6.00 . Other versions might work.
36  * cmake 3.7.0 or higher. This guide uses version 3.7.2
37  * scons. This guide uses version 2.4.1 . Other versions might work.
38  * bazel. This guide uses version 3.1.0 . Other versions might work.
39 
40 Our first step is to build all the build dependencies I have mentioned above. We will have to create quite a few
41 directories. To make navigation a bit easier define a base directory for the project. At this stage we can also
42 install all the tools that are required during the build.
43 ```bash
44 export BASEDIR=/home
45 cd $BASEDIR
46 apt-get update && apt-get install git wget unzip zip python git cmake scons
47 ```
48 
49 ## Build Tensorflow for C++
50 Tensorflow has a few dependencies on it's own. It requires the python packages pip3, numpy, wheel, keras_preprocessing
51 and also bazel which is used to compile Tensoflow. A description on how to build bazel can be
52 found [here](https://docs.bazel.build/versions/master/install-compile-source.html). There are multiple ways.
53 I decided to compile from source because that should work for any platform and therefore adds the most value
54 to this guide. Depending on your operating system and architecture there might be an easier way.
55 ```bash
56 # Install the python packages
57 pip3 install -U pip numpy wheel
58 pip3 install -U keras_preprocessing --no-deps
59 
60 # Bazel has a dependency on JDK (The JDK version depends on the bazel version you want to build)
61 apt-get install openjdk-11-jdk
62 # Build Bazel
63 wget -O bazel-3.1.0-dist.zip https://github.com/bazelbuild/bazel/releases/download/3.1.0/bazel-3.1.0-dist.zip
64 unzip -d bazel bazel-3.1.0-dist.zip
65 cd bazel
66 env EXTRA_BAZEL_ARGS="--host_javabase=@local_jdk//:jdk" bash ./compile.sh
67 # This creates an "output" directory where the bazel binary can be found
68 
69 # Download Tensorflow
70 cd $BASEDIR
71 git clone https://github.com/tensorflow/tensorflow.git
72 cd tensorflow/
73 git checkout tags/v2.3.1 # Minimum version required for the delegate
74 ```
75 Before tensorflow can be built, targets need to be defined in the `BUILD` file that can be
76 found in the root directory of Tensorflow. Append the following two targets to the file:
77 ```
78 cc_binary(
79  name = "libtensorflow_all.so",
80  linkshared = 1,
81  deps = [
82  "//tensorflow/core:framework",
83  "//tensorflow/core:tensorflow",
84  "//tensorflow/cc:cc_ops",
85  "//tensorflow/cc:client_session",
86  "//tensorflow/cc:scope",
87  "//tensorflow/c:c_api",
88  ],
89 )
90 cc_binary(
91  name = "libtensorflow_lite_all.so",
92  linkshared = 1,
93  deps = [
94  "//tensorflow/lite:framework",
95  "//tensorflow/lite/kernels:builtin_ops",
96  ],
97 )
98 ```
99 Now the build process can be started. When calling "configure", as below, a dialog shows up that asks the
100 user to specify additional options. If you don't have any particular needs to your build, decline all
101 additional options and choose default values. Building `libtensorflow_all.so` requires quite some time.
102 This might be a good time to get yourself another drink and take a break.
103 ```bash
104 PATH="$BASEDIR/bazel/output:$PATH" ./configure
105 $BASEDIR/bazel/output/bazel build --define=grpc_no_ares=true --config=opt --config=monolithic --strip=always --config=noaws libtensorflow_all.so
106 $BASEDIR/bazel/output/bazel build --config=opt --config=monolithic --strip=always libtensorflow_lite_all.so
107 ```
108 
109 ## Build Flatbuffers
110 
111 Flatbuffers is a memory efficient cross-platform serialization library as
112 described [here](https://google.github.io/flatbuffers/). It is used in tflite to store models and is also a dependency
113 of the delegate. After downloading the right version it can be built and installed using cmake.
114 ```bash
115 cd $BASEDIR
116 wget -O flatbuffers-1.12.0.zip https://github.com/google/flatbuffers/archive/v1.12.0.zip
117 unzip -d . flatbuffers-1.12.0.zip
118 cd flatbuffers-1.12.0
119 mkdir install && mkdir build && cd build
120 # I'm using a different install directory but that is not required
121 cmake .. -DCMAKE_INSTALL_PREFIX:PATH=$BASEDIR/flatbuffers-1.12.0/install
122 make install
123 ```
124 
125 ## Build the Arm Compute Library
126 
127 The Arm NN library depends on the Arm Compute Library (ACL). It provides a set of functions that are optimized for
128 both Arm CPUs and GPUs. The Arm Compute Library is used directly by Arm NN to run machine learning workloads on
129 Arm CPUs and GPUs.
130 
131 It is important to have the right version of ACL and Arm NN to make it work. Luckily, Arm NN and ACL are developed
132 very closely and released together. If you would like to use the Arm NN version "20.11" you can use the same "20.11"
133 version for ACL too.
134 
135 To build the Arm Compute Library on your platform, download the Arm Compute Library and checkout the branch
136 that contains the version you want to use and build it using `scons`.
137 ```bash
138 cd $BASEDIR
139 git clone https://review.mlplatform.org/ml/ComputeLibrary
140 cd ComputeLibrary/
141 git checkout <branch_name> # e.g. branches/arm_compute_20_11
142 # The machine used for this guide only has a Neon CPU which is why I only have "neon=1" but if
143 # your machine has an arm Gpu you can enable that by adding `opencl=1 embed_kernels=1 to the command below
144 scons arch=arm64-v8a neon=1 extra_cxx_flags="-fPIC" benchmark_tests=0 validation_tests=0
145 ```
146 
147 ## Build the Arm NN Library
148 
149 After building ACL we can now continue building Arm NN. To do so, download the repository and checkout the same
150 version as you did for ACL. Create a build directory and use cmake to build it.
151 ```bash
152 cd $BASEDIR
153 git clone "https://review.mlplatform.org/ml/armnn"
154 cd armnn
155 git checkout <branch_name> # e.g. branches/armnn_20_11
156 mkdir build && cd build
157 # if you've got an arm Gpu add `-DARMCOMPUTECL=1` to the command below
158 cmake .. -DARMCOMPUTE_ROOT=$BASEDIR/ComputeLibrary -DARMCOMPUTENEON=1 -DBUILD_UNIT_TESTS=0
159 make
160 ```
161 
162 # Build the TfLite Delegate (Stand-Alone)
163 
164 The delegate as well as Arm NN is built using cmake. Create a build directory as usual and build the Delegate
165 with the additional cmake arguments shown below
166 ```bash
167 cd $BASEDIR/armnn/delegate && mkdir build && cd build
168 cmake .. -DTENSORFLOW_LIB_DIR=$BASEDIR/tensorflow/bazel-bin \ # Directory where tensorflow libraries can be found
169  -DTENSORFLOW_ROOT=$BASEDIR/tensorflow \ # The top directory of the tensorflow repository
170  -DTFLITE_LIB_ROOT=$BASEDIR/tensorflow/bazel-bin \ # In our case the same as TENSORFLOW_LIB_DIR
171  -DFLATBUFFERS_ROOT=$BASEDIR/flatbuffers-1.12.0/install \ # The install directory
172  -DArmnn_DIR=$BASEDIR/armnn/build \ # Directory where the Arm NN library can be found
173  -DARMNN_SOURCE_DIR=$BASEDIR/armnn # The top directory of the Arm NN repository.
174  # Required are the includes for Arm NN
175 make
176 ```
177 
178 To ensure that the build was successful you can run the unit tests for the delegate that can be found in
179 the build directory for the delegate. [Doctest](https://github.com/onqtam/doctest) was used to create those tests. Using test filters you can
180 filter out tests that your build is not configured for. In this case, because Arm NN was only built for Cpu
181 acceleration (CpuAcc), we filter for all test suites that have `CpuAcc` in their name.
182 ```bash
183 cd $BASEDIR/armnn/delegate/build
184 ./DelegateUnitTests --test-suite=*CpuAcc*
185 ```
186 If you have built for Gpu acceleration as well you might want to change your test-suite filter:
187 ```bash
188 ./DelegateUnitTests --test-suite=*CpuAcc*,*GpuAcc*
189 ```
190 
191 
192 # Build the Delegate together with Arm NN
193 
194 In the introduction it was mentioned that there is a way to integrate the delegate build into Arm NN. This is
195 pretty straight forward. The cmake arguments that were previously used for the delegate have to be added
196 to the Arm NN cmake arguments. Also another argument `BUILD_ARMNN_TFLITE_DELEGATE` needs to be added to
197 instruct Arm NN to build the delegate as well. The new commands to build Arm NN are as follows:
198 ```bash
199 cd $BASEDIR
200 git clone "https://review.mlplatform.org/ml/armnn"
201 cd armnn
202 git checkout <branch_name> # e.g. branches/armnn_20_11
203 mkdir build && cd build
204 # if you've got an arm Gpu add `-DARMCOMPUTECL=1` to the command below
205 cmake .. -DARMCOMPUTE_ROOT=$BASEDIR/ComputeLibrary \
206  -DARMCOMPUTENEON=1 \
207  -DBUILD_UNIT_TESTS=0 \
208  -DBUILD_ARMNN_TFLITE_DELEGATE=1 \
209  -DTENSORFLOW_LIB_DIR=$BASEDIR/tensorflow/bazel-bin \
210  -DTENSORFLOW_ROOT=$BASEDIR/tensorflow \
211  -DTFLITE_LIB_ROOT=$BASEDIR/tensorflow/bazel-bin \
212  -DFLATBUFFERS_ROOT=$BASEDIR/flatbuffers-1.12.0/install
213 make
214 ```
215 The delegate library can then be found in `build/armnn/delegate`.
216 
217 
218 # Integrate the Arm NN TfLite Delegate into your project
219 
220 The delegate can be integrated into your c++ project by creating a TfLite Interpreter and
221 instructing it to use the Arm NN delegate for the graph execution. This should look similiar
222 to the following code snippet.
223 ```objectivec
224 // Create TfLite Interpreter
225 std::unique_ptr<Interpreter> armnnDelegateInterpreter;
226 InterpreterBuilder(tfLiteModel, ::tflite::ops::builtin::BuiltinOpResolver())
227  (&armnnDelegateInterpreter)
228 
229 // Create the Arm NN Delegate
230 armnnDelegate::DelegateOptions delegateOptions(backends);
231 std::unique_ptr<TfLiteDelegate, decltype(&armnnDelegate::TfLiteArmnnDelegateDelete)>
232  theArmnnDelegate(armnnDelegate::TfLiteArmnnDelegateCreate(delegateOptions),
233  armnnDelegate::TfLiteArmnnDelegateDelete);
234 
235 // Instruct the Interpreter to use the armnnDelegate
236 armnnDelegateInterpreter->ModifyGraphWithDelegate(theArmnnDelegate.get());
237 ```
238 For further information on using TfLite Delegates
239 please visit the [tensorflow website](https://www.tensorflow.org/lite/guide)
240