Падение производительности после помещения функции Rcpp в пакет R - PullRequest
0 голосов
/ 07 ноября 2018

Я хочу ускорить умножение матриц в R с помощью библиотеки C ++ Eigen. Каким-то образом моя простая функция 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

Почему это происходит? Вот ссылка на функцию в пакете https://github.com/alexandergerber/svmod/blob/master/src/utility.cpp

Редактировать

В своей сессии Info я обнаружил, что в то время пакет работал плохо, и 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

Я не знаю, как воспроизвести первый сеанс, чтобы проверить, является ли это источником проблемы.

1 Ответ

0 голосов
/ 07 ноября 2018

Не полный ответ (пока), но я хочу отметить, что у меня не получается такое поведение:

# 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 
...