具有不同BLAS实现的NumPy的性能

lum*_*lum 12 numpy amazon-ec2 blas accelerate-framework openblas

我正在运行一个用Python实现并使用NumPy的算法.算法中计算成本最高的部分涉及求解一组线性系统(即调用numpy.linalg.solve().我想出了这个小基准:

import numpy as np
import time

# Create two large random matrices
a = np.random.randn(5000, 5000)
b = np.random.randn(5000, 5000)

t1 = time.time()
# That's the expensive call:
np.linalg.solve(a, b)
print time.time() - t1
Run Code Online (Sandbox Code Playgroud)

我一直在运行:

  1. 我的笔记本电脑,2013年末MacBook Pro 15",2核4芯(sysctl -n machdep.cpu.brand_string给我Intel(R)Core(TM)i7-4750HQ CPU @ 2.00GHz)
  2. Amazon EC2 c3.xlarge实例,具有4个vCPU.亚马逊宣称它们为"高频英特尔至强E5-2680 v2(Ivy Bridge)处理器"

底线:

  • 在Mac上,它运行约4.5秒
  • 在EC2实例上,它运行大约19.5秒

我也在其他基于OpenBLAS/Intel MKL的设置上尝试过它,运行时总是与我在EC2实例上得到的(模块化硬件配置)相当.

任何人都可以解释为什么Mac(使用Accelerate Framework)的性能提高了4倍?下面提供了有关NumPy/BLAS设置的更多详细信息.

笔记本设置

numpy.show_config() 给我:

atlas_threads_info:
  NOT AVAILABLE
blas_opt_info:
    extra_link_args = ['-Wl,-framework', '-Wl,Accelerate']
    extra_compile_args = ['-msse3', '-I/System/Library/Frameworks/vecLib.framework/Headers']
    define_macros = [('NO_ATLAS_INFO', 3)]
atlas_blas_threads_info:
  NOT AVAILABLE
openblas_info:
  NOT AVAILABLE
lapack_opt_info:
    extra_link_args = ['-Wl,-framework', '-Wl,Accelerate']
    extra_compile_args = ['-msse3']
    define_macros = [('NO_ATLAS_INFO', 3)]
atlas_info:
  NOT AVAILABLE
lapack_mkl_info:
  NOT AVAILABLE
blas_mkl_info:
  NOT AVAILABLE
atlas_blas_info:
  NOT AVAILABLE
mkl_info:
  NOT AVAILABLE
Run Code Online (Sandbox Code Playgroud)

EC2实例设置:

在Ubuntu 14.04上,我安装了OpenBLAS

sudo apt-get install libopenblas-base libopenblas-dev
Run Code Online (Sandbox Code Playgroud)

安装NumPy时,我创建了一个site.cfg包含以下内容:

[default]
library_dirs= /usr/lib/openblas-base

[atlas]
atlas_libs = openblas
Run Code Online (Sandbox Code Playgroud)

numpy.show_config() 给我:

atlas_threads_info:
    libraries = ['lapack', 'openblas']
    library_dirs = ['/usr/lib']
    define_macros = [('ATLAS_INFO', '"\\"None\\""')]
    language = f77
    include_dirs = ['/usr/include/atlas']
blas_opt_info:
    libraries = ['openblas']
    library_dirs = ['/usr/lib']
    language = f77
openblas_info:
    libraries = ['openblas']
    library_dirs = ['/usr/lib']
    language = f77
lapack_opt_info:
    libraries = ['lapack', 'openblas']
    library_dirs = ['/usr/lib']
    define_macros = [('ATLAS_INFO', '"\\"None\\""')]
    language = f77
    include_dirs = ['/usr/include/atlas']
openblas_lapack_info:
  NOT AVAILABLE
lapack_mkl_info:
  NOT AVAILABLE
blas_mkl_info:
  NOT AVAILABLE
mkl_info:
  NOT AVAILABLE
Run Code Online (Sandbox Code Playgroud)

Elm*_*ise 3

出现此行为的原因可能是 Accelerate 使用多线程,而其他则不使用。

大多数 BLAS 实现都遵循环境变量OMP_NUM_THREADS来确定要使用多少个线程。我相信如果没有明确告知的话他们只使用 1 个线程。 Accelerate 的手册页,但是听起来默认情况下线程是打开的;可以通过设置环境变量来关闭它VECLIB_MAXIMUM_THREADS

要确定这是否真的发生了,请尝试

export VECLIB_MAXIMUM_THREADS=1
Run Code Online (Sandbox Code Playgroud)

在调用 Accelerate 版本之前,以及

export OMP_NUM_THREADS=4
Run Code Online (Sandbox Code Playgroud)

对于其他版本。

无论这是否是真正的原因,在使用 BLAS 时始终设置这些变量是一个好主意,以确保您控制正在发生的事情。