在我的两台计算机上,我尝试了以下代码:
N <- 10e3
M <- 2000
X <- matrix(rnorm(N * M), N)
system.time(crossprod(X))
第一个是标准笔记本电脑,此操作需要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
第二台是一台相当不错的台式计算机,耗时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
台式计算机比笔记本计算机性能更高,但是这种矩阵计算所需的时间却要多10倍。
问题是否出自所使用的默认BLAS/LAPACK?
最佳答案
tldr: CentOS使用单线程OpenBLAS,Linux Mint默认使用引用BLAS,但可以使用其他BLAS版本。
可从EPEL获得的CentOS的R软件包取决于openblas-Rblas
。这似乎是为R提供BLAS的OpenBLAS构建。因此,尽管看起来使用了R的BLAS,但实际上是OpenBLAS。 LAPACK版本始终是R提供的版本。
在Debian和衍生版本(如Mint)上,r-base-core
取决于
默认情况下,这些是由引用实现
libblas3
和liblapack3
提供的。它们并不是特别快,但是您可以通过安装libopenblas-base
之类的软件包轻松地替换它们。您可以通过update-alternatives
来控制系统上使用的BLAS和LAPACK。为了使用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
由于某些原因,从R设置environment variables
OPENBLAS_NUM_THREADS
,GOTO_NUM_THREADS
或OMP_NUM_THREADS
并没有达到预期的效果。在CentOS上,即使RhpcBLASctl
也无济于事,因为使用的OpenBLAS是单线程的。关于r - 矩阵计算的OS之间存在很大的性能差异,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50857568/