Я пытаюсь понять разницу в производительности между функцией, написанной на RcppArmadillo, и одной написанной в автономной программе на C++ с использованием библиотеки Armadillo. Например, рассмотрим следующую простую функцию, которая вычисляет коэффициенты для линейной модели с использованием традиционной формулы учебника.Разница в производительности между RcppArmadillo и Armadillo
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
using namespace arma;
// [[Rcpp::export]]
void simpleLm(NumericMatrix Xr, NumericMatrix yr) {
int n = Xr.nrow(), k = Xr.ncol();
mat X(Xr.begin(), n, k, false);
colvec y(yr.begin(), yr.nrow(), false);
colvec coef = inv(X.t()*X)*X.t()*y;
}
Это занимает около 6 секунд, чтобы работать с 1000000x100
матрицей для X
. Некоторые тайминги кода (не показаны) показали, что все время расходуется на расчет coef
.
X <- matrix(rnorm(1000000*100), ncol=100)
y <- matrix(rep(1, 1000000))
system.time(simpleLm(X,y))
user system elapsed
6.028 0.009 6.040
Теперь рассмотрим очень сходную функцию, написанный на C++, который затем компилируется с g++
.
#include <iostream>
#include <armadillo>
#include <chrono>
#include <cstdlib>
using namespace std;
using namespace arma;
int main(int argc, char **argv) {
int n = 1000000;
mat X = randu<mat>(n,100);
vec y = ones<vec>(n);
chrono::steady_clock::time_point start = chrono::steady_clock::now();
colvec coef = inv(X.t()*X)*X.t()*y;
chrono::steady_clock::time_point end = chrono::steady_clock::now();
chrono::duration<double, milli> diff = end - start;
cout << diff.count() << endl;
return 0;
}
Здесь вычисление переменной coef
занимает около 0,5 секунд, или только 1/12 время как, когда сделано с RcppArmadillo.
Я использую Mac OS X 10.9.2 с R 3.1.0, Rcpp 0.11.1 и RcppArmadillo 0.4.200.0. Я скомпилировал пример Rcpp, используя функцию sourceCpp. В отдельном примере на C++ используется Armadillo 4.200.0, и я также установил компилятор Fortran для Mac с помощью Homebrew (brew install gfortran
).
Вы не указали установленные флаги оптимизации: если я правильно помню R (и, следовательно, sourceCpp), по умолчанию используется значение -O2, но вы должны проверить (попробуйте 'verbose = TRUE' в' sourceCpp'). Вы должны убедиться, что вы компилируете автономный файл C++ с тем же уровнем оптимизации. –
Да - R использует все, что было использовано при настройке; делать; make install' run, который вы можете переопределить через 'CXXFLAGS' и друзей. Оптимизация вряд ли приведет к тому, что Абиэль увидит здесь порядок. –