根据 Dirk 的回复here:
有没有办法在不使用显式循环的情况下修复代码
在 C++ 代码中?
我不这么认为。代码目前有这个硬连线: <...> 所以
直到我们中的一个人有足够的 [时间] 来扩展这个(并测试它)
在你的最后做循环。
这是我对“矢量化”代码的实现:
library(Rcpp)
cppFunction("NumericVector cpprbinom(int n, double size, NumericVector prob) {
NumericVector v(n);
for (int i=0; i<n; i++) {v[i] = as<double>(rbinom(1, size, prob[i]));}
return(v); }")
r <- runif(1e6)
all.equal({set.seed(42); rbinom(length(r), 1, r)},
{set.seed(42); cpprbinom(length(r), 1, r)})
#TRUE
但问题是(再次引用 Dirk),
而且我建议在花费大量精力之前检查一下
你是否有可能比 R 函数 rbinom 做得更好。那
R 函数在 C 代码中被矢量化,你不太可能做事
使用 Rcpp 更快,除非你想使用随机变量
在另一个 C++ 函数中。
而且它实际上更慢(在我的机器上是 x3),所以至少像我这样幼稚的实现不会有帮助:
library(microbenchmark)
microbenchmark(rbinom(length(r), 1, r), cpprbinom(length(r), 1, r))
Unit: milliseconds
expr min lq mean median uq max neval
rbinom(length(r), 1, r) 55.50856 56.09292 56.49456 56.45297 56.65897 59.42524 100
cpprbinom(length(r), 1, r) 117.63761 153.37599 154.94164 154.29623 155.37247 225.56535 100
编辑:根据下面 Romain 的评论,这是一个更快的高级版本!
cppFunction(plugins=c("cpp11"), "NumericVector cpprbinom2(int n, double size, NumericVector prob) {
NumericVector v = no_init(n);
std::transform( prob.begin(), prob.end(), v.begin(), [=](double p){ return R::rbinom(size, p); });
return(v);}")
r <- runif(1e6)
all.equal({set.seed(42); rbinom(length(r), 1, r)},
{set.seed(42); cpprbinom(length(r), 1, r)},
{set.seed(42); cpprbinom2(length(r), 1, r)})
#TRUE
microbenchmark(rbinom(length(r), 1, r), cpprbinom(length(r), 1, r), cpprbinom2(length(r), 1, r))
Unit: milliseconds
expr min lq mean median uq max neval
rbinom(length(r), 1, r) 55.26412 56.00314 56.57814 56.28616 56.59561 60.01861 100
cpprbinom(length(r), 1, r) 113.72513 115.94758 122.81545 117.24708 119.95134 168.47246 100
cpprbinom2(length(r), 1, r) 36.67589 37.12182 38.95318 37.37436 37.97719 84.73516 100