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

Posted

技术标签:

【中文标题】具有不同 BLAS 实现的 NumPy 的性能【英文标题】:performance of NumPy with different BLAS implementations 【发布时间】:2014-10-22 15:38:02 【问题描述】:

我正在运行一个用 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

我一直在运行这个:

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

底线:

在 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

EC2 实例设置:

在 Ubuntu 14.04 上,我安装了 OpenBLAS

sudo apt-get install libopenblas-base libopenblas-dev

在安装 NumPy 时,我创建了一个 site.cfg,内容如下:

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

[atlas]
atlas_libs = openblas

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

【问题讨论】:

Haswell 每个内核每个周期的原始计算量是 Ivybridge 的 2 倍(由于包含 FMA)。我想知道您的 openblas 是否是在未启用 AVX 支持的情况下构建的?这将再提供 2 倍。 听起来可能与this有关。您能否检查您的 EC2 实例是否实际上是多线程 BLAS 操作? 【参考方案1】:

这种行为的原因可能是 Accelerate 使用了多线程,而其他的则没有。

大多数 BLAS 实现都遵循环境变量 OMP_NUM_THREADS 来确定要使用的线程数。我相信如果没有明确告知他们只使用 1 个线程。 Accelerate's man page,不过听起来好像线程是默认开启的;可以通过设置环境变量VECLIB_MAXIMUM_THREADS来关闭。

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

export VECLIB_MAXIMUM_THREADS=1

在调用 Accelerate 版本之前,并且

export OMP_NUM_THREADS=4

对于其他版本。

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

【讨论】:

链接到 Accelerate,VECLIB_MAXIMUM_THREADS 确实会影响 numpy.linalg.norm 的性能。另一方面,scipy.linalg.norm 始终较慢且不受变量影响,这使我相信它与 Accelerate 无关,而是使用参考 LAPACK。 谢谢埃尔玛。 Fwiw,scipy.linalg.norm 确实if ord in (None, 2) and (a.ndim == 1): nrm2 = get_blas_funcs('nrm2')norm 在numpy.linalg.linalg 中说“# 立即处理一些默认的、简单的、快速的和常见的情况”。总之,太复杂了。

以上是关于具有不同 BLAS 实现的 NumPy 的性能的主要内容,如果未能解决你的问题,请参考以下文章

与 Python+Numba LLVM/JIT 编译的代码相比,Julia 的性能

为啥 blas 比 numpy 慢

如何检查 NumPy 和 SciPy 中的 BLAS/LAPACK 链接?

用 LAPACK/BLAS 安装 numpy 的最简单方法是啥?

附加一个具有不同第一维的numpy数组

使用Numpy进行深度学习中5大反向传播优化算法的性能比较