【问题标题】:Compiling numpy with OpenBLAS integration使用 OpenBLAS 集成编译 numpy
【发布时间】:2012-07-11 23:59:47
【问题描述】:

我正在尝试使用 OpenBLAS 安装 numpy ,但是我不知道如何编写 site.cfg 文件。

当遵循installation procedure 时,安装完成且没有错误,但是将 OpenBLAS 使用的线程数从 1 增加(由环境变量 OMP_NUM_THREADS 控制)会导致性能下降。

我不确定 OpenBLAS 集成是否完美。任何人都可以提供一个site.cfg 文件来实现同样的目的。

P.S.:OpenBLAS 集成到其他工具包(如基于 Python 的 Theano)中,可在同一台机器上增加线程数量,从而显着提升性能。

【问题讨论】:

  • 当您说性能下降时,您确定问题大到足以保证增加线程吗?对于太小的问题,使用额外的线程会导致性能下降,我不知道openblas是否足够聪明,只在有用的时候使用额外的线程。
  • 为了检查性能随问题大小的变化,我尝试对随机生成的各种大小的矩阵(100x100、100x1000、1000x1000、1000x10000、10000x10000)使用 numpy.linalg.svd 函数) 但在所有这些情况下,最好的执行时间都是通过 openblas 中的单线程实现的。即使对于繁重的计算负载(例如 10000x10000 矩阵 SVD),单线程也需要 5000 秒,而 3 个线程需要 6000 秒。这让我有点担心,我只是想检查一下openblas集成是否正确。

标签: python numpy blas atlas openblas


【解决方案1】:

我刚刚在带有OpenBLAS 集成的virtualenv 中编译了numpy,它似乎工作正常。

这是我的过程:

  1. 编译OpenBLAS:

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

    如果您没有管理员权限,您可以将PREFIX= 设置为您有写入权限的目录(只需相应地修改下面的相应步骤)。

  2. 确保包含libopenblas.so 的目录在您的共享库搜索路径中。

    • 要在本地执行此操作,您可以编辑 ~/.bashrc 文件以包含该行

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

      LD_LIBRARY_PATH 环境变量将在您启动新的终端会话时更新(使用 $ source ~/.bashrc 在同一会话中强制更新)。

    • 另一个适用于多个用户的选项是在/etc/ld.so.conf.d/ 中创建一个包含/opt/OpenBLAS/lib 行的.conf 文件,例如:

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

    完成任一选项后,运行

    $ sudo ldconfig
    
  3. 获取numpy源代码:

    $ git clone https://github.com/numpy/numpy
    $ cd numpy
    
  4. site.cfg.example 复制到site.cfg 并编辑副本:

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

    取消注释这些行:

    ....
    [openblas]
    libraries = openblas
    library_dirs = /opt/OpenBLAS/lib
    include_dirs = /opt/OpenBLAS/include
    ....
    
  5. 检查配置、构建、安装(可选在 virtualenv 内)

    $ python setup.py config
    

    输出应该是这样的:

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

    使用pip 安装是preferable 到使用python setup.py install,因为pip 将跟踪包元数据并允许您在将来轻松卸载或升级numpy。

    $ pip install .
    
  6. 可选:您可以使用this script 来测试不同线程数的性能。

    $ 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
    

对于更高的线程数,性能似乎有了显着的提高。但是,我没有对此进行非常系统的测试,而且对于较小的矩阵,额外的开销可能会超过更高线程数带来的性能优势。

【讨论】:

  • 我在测试脚本 /linalg/lapack_lite.so: undefined symbol: zgelsd_
  • 即使我严格按照您在上面输入的答案进行操作,我也有以下内容。 libopenblas.so.0 => /usr/lib/libopenblas.so.0 (0x00007f77e08fc000)
  • 还有一个问题。 openBlas 是依赖于 OpenMPI 还是使用它来提高性能?
  • 在 2015 年,我在此处建议的步骤中遇到了一些问题。我发现this 工作得更好。
  • @Afshin - 如果不是sudo 用户,最好将第一步sudo make PREFIX=/opt/OpenBLAS install 更改为使用您自己的主目录中的位置前缀(例如make PREFIX=/home/your_username/my_software/),这那么应该允许您为自己的文件运行ldconfig 命令。
【解决方案2】:

如果您使用的是 ubuntu 或 mint,您可以通过 apt-get as 同时安装 numpy 和 openblas 来轻松地将 openblas 链接到 numpy

sudo apt-get install numpy libopenblas-dev

在一个新的 docker ubuntu 上,我测试了从博客文章 "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))

没有 openblas 的结果是:

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

在我用apt install openblas-dev 安装openblas 后,我用

检查了numpy 链接
import numpy as np
np.__config__.show()

信息是

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

它没有显示与 openblas 的链接。但是,脚本的新结果显示 numpy 肯定使用过 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

【讨论】:

    【解决方案3】:

    这是一种比@ali_m 的答案更简单的方法,它适用于 macOS。

    1. 如果您没有 gfortran 编译器,请安装它。例如。在 macOS 上使用自制软件:

      $ brew install gcc
      
    2. 从源代码编译OpenBLAS [或使用包管理器],获取源代码库或downloading a release

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

      如果你不会/不能sudo,请将PREFIX=设置为另一个目录并在下一步修改路径。

      OpenBLAS 不需要在编译器包含路径或链接器库路径上。

    3. 创建一个~/.numpy-site.cfg 文件,其中包含您在第 2 步中使用的 PREFIX 路径:

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

      include_dirs 用于编译器。 library_dirs 用于链接器。 runtime_library_dirs 用于加载程序,可能不需要。

    4. pip-install numpy 和 scipy 从源代码(最好安装到 virtualenv 中)无需手动下载[您也可以指定发布版本]:

      pip install numpy scipy --no-binary numpy,scipy
      
    5. 根据我的经验,这个 OPENBLAS_NUM_THREADS 在运行时设置使 OpenBLAS 更快,而不是更慢,尤其是。当多个 CPU 进程同时使用它时:

       export OPENBLAS_NUM_THREADS=1
      

      (或者,您可以使用 make FC=gfortran USE_THREAD=0 编译 OpenBLAS。)

    查看其他答案以了解测试方法。

    【讨论】:

    • 在 macOS 11、python 3.9 上为我工作。您可以使用 brew 安装 openblas,并使用 brew info openblas 查找 PREFIX。对我来说是/usr/local/Cellar/openblas/0.3.10_1/
    • 我有macOs11并用brew安装了openblas,我的前缀是:/usr/local/Cellar/openblas/0.3.12_1,但是我不知道接下来要做什么,我应该把~/.numpy-site放在哪里。 cfg文件???文件内的唯一内容应该是 [openblas] 位?还是一定有别的?
    • @digolira2 ~/ 是您的主目录的绝对路径,与$HOME 相同。是的,它只需要[openblas] 部分。
    • 哇,谢谢@Jerry101,效果很好!!! =)))。只是一个菜鸟问题,numpy 安装程序如何知道它必须查看 ~/.numpy-site.cfg 文件?因为我没有做任何链接,只是在根文件夹中创建的。
    • @digolira2 该路径必须内置到 numpy 和 scipy 安装程序中。
    猜你喜欢
    • 1970-01-01
    • 2018-02-22
    • 1970-01-01
    • 2013-12-24
    • 2018-01-25
    • 1970-01-01
    • 1970-01-01
    • 2015-05-15
    • 1970-01-01
    相关资源
    最近更新 更多