Overview

This guide covers what we must do to cross-compile Arm NN using an x86_64 system to target a Raspberry Pi. Cross-compiling Arm NN allows us to work around the limited memory of the Raspberry Pi. Read the guide to find out how to build the Compute Library, Boost, Protobuf, TensorFlow, and Arm NN core libraries that you need for compilation. When we finish, we will be able to compile and run programs that use Arm NN on our Raspberry Pis.

Arm estimates that you will take 90-120 minutes to complete this guide.

Before you begin

This guide assumes:

  • You have a Raspberry Pi board. Arm has tested these instructions on a Raspberry Pi 2 Model B V1.1 that runs Raspian 9, a Rasberry Pi 3 Model B+ that runs Raspian 8, and a Raspberry Pi 4 Model B that runs Raspian 9.
  • You compile on a Linux virtual machine. Arm has tested these instructions on an Ubuntu 16.04 virtual machines that runs on MacOS and Windows 10 and an Ubuntu 18.04 machine.

You must install the following software tools on your virtual machine:

Git A version control system software developers use for source code management.

Scons An open-source software construction tool.

GNU C and C++ compilers for the armhf architecture The Raspberry Pi uses the armhf Arm architecture.

Note

For the instructions in this guide to work, the cross-compiler version on the host machine must match the compiler version on your Raspberry Pi.

Curl A tool for transferring data to or from a Linux or Unix-like server.

GNU Autoconf A tool for producing configure scripts for building, installing and packaging software.

GNU libtool A generic library support script.

CMake An open-source and cross-platform family of tools for building, testing, and packaging software.

To install the tools you require, open a command window and enter the following commands:

sudo apt-get install git
sudo apt-get install scons
sudo apt-get install gcc-arm-linux-gnueabihf
sudo apt-get install g++-arm-linux-gnueabihf 
sudo apt-get install curl 
sudo apt-get install autoconf
sudo apt-get install libtool 
sudo apt-get install cmake

Downloading the repositories and bundles

Create a directory on your virtual machine to build your Arm NN distribution for your Raspberry Pi. 

To create a directory and build your distribution:

  1. Enter the following commands:

    mkdir armnn-pi && cd armnn-pi
    export BASEDIR=`pwd`
  2. Download the Compute Library, Boost, Protobuf, TensorFlow, and Arm NN git repositories and source bundles. To download the repositories and bundles, enter the following commands:

    git clone https://github.com/Arm-software/ComputeLibrary.git 
    git clone https://github.com/Arm-software/armnn
    wget https://dl.bintray.com/boostorg/release/1.64.0/source/boost_1_64_0.tar.bz2
    tar xf boost_1_64_0.tar.bz2
    git clone -b v3.5.0 https://github.com/google/protobuf.git
    git clone https://github.com/tensorflow/tensorflow.git
    cd tensorflow/
    git checkout a0043f9262dc1b0e7dc4bdf3a7f0ef0bebc4891e

Building the Compute Library

Build the Compute Library on your virtual machine. To build the library, enter the following command:

cd $BASEDIR/ComputeLibrary
scons extra_cxx_flags="-fPIC" Werror=0 debug=0 asserts=0 neon=1 opencl=0 os=linux arch=armv7a examples=1

Arm estimates that your virtual machine will take approximately 15-20 minutes to execute this command.

Building the Boost library for your Raspberry Pi

To build the Boost library for your Raspberry Pi:

  1. Enter the following commands:

    cd $BASEDIR/boost_1_64_0/tools/build
    ./bootstrap.sh
    ./b2 install --prefix=$BASEDIR/boost.build
    export PATH=$BASEDIR/boost.build/bin:$PATH
    
  2. Create a project-config.jam file by copying the user-config.jam file. To copy the user-config.jam file, enter the following command:

    cp $BASEDIR/boost_1_64_0/tools/build/example/user-config.jam $BASEDIR/boost_1_64_0/project-config.jam
  3. Go to the $BASEDIR/boost_1_64_0/ directory and open the project-config.jam file in a text editor. In the GCC Configuration section, add the following line:

    using gcc : arm : arm-linux-gnueabihf-g++ ;
  4. Save the project-config.jam file in the $BASEDIR/boost_1_64_0/ directory.

  5. To complete the build, enter the following commands:

    cd $BASEDIR/boost_1_64_0
    b2 --build-dir=$BASEDIR/boost_1_64_0/build toolset=gcc-arm link=static cxxflags=-fPIC --with- 
    filesystem --with-test --with-log --with-program_options install --prefix=$BASEDIR/boost
    1. Arm estimates that your virtual machine will take approximately 15 minutes to execute these commands.

Building the Google Protobuf library

You use two versions of the Google Protobuf library. One version of the library runs on your virtual machine and the other runs on your Raspberry Pi.

Building the Google Protobuf library for your virtual machine

To build the Google Protobuf library for your virtual machine:

  1. Enter the following commands:

    cd $BASEDIR/protobuf
    git submodule update --init --recursive
    ./autogen.sh ./configure --prefix=$BASEDIR/protobuf-host make

    Arm estimates that your virtual machine will take approximately 15 minutes to execute these commands.

  2. Enter the following commands:

    make install
    make clean

Building the Google Protobuf library for your Raspberry Pi

    To build the Google Protobuf library for your Raspberry Pi:

  1. Enter the following commands:

    ./configure --prefix=$BASEDIR/protobuf-arm --host=arm-linux CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ --with-protoc=$BASEDIR/protobuf-host/bin/protoc
    make

    Arm estimates that your virtual machine will take approximately 15 minutes to execute these commands.

  2. Enter the following command:

    make install

Generating the TensorFlow Protobuf library

To generate the TensorFlow library, enter the following command:

cd $BASEDIR/tensorflow
../armnn/scripts/generate_tensorflow_protobuf.sh ../tensorflow-protobuf ../protobuf-host

Building Arm NN

To build Arm NN:

  1. Enter the following commands:

    cd $BASEDIR/armnn
    mkdir build
    cd build
    
  2. Place the library files you require in the build directory. To place the library files, enter:

    cmake .. -DCMAKE_LINKER=/usr/bin/arm-linux-gnueabihf-ld \
    -DCMAKE_C_COMPILER=/usr/bin/arm-linux-gnueabihf-gcc \
    -DCMAKE_CXX_COMPILER=/usr/bin/arm-linux-gnueabihf-g++ \
    -DCMAKE_C_COMPILER_FLAGS=-fPIC \
    -DCMAKE_CXX_FLAGS=-mfpu=neon \
    -DARMCOMPUTE_ROOT=$BASEDIR/ComputeLibrary \
    -DARMCOMPUTE_BUILD_DIR=$BASEDIR/ComputeLibrary/build \
    -DBOOST_ROOT=$BASEDIR/boost \
    -DTF_GENERATED_SOURCES=$BASEDIR/tensorflow-protobuf \
    -DBUILD_TF_PARSER=1 \
    -DPROTOBUF_ROOT=$BASEDIR/protobuf-arm \
    -DARMCOMPUTENEON=1 \
    -DARMNNREF=1
    make
    

    Arm estimates that your virtual machine will take approximately 12 minutes to execute these commands.

Extracting Arm NN to your Raspberry Pi and running a sample program

Creating an archive of cross-compiled libraries, binaries, and directories

To create an archive of cross-compiled libraries, binaries, and directories:

  1. Copy the following libraries, binaries, and directories from your virtual machine. To copy these libraries, binaries, and directories enter the following commands:

    cd $BASEDIR
    mkdir armnn-dist
    mkdir armnn-dist/armnn
    mkdir armnn-dist/armnn/lib
    
    cp $BASEDIR/armnn/build/libarmnn.so $BASEDIR/armnn-dist/armnn/lib
    cp $BASEDIR/armnn/build/libarmnnTfParser.so $BASEDIR/armnn-dist/armnn/lib
    cp $BASEDIR/protobuf-arm/lib/libprotobuf.so.15.0.0 $BASEDIR/armnn-dist/armnn/lib/libprotobuf.so
    cp $BASEDIR/protobuf-arm/lib/libprotobuf.so.15.0.0 $BASEDIR/armnn-dist/armnn/lib/libprotobuf.so.15
    cp -r $BASEDIR/armnn/include $BASEDIR/armnn-dist/armnn/include
    cp -r $BASEDIR/boost $BASEDIR/armnn-dist/boost
  2. Copy the following dynamic backend related files from your virtual machine. To copy these files, enter the following commands:

    mkdir -p $BASEDIR/armnn-dist/src/backends/backendsCommon/test/
    cp -r $BASEDIR/armnn/build/src/backends/backendsCommon/test/testSharedObject $BASEDIR/armnn-dist/src/backends/backendsCommon/test/testSharedObject/
    
    cp -r $BASEDIR/armnn/build/src/backends/backendsCommon/test/testDynamicBackend/ $BASEDIR/armnn-dist/src/backends/backendsCommon/test/testDynamicBackend/
    cp -r $BASEDIR/armnn/build/src/backends/backendsCommon/test/backendsTestPath1/ $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath1/
    
    mkdir -p $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath2
    cp $BASEDIR/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath2/
    
    ln -s Arm_CpuAcc_backend.so $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1
    ln -s Arm_CpuAcc_backend.so.1 $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1.2
    ln -s Arm_CpuAcc_backend.so.1.2 $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath2/Arm_CpuAcc_backend.so.1.2.3
    cp $BASEDIR/armnn/build/src/backends/backendsCommon/test/backendsTestPath2/Arm_GpuAcc_backend.so $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath2/
    ln -s nothing $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath2/Arm_no_backend.so
    
    mkdir -p $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath3
    
    cp -r $BASEDIR/armnn/build/src/backends/backendsCommon/test/backendsTestPath5/ $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath5
    cp -r $BASEDIR/armnn/build/src/backends/backendsCommon/test/backendsTestPath6/ $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath6
    
    mkdir -p $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath7
    
    cp -r $BASEDIR/armnn/build/src/backends/backendsCommon/test/backendsTestPath9/ $BASEDIR/armnn-dist/src/backends/backendsCommon/test/backendsTestPath9
    
    mkdir -p $BASEDIR/armnn-dist/src/backends/dynamic/reference
    cp $BASEDIR/armnn/build/src/backends/dynamic/reference/Arm_CpuRef_backend.so $BASEDIR/armnn-dist/src/backends/dynamic/reference/
  3. Copy the Unit Tests and a sample Arm NN program. To copy this test and program, enter the following commands:

    cp $BASEDIR/armnn/build/UnitTests $BASEDIR/armnn-dist
    cp $BASEDIR/armnn/samples/SimpleSample.cpp $BASEDIR/armnn-dist
  4. Create the archive for your Raspberry Pi. To create the archive, enter the following command:

    tar -czf $BASEDIR/armnn-dist.tar.gz armnn-dist

Extract the libraries, binaries, and directories to your Raspberry Pi

Extract the libraries, binaries, and directories to your Raspberry Pi. To extract the libraries, binaries and directories enter the following commands:

cd /home/pi
tar -xzf /home/pi/armnn-dist.tar.gz

Compiling and running a sample Arm NN program on your Raspberry Pi

To compile and run a sample C++ program that uses Arm NN on your Raspberry Pi:

  1. Enter the following commands:

    export LD_LIBRARY_PATH=/home/pi/armnn-dist/armnn/lib
    cd /home/pi/armnn-dist

    To compile the program, enter the following commands:

    g++ SimpleSample.cpp -I/home/pi/armnn-dist/armnn/include -I/home/pi/armnn-dist/boost/include -L/home/pi/armnn-dist/armnn/lib -larmnn -larmnnTfParser -lprotobuf -o SimpleSample
  2. To run the program, enter the following command:

    ./SimpleSample

    The console returns the following:

    Please enter a number:

    Enter your number. For example:

    345

    The console returns the following:

    Your number was 345

Testing your build

To test that your build of Arm NN works correctly, run the Unit Tests. To run the Unit Tests, enter the following:

export LD_LIBRARY_PATH=/home/pi/armnn-dist/armnn/lib
cd /home/pi/armnn-dist
./UnitTests

If the tests are successful they output the following to the console:

*** No errors detected

If some of the tests are unsuccessful, go back through the steps and check that all the commands have been entered correctly.

Note

Arm is aware of an issue resulting in a NeonTimerMeasure unit test error on Raspberry Pi. The implementation by the Raspberry Pi of the timing libraries Arm NN uses to get its timing data causes this error. You can safely ignore this error.

Next steps

You are now ready to compile and run programs that use Arm NN on your Raspberry Pi.

Find out how to deploy Caffe and TensorFlow models.