获得双向量的非负分量的更快方法是什么?也就是说,
{
"my_bean_name": "Sth"
//...
}
我的尝试是使用Rcpp:
pmax(x, 0)
这是一个适度的改进:
//' @title Parallel maximum
//' @description A faster \code{pmax()}.
//'
//' @name pmaxC
//' @param x A numeric vector.
//' @param a A single numeric value.
//' @return The parallel maximum of the input values.
//' @note This function will always be faster than \code{pmax(x, a)} when \code{a} is a single value, but can be slower than \code{pmax.int(x, a)} when \code{x} is short. Use this function when comparing a numeric vector with a single value.
//' @export pmaxC
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector pmaxC(NumericVector x, double a) {
int n = x.length();
NumericVector out(n);
for (int i = 0; i < n; ++i) {
double xi = x[i];
if (xi < a) {
out[i] = a;
} else {
out[i] = xi;
}
}
return out;
}
两者都没有令人无法接受的缓慢,但鉴于这是一种常见的情况,我想知道一个软件包是否已经开发出更快的方法。
答案 0 :(得分:2)
您正在执行的操作非常简单,因此我不确定您的算法在上面有很大的改进空间。但是,如果真的需要挤出额外的性能,这似乎是并行化的一个很好的候选者。以下是使用RcppParallel
:
// [[Rcpp::depends(RcppParallel)]]
#include <RcppParallel.h>
#include <Rcpp.h>
struct Pmax : public RcppParallel::Worker {
struct Apply {
double mx;
Apply(double mx_)
: mx(mx_)
{}
double operator()(const double x) const
{
return x > mx ? x : mx;
}
};
const RcppParallel::RVector<double> input;
RcppParallel::RVector<double> output;
Apply f;
Pmax(const Rcpp::NumericVector input_,
Rcpp::NumericVector output_,
double mx_)
: input(input_), output(output_), f(mx_)
{}
void operator()(std::size_t begin, std::size_t end)
{
std::transform(
input.begin() + begin,
input.begin() + end,
output.begin() + begin,
f
);
}
};
// [[Rcpp::export]]
Rcpp::NumericVector par_pmax(Rcpp::NumericVector x, double y)
{
Rcpp::NumericVector res = Rcpp::no_init_vector(x.size());
Pmax p(x, res, y);
RcppParallel::parallelFor(0, x.size(), p);
return res;
}
使用您的示例数据对此进行测试,我得到了合理的改进:
set.seed(5)
x <- rnorm(1e6)
all.equal(pmax(x, 0), par_pmax(x, 0))
#[1] TRUE
microbenchmark::microbenchmark(
pmax(x, 0),
pmaxC(x, 0),
par_pmax(x, 0),
times = 500L
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# pmax(x, 0) 11.843528 12.193126 14.972588 13.030448 16.799250 102.09895 500
# pmaxC(x, 0) 7.804883 8.036879 10.462070 8.772635 12.407587 69.08290 500
# par_pmax(x, 0) 2.244691 2.443971 4.552169 2.624008 6.359027 65.99233 500