Rcpp可以替换R中的unif函数吗?

can*_*his 7 c++ r rcpp

我刚开始使用RcppR中的包,我的学习灵感来自Hadley Wickham的高级R课程.

在R studio中我有以下.cpp文件.问题更为笼统,但这个例子有所帮助.

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector runifC(int n, double min=0, double max=1) {
  NumericVector out(n);

  for(int i = 0; i < n; ++i) {
    out[i] = min + ((double) rand() / (RAND_MAX)) * (max - min);
  }
  return out;
}

/*** R
library(microbenchmark)
microbenchmark(
  'R unif-1'      = runif(1),
  'C++ unif-1'    = runifC(1),
  'R unif-100'    = runif(100),
  'C++ unif-100'  = runifC(100),
  'R unif-1000'   = runif(1000),
  'C++ unif-1000' = runifC(1000),
  'R unif-100000'   = runif(100000),
  'C++ unif-100000' = runifC(100000)
)
*/
Run Code Online (Sandbox Code Playgroud)

当我发送/保存文件时,它会向我显示性能输出.

Unit: nanoseconds
             expr     min        lq       mean    median        uq     max neval
         R unif-1    2061    2644.5    4000.71    3456.0    4297.0   15402   100
       C++ unif-1     710    1190.0    1815.11    1685.0    2168.5    5776   100
       R unif-100    4717    5566.5    6794.14    6563.0    7435.5   16600   100
     C++ unif-100    1450    1997.5    2663.29    2591.5    3107.0    5307   100
      R unif-1000   28210   29584.5   31310.54   30380.0   31599.0   52879   100
    C++ unif-1000    8292    8951.0   10113.78    9462.5   10121.5   25099   100
    R unif-100000 2642581 2975117.0 3104580.62 3030938.5 3119489.0 5435046   100
  C++ unif-100000  699833  990924.0 1058855.49 1034430.5 1075078.0 1530351   100
Run Code Online (Sandbox Code Playgroud)

我希望这runif将是一个非常优化的函数,但C++代码运行得更高效.我可能在这里天真,但如果性能有这么大差异,为什么不能用C++重写所有适用的R函数?

看起来很明显,有很多可能的改进,我觉得好像我错过了一个很大的原因,为什么不能将所有R函数盲目地复制到C++中以获得性能.

编辑:对于这个例子,已经证明C++实现rand()有点缺陷.我注意到最常用的rand()功能差距.其他功能的表现似乎并不那么激烈,所以我改变了问题的名称.

Dir*_*tel 11

请不要使用rand().如果您提交,那么这样做也会使您的包裹脱离CRAN.

有关警告,请参阅此C++参考页面:

笔记

无法保证产生的随机序列的质量.在过去,rand()的一些实现在所产生的序列的随机性,分布和周期中具有严重的缺点(在一个众所周知的示例中,低阶位简单地在调用之间在1和0之间交替).

如果您对备用随机数生成器和时序感兴趣,可以使用Rcpp Gallery.

通常,使用由R提供的具有优异统计质量的发生器,并且由Rcpp以标量和矢量化形式("Rcpp Sugar")提供.


Jos*_*ich 5

从R-3.1.1开始,runif使用.External复制其参数的接口.Luke Tierney将此更改为使用.CallR-devel中的界面修订版66110.该.Call接口不会复制它的参数.Rcpp使用该.Call接口.


在R-devel(使用.Call界面)下,您的C++代码仍然更快.这很可能是因为使用的随机数发生器存在差异.此外,R的功能通常会比您编写的任何专用代码具有更多的检查; 那些检查需要时间.