我正在使用此Rcpp代码在值的向量上进行quickselect运算,即在O(n)的时间内从向量中获取第k个最大元素(我将其保存为qselect.cpp
):
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
using namespace arma;
// [[Rcpp::export]]
double qSelect(arma::vec& x, const int k) {
// ARGUMENTS
// x: vector to find k-th largest element in
// k: desired k-th largest element
// safety copy since nth_element modifies in place
arma::vec y(x.memptr(), x.n_elem);
// partially sort y in O(n) time
std::nth_element(y.begin(), y.begin() + k - 1, y.end());
// the k-th largest value
const double kthValue = y(k-1);
return kthValue;
}
我使用它作为计算所需百分位数的快速方法。
例如。
n = 50000
set.seed(1)
x = rnorm(n=n, mean=100, sd=20)
tau = 0.01 # desired percentile
k = tau*n+1 # here we will get the 6th largest element
library(Rcpp)
Rcpp::sourceCpp('qselect.cpp')
library(microbenchmark)
microbenchmark(qSelect(x,k)) # 53.32917, 548 µs
microbenchmark(sort(x, partial=k)[k]) # 53.32917, 694 µs = pure R solution
[这看起来好像已经快了,但是我需要在我的应用程序中完成数百万次]
现在,我想修改此Rcpp函数,以便对R矩阵的所有列或所有行执行多线程快速选择,并将结果作为向量返回。由于我是Rcpp的新手,因此我希望获得一些建议,尽管有关哪种框架可能对此最快,并且最容易编写代码(它必须易于跨平台工作,并且我需要对nr进行良好的控制使用的线程数)。使用OpenMP,RcppParallel或RcppThread?甚至更好-如果有人可以展示一种快速而优雅的方法来做到这一点?
最佳答案
是的,这可能是多线程变体的候选者-但是正如RcppParallel文档会告诉您的那样,并行代码的一个要求是非R内存,这里我们以有效的零拷贝方式使用RcppArmadillo,这意味着它是R内存。
因此,您可能需要权衡并行执行的额外数据副本(例如,RcppParallel使用的RMatrix
类型)。
但是由于算法简单且按列进行,因此您还可以在上面的函数中尝试单个OpenMP循环:将其传递给矩阵,使用#pragma for
将其循环到列上。