У меня есть функция, которая вычисляет основную сводную статистику из строк (или столбцов) данной матрицы, и сейчас я пытаюсь также использовать эту функцию с bigstatsr :: FBM (я знаю, что использование столбцов должно быть более эффективным ).
Причина, по которой я хочу хранить строки / столбцы в векторе, заключается в том, что я хотел бы вычислять квантили с помощью std :: nth_element. Если есть другой способ сделать это без вектора, я был бы одинаково счастлив.
Это код, который я использую для обычной матрицы.
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::depends(RcppEigen)]]
#include <RcppEigen.h>
using namespace Rcpp;
// [[Rcpp::export]]
Eigen::MatrixXd summaryC(Eigen::MatrixXd x,int nrow) {
Eigen::MatrixXd result(nrow, 5);
int indices[6] = {-1, 0, 249, 500, 750, 999};
for (int i = 0; i < nrow; i++) {
Eigen::VectorXd v = x.row(i);
for (int q = 0; q < 5; ++q) {
std::nth_element(v.data() + indices[q] + 1,
v.data() + indices[q+1],
v.data() + v.size());
result(i,q) = v[indices[q+1]];
}
}
return result;
}
/*** R
x <- matrix(as.numeric(1:1000000), ncol = 1000)
summaryC(x = x, nrow = 1000)
***/
Однако я изо всех сил пытаюсь сделать это с FBM, поскольку я не до конца осознаю тонкости того, как работает FBM - Pointer.
Я безуспешно пробовал следующее:
// [[Rcpp::depends(BH, bigstatsr, RcppEigen)]]
// [[Rcpp::plugins(cpp11)]]
#include <bigstatsr/BMAcc.h>
#include <RcppEigen.h>
// [[Rcpp::export]]
Eigen::MatrixXd summaryCbig(Environment fbm,int nrow, Eigen::VecttorXi ind_col) {
Eigen::MatrixXd result(nrow, 5);
XPtr<FBM> xpMat = fbm["address"];
BMAcc<double> macc(xpMat);
int indices[6] = {-1, 0, 249, 500, 750, 999};
for (int i = 0; i < nrow; i++) {
Eigen::VectorXd v = macc.row(i); // this does not work
Eigen::VectorXd v = macc(i,_); // this does not work
SubBMAcc<double> maccr(XPtr, i, ind_col -1); // This did not work with Eigen::VectorXi, but works with const NumericVector&
Eigen::VectorXd v = maccr // this does not work even for appropriate ind_col
for (int q = 0; q < 5; ++q) {
std::nth_element(v.data() + indices[q] + 1,
v.data() + indices[q+1],
v.data() + v.size());
macc(i,q) = v[indices[q+1]];
}
}
}
/*** R
x <- matrix(as.numeric(1:1000000), ncol = 1000)
summaryCbig(x = x, nrow = 1000, ind_col = 1:1000)
***/
Любая помощь будет принята с благодарностью, спасибо!
Обновление - big_apply - подход
Я реализовал подход дважды с двумя матрицами разного размера X1 и X2. Код для X1:
X1 <- FBM(1000, 1000, init 1e6)
X2 <- FBM(10000, 10000, init = 9999)
library(bigstatsr)
microbenchmark::microbenchmark(
big_apply(X, a.FUN = function(X, ind) {
matrixStats::rowQuantiles(X1[ind, ])
}, a.combine = "rbind", ind = rows_along(X), ncores = nb_cores(), block.size = 500),
big_apply(X, a.FUN = function(X, ind) {
matrixStats::rowQuantiles(X1[ind, ])
}, a.combine = "rbind", ind = rows_along(X), ncores = 1, block.size = 500),
times = 5
)
При использовании X1 и block.size = 500, наличие 4 ядер вместо 1 делает задачу в 5-10 раз медленнее на моем ПК (4 процессора и использование Windows, к сожалению).
использование большей матрицы X2 и оставление block.size со значением по умолчанию занимает 10 раз дольше с 4 ядрами вместо непараллельной версии.
Результат для X2:
min lq mean median uq max neval
16.149055 19.13568 19.369975 20.139363 20.474103 20.951676 5
1.297259 2.67385 2.584647 2.858035 2.867537 3.226552 5