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

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 | libblas.so.3
  • liblapack3 | liblapack.so.3

  • 默认情况下,这些是由引用实现libblas3liblapack3提供的。它们并不是特别快,但是您可以通过安装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_THREADSGOTO_NUM_THREADSOMP_NUM_THREADS并没有达到预期的效果。在CentOS上,即使RhpcBLASctl也无济于事,因为使用的OpenBLAS是单线程的。

    关于r - 矩阵计算的OS之间存在很大的性能差异,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50857568/

    10-12 20:51