Guide: Installing NuPIC on Raspberry Pi

nupic
raspberrypi
guide

#1

NuPIC Version: 1.0.5
Raspbian Version: 2018-06-27 Stretch
Devices tested: Raspberry Pi 3B+
Status: Failed Unit Tests – 11 for NuPIC
Unit Test Warnings – 2 for NuPIC bindings, 5 for NuPIC


Notes: I ran a lot of steps with root privileges. I’ll try and streamline the process some more to remove any extraneous steps and lower privileges.

The first issue that must be dealt with is the fact that Raspbian comes with a 100MB swapfile. This is designed to increase the lifespan of the SD card, but it is too low for building binaries, and you’ll get errors about running out of virtual memory.

IMPORTANT: You need to make sure you have at least 2GB of free space to hold the swap file before making the below changes. Run “df” to see how much free space you have.

After you have verified that you have more than 2GB of free space on your SD card, increase the swapfile size by editing the configuration file:

sudo nano /etc/dphys-swapfile

Find the line that says “CONF_SWAPSIZE=100” and change it to:

CONF_SWAPSIZE=2048

Use Ctrl + X to exit nano, and press Y and Enter to save the changes. Then you will need to restart the service that manages the swapfile for the changes to take effect:

sudo /etc/init.d/dphys-swapfile restart

Begin by updating everything and installing some tools needed for the build process:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install git-core cmake libyaml-dev
sudo -H pip install --upgrade setuptools

Install dependency pycapnp version 0.6.3:

sudo -H pip install pycapnp==0.6.3

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

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

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) {

Because the Raspberry Pi is a 32 bit Linux system, one of the NuPIC bindings interfaces will be broken. This issue is addressed in PR #1438 (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 engine_internal.i:
nano $NUPIC_CORE/src/nupic/bindings/engine_internal.i

and replace the if condition on line 152 with:

#if (defined(NTA_ARCH_32) && defined(NTA_OS_LINUX))
%template(Dimset) std::vector<unsigned long>;
#else

Then edit Dimensions.hpp:
nano $NUPIC_CORE/src/nupic/ntypes/Dimensions.hpp

and after line 100, add:

#if (defined(NTA_ARCH_32) && defined(NTA_OS_LINUX))
  Dimensions(std::vector<unsigned long> v);
#endif

Then edit Dimensions.cpp
nano $NUPIC_CORE/src/nupic/ntypes/Dimensions.hpp

and after line 27, add:

#if (defined(NTA_ARCH_32) && defined(NTA_OS_LINUX))
#include <climits>
#endif

and after line 34 (now 37) add:

#if (defined(NTA_ARCH_32) && defined(NTA_OS_LINUX))
Dimensions::Dimensions(std::vector<unsigned long> v) {
  for (size_t i = 0; i < v.size(); i++) {
    push_back(v[i] & UINT_MAX);
  }
}
#endif

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

Now you can build NuPIC Core:

make -j6

Now that 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

There will be 11 failed and 5 warnings Here is the output. TODO: Investigate


Running NuPIC on Raspberry Pi...having problems
#2

I’ve started publishing Docker images for the Pi (with official Raspbian Stretch, as outlined above), and will keep them updated as we resolve the remaining failures. While not at 100% yet, NuPIC at least partially usable at this point.

I have two images up so far. They should be compatible with all Pi models (though I’ve only tested on the 3B+ and zeroW).

paulscode/nupic:pitest
Comes with the nupic.core and nupic source code under the home folder, where you can access the unit tests and examples. Image is about 1GB

paulscode/nupic:pi
Same as above image, except NuPIC source code is not included. Note this image is barely smaller than the other one – I’m planning to do a lot more cleaning to get it lighter weight.

paulscode/nupic:pizero
Same as nupic:pi image, except built on armel base image instead of armhf. The armhf images used to work on the pi zero w, but recently started failing with code (139). However, armel seems to still be working.

You will first need to install Docker on your Pi. Easiest way is with this command:

curl -fsSL https://get.docker.com/ | sh

Once it completes, add user “pi” to the docker group:

sudo usermod -a -G docker pi

And then reboot the Pi.

Then you can pull the latest NuPIC image you want to run:

docker pull paulscode/nupic:pi

And then launch it with a couple flags to give it access to the GPIO interface:

docker run -it --rm --device /dev/gpiomem:/dev/gpiomem -v /sys:/sys paulscode/nupic:pi /bin/bash

By default, the container will run as user “pi” (with same uid as host).

I typically also mount a local folder to share source code from the host with the container (and so I don’t lose anything when I delete the container). This lets you code in whatever python editor on the host you like without having to install a copy of it in the container as well. For example:

mkdir /home/pi/myproject
docker run -it --rm --device /dev/gpiomem:/dev/gpiomem -v /sys:/sys -v /home/pi/myproject:/home/pi/myproject paulscode/nupic:pi /bin/bash