NuPIC on Raspberry Pi 2(rev 1.2)/ 3B/ B+ with Xubuntu

ubuntu
raspberrypi
guide

#1

It is a challenge getting NuPIC to run on the Raspberry Pi because Raspbian is a 32 bit operating system. At the time of writing, NuPIC 1.0.5 (connected with NuPIC core 1.0.6 built from source) fails a number of tests cases on 32 bit systems (these failures happen on x86 as well, not only armhf). The chips on the Pi 2 (rev 1.2), 3B, and 3B+ models support 64 bit, but at the time of writing this, there isn’t an official 64 bit build of Raspbian.

Luckily, there are other operating systems which are 64 bit and run well on the Raspberry Pi. For this guide, I will show how I got NuPIC running on the Raspberry Pi 3B+ using an arm64 build of Xubuntu (including GPIO access). Nupic 1.0.5 connected with NuPIC core 1.0.6 built from source on this system passes all test cases. This should also work for the Pi 2 (rev 1.2) and 3B, however I do not have those models myself to test on.

Firstly, you will need to download an arm64 Linux build that is compatible with the Raspberry Pi. I like this Xubuntu installer created by stillwinter, because it is a pure Xubuntu system with the exception of only the bootloader and wifi firmware. With this system, you don’t have to use any special commands to perform updates.

Note that this is a standard Xubuntu installer, not the typical img file that you might be used to flashing to an SD card for the Pi. To use it, you will need a USB thumb drive that has a FAT32 partition (needs to use an MBR/msdos partition table) Unzip the files and copy all of them (including the usually hidden ‘.disk’ folder) to the USB thumb drive.

Next you need to enable your Pi to boot from a USB thumb drive. For this, you will need an SD card that is flashed with the latest Raspbian Stretch. Boot your Pi into Raspbian and open a terminal. Enter:

echo program_usb_boot_mode=1 | sudo tee -a /boot/config.txt

This adds program_usb_boot_mode=1 to the end of /boot/config.txt . Reboot the Raspberry Pi with sudo reboot , then check that the OTP has been programmed with:

$ vcgencmd otp_dump | grep 17:
17:3020000a

Ensure the output 0x3020000a is shown.

Then power down your Pi, remove the SD card, plug in the USB thumb drive, and power it back up. It will sit at the rainbow screen for a long time, but eventually the Xubuntu installer will launch.

Whichever SD card you want to install Xubuntu on, be sure to wipe it clean from another PC. I used gparted, and unmounted and deleted all partitions. Then I inserted the blank SD card into the Pi once the Xubuntu installer had launched.

With the blank SD card in the Pi, begin the installation process. When asked, choose the option to “Erase disk and install Xubuntu”. When the installation is complete, click the button to Restart. You can now boot Xubuntu from the SD card, and won’t need the USB thumb drive any more.

Begin by updating everything, and installing some required packages:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install curl git gcc g++ cmake python2.7-dev zlib1g-dev libyaml-dev python-pip
sudo -H pip install --upgrade setuptools wheel RPi.GPIO
sudo -H pip install pycapnp==0.6.3

A header used by numpy core has changed in the version of GNU C we are running, so we’ll need to make a symlink to avoid an error while installing the remaining dependencies.

sudo ln -s /usr/include/locale.h /usr/include/xlocale.h

Next, install NuPIC Core from source. NuPIC 1.0.5 calls for NuPIC Core 1.0.6 specifically so check out that tag.

cd ~   # (or wherever you prefer)
git clone -b 1.0.6 https://github.com/numenta/nupic.core.git
cd nupic.core
NUPIC_CORE="$(pwd)"

Install any remaining dependencies. The system will become unresponsive during CPU-intensive points during this step.

sudo -H pip install -r bindings/py/requirements.txt

If you are having problems with your Pi overheating, you might want to shut it down after this step and let it cool before continuing (but don’t forget to set variable $NUPIC_CORE again if you reboot!)

Set some required ENV variables:

export CC=gcc
export CXX=g++
export USER=pi      # replace with correct user if not "pi"

At this point, if you try to build NuPIC core, it will fail due to some code that is written to throw an exception in a destructor. This issue was resolved in PR #1432 which was merged after 1.0.6, so we’ll need to make that change before building:

*** Expand to see the required code changes ***

Edit Output.hpp:
nano $NUPIC_CORE/src/nupic/engine/Output.hpp

And add “noexcept(false)” to line 52:
~Output() noexcept(false);

Then edit Output.cpp:
nano $NUPIC_CORE/src/nupic/engine/Output.cpp

And add “noexcept(false)” to line 44:
Output::~Output() noexcept(false) {

Another place the build will fail is due to some asm code that isn’t compatible with arm64. This issue is addressed in PR #1440 (pending review at the time of writing this). We will need to make that change as well before building:

*** Expand to see the required code changes ***

Edit ArrayAlgo.hpp:
nano $NUPIC_CORE/src/nupic/math/ArrayAlgo.hpp

Add “defined(NTA_ASM)” to the condition on line 3427:
#if defined(NTA_ASM) && defined(NTA_ARCH_64) && !defined(NTA_OS_WINDOWS)

Edit CMakeLists.txt
nano $NUPIC_CORE/src/CMakeLists.txt

Change line 94 to:

if(NOT ("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7l" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64"))

Now you are ready to generate the build scripts:

mkdir -p $NUPIC_CORE/build/scripts
cd $NUPIC_CORE/build/scripts
cmake $NUPIC_CORE -DCMAKE_BUILD_TYPE=Release -DPY_EXTENSIONS_DIR=$NUPIC_CORE/bindings/py/src/nupic/bindings -UNTA_ASM

You are now ready to build NuPIC Core. The system will become unresponsive during CPU-intensive points during the build. You can use -j3 instead to put less stress on the system, but it will take longer to complete. If you are having problems with your Pi overheating, you might want to shut it down after this step and let it cool before continuing.

make -j4

Once NuPic Core is built, install it:

sudo make install

And finally run the tests (all should pass)

cpp_region_test
unit_tests

To avoid a pycapnp related error, install the “develop” version of nupic.bindings Python library

cd $NUPIC_CORE
sudo python setup.py develop

Run the NuPIC bindings tests:

sudo python setup.py test

All should pass. There will be two warnings.

Now install NuPIC 1.0.5:

sudo -H pip install nupic==1.0.5

And finally, run the unit tests

cd ~   # (or wherever you prefer)
git clone -b 1.0.5 https://github.com/numenta/nupic.git
cd nupic
py.test tests/unit

All should pass. There will be five warnings.


#2

Nice writeup, a few comments though:

  1. Raspberry pi has 4 cores, so you should do make -j4
  2. Can you export a wheel so others don’t have to go through the pain?

#3

There is some debate about this point (Googling will give you mixed answers). Typically breaks down to three camps – use number of cores, number of cores plus 1, or number of cores * 1.5. My own experience is that the last one is the fastest. (not 50% faster though – it isn’t linear). That said, I’ve not run any benchmarks on the Pi, so that is probably the first step to figure out the best value to use. I’ll do that at some point. In the meantime I’ve updated the guide to -j4

Still new to Python, but I’ll look into that. What I’m working on now is optimizing the process (for example, I ran everything with elevated permissions). Also planning to do a flashable img and a Docker image.


#4

Dude, you’re awesome.

That’s all.