用于矩阵计算的OS之间的大的性能差异

F. *_*ivé 5 r

在我的两台计算机上,我尝试了这段代码:

N <- 10e3
M <- 2000
X <- matrix(rnorm(N * M), N)
system.time(crossprod(X))
Run Code Online (Sandbox Code Playgroud)

第一个是标准笔记本电脑,此操作需要1.7秒.

> sessionInfo()
R version 3.4.4 (2018-03-15)
Platform: x86_64-redhat-linux-gnu (64-bit)
Running under: CentOS Linux 7 (Core)

Matrix products: default
BLAS/LAPACK: /usr/lib64/R/lib/libRblas.so
Run Code Online (Sandbox Code Playgroud)

第二个是相当不错的台式电脑,花了17秒.

> sessionInfo()
R version 3.4.4 (2018-03-15)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Linux Mint 18.3

Matrix products: default
BLAS: /usr/lib/libblas/libblas.so.3.6.0
LAPACK: /usr/lib/lapack/liblapack.so.3.6.0
Run Code Online (Sandbox Code Playgroud)

台式计算机比笔记本电脑更高性能,但这种矩阵计算需要10倍的时间.

问题来自默认的BLAS/LAPACK吗?

Ral*_*ner 7

tldr: CentOS使用单线程OpenBLAS,Linux Mint默认使用Reference BLAS,但可以使用其他BLAS版本.

EPEL提供的CentOS R套件依赖于openblas-Rblas.这似乎是为BL提供BLAS的OpenBLAS构建.因此,虽然看起来使用了R的BLAS,但它实际上是OpenBLAS.LAPACK版本始终是R提供的版本.

在Debian和衍生的发行版上,如Mint,r-base-core取决于

  • libblas3 | libblas.so.3
  • liblapack3 | liblapack.so.3

默认情况下,这些由参考实现提供libblas3liblapack3.这些并不是特别快,但您可以通过安装类似的软件包轻松更换它们libopenblas-base.您可以通过控制系统上使用的BLAS和LAPACK update-alternatives.

为了控制OpenBLAS的线程数,我通常使用RhpcBLASctl:

N <- 20000
M <- 2000
X <- matrix(rnorm(N * M), N)
RhpcBLASctl::blas_set_num_threads(2)
system.time(crossprod(X))
#>        User      System verstrichen 
#>       2.492       0.331       1.339
RhpcBLASctl::blas_set_num_threads(1)
system.time(crossprod(X))
#>        User      System verstrichen 
#>       2.319       0.052       2.316
Run Code Online (Sandbox Code Playgroud)

由于某种原因设置环境变量 OPENBLAS_NUM_THREADS,GOTO_NUM_THREADSOMP_NUM_THREADS从R没有预期的效果.在CentOS上甚至RhpcBLASctl没有帮助,因为使用的OpenBLAS是单线程的.


fra*_*cis 5

R是使用默认的BLAS实现分发的,但可能未针对您的计算机进行优化。按照R 的安装指南中的建议,在 R之前通过ATLASOpenBLAS 安装 BLAS的优化版本是可行的方法。如果您轻按Download R for Linux,然后再轻按debian/。据说:

您可能需要安装自动调整的Atlas或多线程OpenBlas库,以便为线性代数运算获得更高的性能

R的源代码可以在此处下载而BLAS实现则位于R-3.5.0/src/extra/blas。例如,矩阵矩阵乘法的Fortran源代码dgemm位于blas.f中,以及大多数BLAS例程(在单个文件中!)。

该函数的注释指定:

 -- Written on 8-February-1989.
 Jack Dongarra, Argonne National Laboratory.
 Iain Duff, AERE Harwell.
 Jeremy Du Croz, Numerical Algorithms Group Ltd.
 Sven Hammarling, Numerical Algorithms Group Ltd.
Run Code Online (Sandbox Code Playgroud)

在例程dgemm的netlib实现中可以找到相同的代码行。

相反,OpenBLAS提供了不同的实现方式,每种实现都针对一种处理器。例如,参见该文件专用于dgemm的haswell微体系结构。有对prefetcht0的调用以进行预取,有对vfmadd231pd的调用,vfmadd231pd是矢量FMA SIMD指令,它一次执行4次双精度d = a * b + c。

使用优化的BLAS可以节省时间。例如,参见此基准测试,其中netlib的dgemm()持续64秒,而MKL,OpenBLAS或ATLAS dgemm花费不到4秒。

R内部BLAS的情况可能比经典的Netlib库更糟。实际上,如附录A.3.1.5 Shared BLAS中所指定R Installation and Administration

R提供了将BLAS编译到存储在R_HOME / lib中的动态库libRblas中的选项,并且可以将R本身和所有附加软件包链接到该库。....使用共享的BLAS可能会有性能上的缺点。...但是,实验表明,在许多情况下,只要使用了高级编译器优化,使用共享BLAS的速度就一样快。

查看R的config.site文件,可以看到,对于g77 / gfortran,优化级别为“ -O2”。因此,如果fortran编译器不是g77 / gfortran,调整FFLAGS选项可能会很有用。在配置步骤中,应该有一行checking whether we are using the GNU Fortran 77 compiler... yes(配置文件的7521行)。