在我的两台计算机上,我尝试了以下代码:
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 默认使用 Reference 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 - 用于矩阵计算的操作系统之间的巨大性能差异,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55615428/