Numpy is a great software package for doing numeric computations in Python. If set up right (i.e. using OpenBLAS), I’ve found it can be even faster than MATLAB’s highly optimized ATLAS backend. Unfortunately, if installed naïvely using
pip, it can be very slow. Even installing it using
sudo apt-get install python-numpy (on Ubuntu) is not as good as the following setup in my experience.
Here I will tell you how to set up Numpy and OpenBLAS on an Ubuntu machine from source (though I think they should be pretty transferable to any flavour of Linux). These instructions are based on the very useful blog post that can be found on odsf’s blog.
Before we begin
First, make sure you have these tools installed
sudo apt-get install git python-dev gfortran
Also, it might make things easier to make sure that the other Fortran compiler,
g77, is not installed (though if you prefer to keep it around, you just have to take an extra step in the Numpy install).
The first step is to install OpenBLAS. This can be done via
apt-get, but installing from source has the advantages that OpenBLAS will be fully optimized to your machine, and you can put it somewhere other than
/usr/lib (which should hopefully allow Octave to be installed simultaneously, though I haven’t tried this yet).
To install OpenBLAS, do the following commands
cd ~/src git clone https://github.com/xianyi/OpenBLAS cd OpenBLAS make FC=gfortran sudo make PREFIX=/opt/openblas install
As you can see, I prefer to put my OpenBLAS install in
/opt, so it’s out of the way of things I install with
Finally, you have to let your system know about these new libraries. Add a file to
openblas.conf, containing the path to your new libraries (
/opt/openblas/lib). Then run
Building Numpy requires Cython, so make sure it is installed (
pip install cython, with
--user as necessary depending on where you want to install it).
Next, we install Numpy
cd ~/src git clone https://github.com/numpy/numpy cd ~/numpy
By default, the repository will be on the current development (
master) branch. I prefer to use the latest stable branch. To find this, type
git checkout v and press Tab. This should show you all the possible branches. Find the newest branch (largest version number) with no letters after it (indicating a full release). Right now it’s
git checkout v1.10.4
Add a file called
site.cfg, with the following lines
[default] include_dirs = /opt/openblas/include library_dirs = /opt/openblas/lib [openblas] openblas_libs = openblas library_dirs = /opt/openblas/lib [lapack] lapack_libs = openblas library_dirs = /opt/openblas/lib
This file lets Numpy know where your OpenBLAS libraries are. Run
python setup.py config to make sure everything is set up correctly. You should see no mention of ATLAS. (TODO: I should try this with ATLAS installed, to see if Numpy ignores it or tries to use it.) If everything looks good, go ahead and call
python setup.py build. If you have both Fortran compilers installed, call:
python setup.py build --fcompiler=gnu95
gfortran as the compiler (see Numpy install notes).
One of the benefits of using OpenBLAS is that it can make Numpy’s
dot function for matrix-matrix multiplies really fast. For this to work, Numpy needs the file
core/_dotblas.so to exist. In your Numpy source directory (where you should still be if you’re following along), look under
build/lib.linux-x86_64-2.7/numpy/core, and make sure
_dotblas.so is there. You can also run
ldd on it, to make sure that it’s finding your OpenBLAS library all right. (Update: new versions of Numpy no longer create
_dotblas.so, see below.)
If everything seems good, call
python setup.py install. Installing to a virtual environment is best. Otherwise, use the
--user flag to install to your home directory, or put the
sudo command on front to install to the
To make sure everything is working right, I run the following script
import numpy as np import numpy.random as npr import time # --- Test 1 N = 1 n = 1000 A = npr.randn(n,n) B = npr.randn(n,n) t = time.time() for i in range(N): C = np.dot(A, B) td = time.time() - t print("dotted two (%d,%d) matrices in %0.1f ms" % (n, n, 1e3*td/N)) # --- Test 2 N = 100 n = 4000 A = npr.randn(n) B = npr.randn(n) t = time.time() for i in range(N): C = np.dot(A, B) td = time.time() - t print("dotted two (%d) vectors in %0.2f us" % (n, 1e6*td/N)) # --- Test 3 m,n = (2000,1000) A = npr.randn(m,n) t = time.time() [U,s,V] = np.linalg.svd(A, full_matrices=False) td = time.time() - t print("SVD of (%d,%d) matrix in %0.3f s" % (m, n, td)) # --- Test 4 n = 1500 A = npr.randn(n,n) t = time.time() w, v = np.linalg.eig(A) td = time.time() - t print("Eigendecomp of (%d,%d) matrix in %0.3f s" % (n, n, td))
And on my machine, I get these results
multiplied two (1000,1000) matrices in 49.8 ms dotted two (4000) vectors in 6.87 us SVD of (2000,1000) matrix in 1.192 s Eigendecomp of (1500,1500) matrix in 7.805 s
If just the matrix-matrix multiply is slow, it’s likely because
core/_dotblas.so didn’t get created, or can’t find your OpenBLAS library (see above). If the SVD and Eigendecomposition are slow, it’s likely that you have a problem with the LAPACK linking (this only happened when I tried to use the OpenBLAS installation from
_dotblas.so in new Numpy
New versions of Numpy no longer create
_dotblas.so, so don’t worry if you don’t see it. If Numpy is finding your OpenBLAS install when you do
python setup.py config, you’re probably good.
Scipy is easy to install, because it will make use of Numpy’s OpenBLAS bindings. Just run
pip install scipy and you should be good to go, or install normally from source to get the lastest development version.