Я начинаю с Rcpp. В настоящее время я написал код Rcpp, который был применен к двум 3-мерным массивам: Array1
и Array2
. Предположим, что Array1
имеет размерность (1000, 100, 40) и Array2
имеет размерность (1000, 96, 40).Эффективность программирования Rcpp
Я хотел бы выполнить wilcox.test
с помощью:
wilcox.test(Array1[i, j,], Array2[i,,])
В R, я написал вложенный for
петли, которые завершили расчет примерно через полчаса.
Затем я написал его в Rcpp. Расчет в Rcpp потребовал часа для достижения тех же результатов. Я думал, что это должно быть быстрее, поскольку он написан на языке C++. Я предполагаю, что мой стиль кодирования является причиной низкой эффективности.
Следующий мой код Rcpp, не могли бы вы помочь мне узнать, какое улучшение я должен сделать, пожалуйста? Я ценю это!
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector Cal(NumericVector Array1,NumericVector Array2,Function wilc) {
NumericVector vecArray1(Array1);
IntegerVector arrayDims1 = vecArray1.attr("dim");
NumericVector vecArray2(Array2);
IntegerVector arrayDims2 = vecArray2.attr("dim");
arma::cube cubeArray1(vecArray1.begin(), arrayDims1[0], arrayDims1[1], arrayDims1[2], false);
arma::cube cubeArray2(vecArray2.begin(), arrayDims2[0], arrayDims2[1], arrayDims2[2], false);
arma::mat STORE=arma::mat(arrayDims1[0], arrayDims1[1]);
for(int i=0;i<arrayDims1[1];i++)
{
for(int j=0;j<arrayDims1[0];j++){
arma::vec v_cl=cubeArray1.subcube(arma::span(j),arma::span(i),arma::span::all);
//arma::mat tem=cubeArray2.subcube(arma::span(j),arma::span::all,arma::span::all);
//arma::vec v_ct=arma::vectorise(tem);
arma::vec v_ct=arma::vectorise(cubeArray2.subcube(arma::span(j),arma::span::all,arma::span::all));
Rcpp::List resu=wilc(v_cl,v_ct);
STORE(j,i)=resu[2];
}
}
return(Rcpp::wrap(STORE));
}
Функция wilc
будет wilcox.test
от R.
Ниже приводится часть моего R кода для реализации вышеупомянутой идеи, где CELLS
и CTRLS
два 3D-массива в R.
for(i in 1:ncol(CELLS)) {
if(T){ print(i) }
for (j in 1:dim(CELLS)[1]) {
wtest = wilcox.test(CELLS[j,i,], CTRLS[j,,])
TSTAT_clcl[j,i] = wtest$p.value
}
}
Вызов R из C++ внутри каждого цикла ... в значительной степени совпадает с записью в R. У вас было неправильное исходное предположение: петли, которые вы переписали, не были узким местом. В следующий раз, возможно, сначала профиль. –
Привет @DirkEddelbuettel, спасибо за ваш комментарий! Я переписал его в R, используя foreach, и использовал doSNOW для реализации кода параллельно. Теперь, учитывая массив 1000 * 100 * 40, для получения результата требуется 18 минут. Однако это все еще не идеально. Это очень сложная задача для тех, кому не хватает знаний в области компьютерных наук, таких как я, чтобы попытаться улучшить производительность кода. Во всяком случае, я считаю это интересным! –