R 中的矩阵乘法速度与 Python 一样快?

Matrix multiplication speeds in R as fast as in Python?

与 python 相比,我在 R 中遇到的矩阵乘法要慢得多。这适用于大型矩阵。例如(在 python 中):

import numpy as np

A = np.random.rand(4112, 23050).astype('float32')
B = np.random.rand(23050, 2500).astype('float32')

%timeit np.dot(A, B)

1 loops, best of 3: 1.09 s per loop

这是 R 中的等价乘法(花费将近 10 倍的时间):

A <- matrix(rnorm(4112*23050), ncol = 23050)
B <- matrix(rnorm(23050*2500), ncol = 2500)

system.time(A %*% B)

user    system  elapsed 
72.032   1.048   9.444 

如何在 R 中实现与标准 python 相媲美的矩阵乘法速度?

我已经尝试过的:

1) 部分差异似乎是 python 支持 float32,而 R 仅使用数字,类似于(与?)float64。例如,与上面相同的 python 命令,除了 float64 需要两倍的时间(但仍然比 R 慢 5 倍):

import numpy as np

A = np.random.rand(4112, 23050).astype('float64')
B = np.random.rand(23050, 2500).astype('float64')

%timeit np.dot(A, B)
1 loops, best of 3: 2.24 s per loop

2) 我正在为 R 使用 openBLAS 线性代数后端。

3) RcppEigen 详见 的回答(参见 link 的 test.cpp 文件)。乘法在 "user" 时间内的速度大约是原来的两倍,但在更关键的运行时间内慢了 3 倍,因为它只使用了 8 个线程中的一个。

library(Rcpp)
sourceCpp("test.cpp")

A <- matrix(rnorm(4112*23050), nrow = 4112)
B <- matrix(rnorm(23050*2500), ncol = 2500)

system.time(res <- eigenMatMult(A, B))
user    system  elapsed 
29.436   0.056  29.551 

我将 MROpythonanacondaMKL BLAS 一起使用。这是相同数据生成过程的结果,即 np.random.rand'float64')或 rnorm 和相同的维度(10 次重复的平均值和标准偏差):

Python:

np.dot(A, B) # 1.3616 s (sd = 0.1776)

R:

Bt = t(B)
a = A %*% B # 2.0285 s (sd = 0.1897)
acp = tcrossprod(A, Bt) # 1.3098 s (sd = 0.1206)
identical(acp, a) # TRUE

有点切线,但我认为对于评论来说太长了。要检查是否设置了相关的编译器标志(例如 -fopenmp),请使用 sourceCpp("testeigen.cpp",verbose=TRUE).

在我的系统上,这表明默认情况下 未定义 OpenMP 标志。

我这样做是为了启用它们(改编自 here):

library(Rcpp)
pkglibs <- "-fopenmp -lgomp"
pkgcxxflags <- "-fopenmp"
Sys.setenv(PKG_LIBS=pkglibs,PKG_CXXFLAGS=pkgcxxflags)
sourceCpp("testeigen.cpp",verbose=TRUE)
  • Dirk Eddelbuettel comments 他更喜欢在 ~/.R/Makevars 中设置编译器标志。
  • 我从调用内部 Rcpp:::RcppLdFlagsRcpp:::RcppCxxFlags 函数中获取的示例并将结果添加到上面给出的标志中;这似乎没有必要(?)