与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)我正在使用openBLAS线性代数后端进行R。
3) RcppEigen详见答案this SO(参见test.cpp文件的链接)。乘法在“用户”时间内大约快两倍,但在更关键的经过时间中减少3倍,因为它只使用8个线程中的1个。
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
答案 0 :(得分:3)
我将MRO
和python
与anaconda
和MKL
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
答案 1 :(得分:1)
略微切向,但我觉得评论太长了。要检查是否设置了相关的编译器标志(例如-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)
~/.R/Makevars
中设置编译器标记。Rcpp:::RcppLdFlags
和Rcpp:::RcppCxxFlags
函数的示例,并将结果添加到上面给出的标志中;这似乎没有必要(?)