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

时间:2016-07-28 16:58:10

标签: python r numpy rcpp matrix-multiplication

与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 

2 个答案:

答案 0 :(得分:3)

我将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

答案 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)
  • Dirk Eddelbuettel comments,他更喜欢在~/.R/Makevars中设置编译器标记。
  • 我从中调用内部Rcpp:::RcppLdFlagsRcpp:::RcppCxxFlags函数的示例,并将结果添加到上面给出的标志中;这似乎没有必要(?)