54

I am trying to install numpy with OpenBLAS , however I am at loss as to how the site.cfg file needs to be written.

When the installation procedure was followed the installation completed without errors, however there is performance degradation on increasing the number of threads used by OpenBLAS from 1 (controlled by the environment variable OMP_NUM_THREADS).

I am not sure if the OpenBLAS integration has been perfect. Could any one provide a site.cfg file to achieve the same.

P.S.: OpenBLAS integration in other toolkits like Theano, which is based on Python, provides substantial performance boost on increasing the number of threads, on the same machine.

Community
  • 1
  • 1
Vijay
  • 849
  • 1
  • 8
  • 10
  • 1
    When you say that there was a performance degradation, are you sure that the problem was big enough to warrant the additional threads? For too small problems you will cause performance degradation when using extra threads, and I don't know if openblas is smart enough to only use extra threads when they are useful. – DaveP Jul 12 '12 at 07:54
  • In order to check for variation of performance with the size of the problem I tried using the numpy.linalg.svd function on randomly generated matrices of various sizes, (100x100, 100x1000, 1000x1000, 1000x10000,10000x10000) but in all these cases the best execution times are achieved with single thread in openblas. Even for heavy computation load (e.g. 10000x10000 matrix SVD) the single thread takes 5000 secs while 3 threads take 6000 seconds. This worries me a bit, I just want to check if the openblas integration is right. – Vijay Jul 12 '12 at 19:48

3 Answers3

100

I just compiled numpy inside a virtualenv with OpenBLAS integration, and it seems to be working OK.

This was my process:

  1. Compile OpenBLAS:

    $ git clone https://github.com/xianyi/OpenBLAS
    $ cd OpenBLAS && make FC=gfortran
    $ sudo make PREFIX=/opt/OpenBLAS install
    

    If you don't have admin rights you could set PREFIX= to a directory where you have write privileges (just modify the corresponding steps below accordingly).

  2. Make sure that the directory containing libopenblas.so is in your shared library search path.

    • To do this locally, you could edit your ~/.bashrc file to contain the line

      export LD_LIBRARY_PATH=/opt/OpenBLAS/lib:$LD_LIBRARY_PATH
      

      The LD_LIBRARY_PATH environment variable will be updated when you start a new terminal session (use $ source ~/.bashrc to force an update within the same session).

    • Another option that will work for multiple users is to create a .conf file in /etc/ld.so.conf.d/ containing the line /opt/OpenBLAS/lib, e.g.:

      $ sudo sh -c "echo '/opt/OpenBLAS/lib' > /etc/ld.so.conf.d/openblas.conf"
      

    Once you are done with either option, run

    $ sudo ldconfig
    
  3. Grab the numpy source code:

    $ git clone https://github.com/numpy/numpy
    $ cd numpy
    
  4. Copy site.cfg.example to site.cfg and edit the copy:

    $ cp site.cfg.example site.cfg
    $ nano site.cfg
    

    Uncomment these lines:

    ....
    [openblas]
    libraries = openblas
    library_dirs = /opt/OpenBLAS/lib
    include_dirs = /opt/OpenBLAS/include
    ....
    
  5. Check configuration, build, install (optionally inside a virtualenv)

    $ python setup.py config
    

    The output should look something like this:

    ...
    openblas_info:
      FOUND:
        libraries = ['openblas', 'openblas']
        library_dirs = ['/opt/OpenBLAS/lib']
        language = c
        define_macros = [('HAVE_CBLAS', None)]
    
      FOUND:
        libraries = ['openblas', 'openblas']
        library_dirs = ['/opt/OpenBLAS/lib']
        language = c
        define_macros = [('HAVE_CBLAS', None)]
    ...
    

    Installing with pip is preferable to using python setup.py install, since pip will keep track of the package metadata and allow you to easily uninstall or upgrade numpy in the future.

    $ pip install .
    
  6. Optional: you can use this script to test performance for different thread counts.

    $ OMP_NUM_THREADS=1 python build/test_numpy.py
    
    version: 1.10.0.dev0+8e026a2
    maxint:  9223372036854775807
    
    BLAS info:
     * libraries ['openblas', 'openblas']
     * library_dirs ['/opt/OpenBLAS/lib']
     * define_macros [('HAVE_CBLAS', None)]
     * language c
    
    dot: 0.099796795845 sec
    
    $ OMP_NUM_THREADS=8 python build/test_numpy.py
    
    version: 1.10.0.dev0+8e026a2
    maxint:  9223372036854775807
    
    BLAS info:
     * libraries ['openblas', 'openblas']
     * library_dirs ['/opt/OpenBLAS/lib']
     * define_macros [('HAVE_CBLAS', None)]
     * language c
    
    dot: 0.0439578056335 sec
    

There seems to be a noticeable improvement in performance for higher thread counts. However, I haven't tested this very systematically, and it's likely that for smaller matrices the additional overhead would outweigh the performance benefit from a higher thread count.

Community
  • 1
  • 1
ali_m
  • 71,714
  • 23
  • 223
  • 298
  • 4
    I apply what you did bu tending with foollowing error at your test script /linalg/lapack_lite.so: undefined symbol: zgelsd_ – erogol Jan 30 '14 at 17:47
  • 1
    I have following line even I do strictly what you typed above answer. libopenblas.so.0 => /usr/lib/libopenblas.so.0 (0x00007f77e08fc000) – erogol Jan 30 '14 at 18:06
  • One more question. Is openBlas depended to OpenMPI or using it increases the performance? – erogol Jan 30 '14 at 22:54
  • worked for me on mac except for additional installation of fortrang – Maddy.Shik Oct 25 '14 at 05:18
  • 1
    In 2015, I had a few problems with the suggested steps here. I found [this](https://hunseblog.wordpress.com/2014/09/15/installing-numpy-and-openblas/) to work better. – Felipe Jun 25 '15 at 04:27
  • @ali_m I had the same problem as @Erogol (undefined symbol: zgelsd_) and I checked that I saw the line you expected in the output from `ldd`, I uninstalled numpy, ran clean and build and install again but nothing worked. The other link I've provided suggests a few more edits to `site.cfg` in addition to what you suggested so I guess that's what you answer lacks (maybe it's due to my using a newer ubuntu version (14.04)). But your answer pointed me to the right path so I voted it up. – Felipe Jun 25 '15 at 21:20
  • What if not sudoer in step sudo ldconfig? – Ash Feb 06 '17 at 01:54
  • 2
    @Afshin - If not a `sudo` user, best thing it to alter the first step `sudo make PREFIX=/opt/OpenBLAS install` to use a prefix with a location in your own home directory (e.g. `make PREFIX=/home/your_username/my_software/`), which then should allow you to run the `ldconfig` command for your own files. – n1k31t4 Apr 16 '17 at 05:21
  • That test_numpy.py script doesn't exist anymore, got an alternative? – Jonno_FTW Mar 29 '18 at 14:10
  • @ali_m my bad, i was thinking it came with numpy – Jonno_FTW Mar 29 '18 at 14:36
  • first and foremost install `sudo apt install gfortran` – Savrige Feb 19 '20 at 21:56
  • `python setup.py config` returns `RuntimeError: Unrecognized setuptools command: ['config']` for me, is this deprecated? – Dave Aug 24 '21 at 17:17
9

Just in case you are using ubuntu or mint, you can easily have openblas linked numpy by installing both numpy and openblas via apt-get as

sudo apt-get install numpy libopenblas-dev

On a fresh docker ubuntu, I tested the following script copied from the blog post "Installing Numpy and OpenBLAS"

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

Without openblas the result is:

dotted two (1000,1000) matrices in 563.8 ms
dotted two (4000) vectors in 5.16 us
SVD of (2000,1000) matrix in 6.084 s
Eigendecomp of (1500,1500) matrix in 14.605 s

After I installed openblas with apt install openblas-dev, I checked the numpy linkage with

import numpy as np
np.__config__.show()

and the information is

atlas_threads_info:
  NOT AVAILABLE
openblas_info:
  NOT AVAILABLE
atlas_blas_info:
  NOT AVAILABLE
atlas_3_10_threads_info:
  NOT AVAILABLE
blas_info:
    library_dirs = ['/usr/lib']
    libraries = ['blas', 'blas']
    language = c
    define_macros = [('HAVE_CBLAS', None)]
mkl_info:
  NOT AVAILABLE
atlas_3_10_blas_threads_info:
  NOT AVAILABLE
atlas_3_10_blas_info:
  NOT AVAILABLE
openblas_lapack_info:
  NOT AVAILABLE
lapack_opt_info:
    library_dirs = ['/usr/lib']
    libraries = ['lapack', 'lapack', 'blas', 'blas']
    language = c
    define_macros = [('NO_ATLAS_INFO', 1), ('HAVE_CBLAS', None)]
blas_opt_info:
    library_dirs = ['/usr/lib']
    libraries = ['blas', 'blas']
    language = c
    define_macros = [('NO_ATLAS_INFO', 1), ('HAVE_CBLAS', None)]
atlas_info:
  NOT AVAILABLE
blas_mkl_info:
  NOT AVAILABLE
lapack_mkl_info:
  NOT AVAILABLE
atlas_3_10_info:
  NOT AVAILABLE
lapack_info:
    library_dirs = ['/usr/lib']
    libraries = ['lapack', 'lapack']
    language = f77
atlas_blas_threads_info:
  NOT AVAILABLE

It doesn't show linkage to openblas. However, the new result of the script shows that numpy must have used openblas:

dotted two (1000,1000) matrices in 15.2 ms
dotted two (4000) vectors in 2.64 us
SVD of (2000,1000) matrix in 0.469 s
Eigendecomp of (1500,1500) matrix in 2.794 s
entron
  • 353
  • 2
  • 12
5

Here's a simpler approach than @ali_m's answer and it works on macOS.

  1. Install a gfortran compiler if you don't have one. E.g. using homebrew on macOS:

    $ brew install gcc
    
  2. Compile OpenBLAS from source [or use a package manager], either getting the source repo or downloading a release:

    $ git clone https://github.com/xianyi/OpenBLAS
    $ cd OpenBLAS && make FC=gfortran
    $ sudo make PREFIX=/opt/OpenBLAS install
    

    If you don't/can't sudo, set PREFIX= to another directory and modify the path in the next step.

    OpenBLAS does not need to be on the compiler include path or the linker library path.

  3. Create a ~/.numpy-site.cfg file containing the PREFIX path you used in step 2:

    [openblas]
    libraries = openblas
    library_dirs = /opt/OpenBLAS/lib
    runtime_library_dirs = /opt/OpenBLAS/lib
    include_dirs = /opt/OpenBLAS/include
    

    include_dirs is for the compiler. library_dirs is for the linker. runtime_library_dirs is for the loader, and might not be needed.

  4. pip-install numpy and scipy from source (preferably into a virtualenv) without manually downloading them [you can also specify the release versions]:

    pip install numpy scipy --no-binary numpy,scipy
    
  5. In my experience, this OPENBLAS_NUM_THREADS setting at runtime makes OpenBLAS faster, not slower, esp. when multiple CPU processes are using it at the same time:

     export OPENBLAS_NUM_THREADS=1
    

    (Alternatively, you can compile OpenBLAS with make FC=gfortran USE_THREAD=0.)

See the other answers for ways to test it.

Jerry101
  • 12,157
  • 5
  • 44
  • 63
  • Worked for me on macOS 11, python 3.9. You can install `openblas` with brew, and find the PREFIX with `brew info openblas`. For me it was `/usr/local/Cellar/openblas/0.3.10_1/` – Sadderdaze Oct 11 '20 at 14:13
  • I have macOs11 and installed `openblas` with brew, my prefix is: `/usr/local/Cellar/openblas/0.3.12_1`, but I don't know what to do next, where should I put the ~/.numpy-site.cfg file??? The only content inside of the file should be the [openblas] bit ? or there must be something else? – digolira2 Nov 18 '20 at 21:16
  • 1
    @digolira2 `~/` is an absolute path to your home directory, the same as `$HOME`. Yes, it only needs the `[openblas]` section. – Jerry101 Nov 19 '20 at 02:04
  • wowww thank you @Jerry101, it worked perfectly!!! =))). Just one rookie question, how the numpy installer knew that it have to look over the ~/.numpy-site.cfg file? Because I haven't made any links, just created it in the root folder. – digolira2 Nov 19 '20 at 15:42
  • @digolira2 that path must be built into the numpy and scipy installers. – Jerry101 Nov 19 '20 at 19:48