将 Rcpp 函数放入 R 包后的性能故障
Performance breakdown after putting an Rcpp function into an R package
我想通过使用 c++ Eigen 库来加速 R 中的矩阵乘法。
不知何故,我的简单函数 eigen_mult
在放入包中时表现非常不同。
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
//[[Rcpp::export]]
Eigen::MatrixXd eigen_mult(Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> X){
return(A * X);
}
基准测试结果:
set.seed(1)
A <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
B <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
microbenchmark::microbenchmark(
"base R" = A %*% B,
"Eigen1" = eigen_mult(A, B),
"Eigen2" = svmod::eigen_mult2(A,B), # exactly the same function but within a package
times = 10
)
Unit: milliseconds
expr min lq mean median uq max neval
base R 685.4485 744.8911 921.5104 878.4409 1040.7563 1405.5009 10
Eigen1 173.9677 180.8769 201.6563 198.3676 218.2076 240.8219 10
Eigen2 6495.3652 6533.3584 6937.0707 7031.7074 7135.5751 7292.6177 10
为什么会这样?这是 link 到包 https://github.com/alexandergerber/svmod/blob/master/src/utility.cpp
中的函数
编辑
在我的会话信息中,我发现包和 RcppEigen
运行不佳时是 loaded via a namespace (and not attached)
:
other attached packages:
[1] microbenchmark_1.4-6
loaded via a namespace (and not attached):
[1] compiler_3.5.1 RcppEigen_0.3.3.4.0 Matrix_1.2-14 tools_3.5.1 yaml_2.2.0 Rcpp_0.12.19 svmod_0.1.0
[8] grid_3.5.1 lattice_0.20-35
而它正在工作的会话看起来像这样:
other attached packages:
[1] svmod_0.1.0 microbenchmark_1.4-6
loaded via a namespace (and not attached):
[1] compiler_3.5.1 Matrix_1.2-14 tools_3.5.1 yaml_2.2.0 Rcpp_0.12.19 grid_3.5.1 lattice_0.20-35
我不知道如何重现第一个会话来检查这是否是问题的根源。
(还)不是一个完整的答案,但我想指出我没有得到这种行为:
# Try using a new package from scratch, with only this function
Rcpp::Rcpp.package.skeleton("svmod", example_code = FALSE)
# Then add RcppEigen in LinkingTo, add eigen_mult.cpp to src/
Rcpp::compileAttributes("svmod")
devtools::install("svmod")
Rcpp::sourceCpp("eigen_mult.cpp")
library(microbenchmark)
set.seed(1)
A <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
B <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
microbenchmark(
"base R" = A %*% B,
"Eigen1" = eigen_mult(A, B),
"Eigen2" = svmod::eigen_mult(A,B),
times = 10
)
Unit: milliseconds
expr min lq mean median uq max neval cld
base R 853.6304 858.1488 882.5745 871.6440 894.3132 938.8883 10 b
Eigen1 172.4896 173.4745 174.5335 174.5249 175.4813 177.6152 10 a
Eigen2 170.9105 174.1170 174.7807 174.3971 176.5156 179.0742 10 a
# Try your package
remove.packages("svmod")
devtools::install_github("alexandergerber/svmod")
# (in a new R session)
Rcpp::sourceCpp("eigen_mult.cpp")
library(microbenchmark)
set.seed(1)
A <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
B <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
microbenchmark(
"base R" = A %*% B,
"Eigen1" = eigen_mult(A, B),
"Eigen2" = svmod::eigen_mult2(A,B),
times = 10
)
Unit: milliseconds
expr min lq mean median uq max neval cld
base R 813.7922 820.6887 854.6929 837.3059 879.7640 978.0778 10 b
Eigen1 171.8826 172.6738 210.6316 181.7109 246.6778 332.1725 10 a
Eigen2 171.7884 172.8768 176.0966 173.5973 177.5424 186.5957 10 a
我想通过使用 c++ Eigen 库来加速 R 中的矩阵乘法。
不知何故,我的简单函数 eigen_mult
在放入包中时表现非常不同。
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
//[[Rcpp::export]]
Eigen::MatrixXd eigen_mult(Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> X){
return(A * X);
}
基准测试结果:
set.seed(1)
A <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
B <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
microbenchmark::microbenchmark(
"base R" = A %*% B,
"Eigen1" = eigen_mult(A, B),
"Eigen2" = svmod::eigen_mult2(A,B), # exactly the same function but within a package
times = 10
)
Unit: milliseconds
expr min lq mean median uq max neval
base R 685.4485 744.8911 921.5104 878.4409 1040.7563 1405.5009 10
Eigen1 173.9677 180.8769 201.6563 198.3676 218.2076 240.8219 10
Eigen2 6495.3652 6533.3584 6937.0707 7031.7074 7135.5751 7292.6177 10
为什么会这样?这是 link 到包 https://github.com/alexandergerber/svmod/blob/master/src/utility.cpp
中的函数编辑
在我的会话信息中,我发现包和 RcppEigen
运行不佳时是 loaded via a namespace (and not attached)
:
other attached packages:
[1] microbenchmark_1.4-6
loaded via a namespace (and not attached):
[1] compiler_3.5.1 RcppEigen_0.3.3.4.0 Matrix_1.2-14 tools_3.5.1 yaml_2.2.0 Rcpp_0.12.19 svmod_0.1.0
[8] grid_3.5.1 lattice_0.20-35
而它正在工作的会话看起来像这样:
other attached packages:
[1] svmod_0.1.0 microbenchmark_1.4-6
loaded via a namespace (and not attached):
[1] compiler_3.5.1 Matrix_1.2-14 tools_3.5.1 yaml_2.2.0 Rcpp_0.12.19 grid_3.5.1 lattice_0.20-35
我不知道如何重现第一个会话来检查这是否是问题的根源。
(还)不是一个完整的答案,但我想指出我没有得到这种行为:
# Try using a new package from scratch, with only this function
Rcpp::Rcpp.package.skeleton("svmod", example_code = FALSE)
# Then add RcppEigen in LinkingTo, add eigen_mult.cpp to src/
Rcpp::compileAttributes("svmod")
devtools::install("svmod")
Rcpp::sourceCpp("eigen_mult.cpp")
library(microbenchmark)
set.seed(1)
A <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
B <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
microbenchmark(
"base R" = A %*% B,
"Eigen1" = eigen_mult(A, B),
"Eigen2" = svmod::eigen_mult(A,B),
times = 10
)
Unit: milliseconds
expr min lq mean median uq max neval cld
base R 853.6304 858.1488 882.5745 871.6440 894.3132 938.8883 10 b
Eigen1 172.4896 173.4745 174.5335 174.5249 175.4813 177.6152 10 a
Eigen2 170.9105 174.1170 174.7807 174.3971 176.5156 179.0742 10 a
# Try your package
remove.packages("svmod")
devtools::install_github("alexandergerber/svmod")
# (in a new R session)
Rcpp::sourceCpp("eigen_mult.cpp")
library(microbenchmark)
set.seed(1)
A <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
B <- matrix(rnorm(1000000), ncol = 1000, nrow = 1000)
microbenchmark(
"base R" = A %*% B,
"Eigen1" = eigen_mult(A, B),
"Eigen2" = svmod::eigen_mult2(A,B),
times = 10
)
Unit: milliseconds
expr min lq mean median uq max neval cld
base R 813.7922 820.6887 854.6929 837.3059 879.7640 978.0778 10 b
Eigen1 171.8826 172.6738 210.6316 181.7109 246.6778 332.1725 10 a
Eigen2 171.7884 172.8768 176.0966 173.5973 177.5424 186.5957 10 a