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
我将 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
有点切线,但我认为对于评论来说太长了。要检查是否设置了相关的编译器标志(例如 -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:::RcppLdFlags
和 Rcpp:::RcppCxxFlags
函数中获取的示例并将结果添加到上面给出的标志中;这似乎没有必要(?)
与 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 详见
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
我将 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
有点切线,但我认为对于评论来说太长了。要检查是否设置了相关的编译器标志(例如 -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:::RcppLdFlags
和Rcpp:::RcppCxxFlags
函数中获取的示例并将结果添加到上面给出的标志中;这似乎没有必要(?)