什么时候使用 RNGScope 会有所作为?

When does using RNGScope make a difference?

在 Rcpp 文档中,我经常发现在 Rcpp 中使用随机抽取之前放置 Rcpp::RNGScope scope; 的建议。我想知道这到底是做什么的,因为我只见过它被描述为“确保 RNG 状态得到 set/reset”。

然后,我进行了一些测试,但我似乎无法想出这样做有什么不同的例子。我使用了 here 中的示例。我的测试是:

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector noscope() {
  Rcpp::Function rt("rt");
   return rt(5, 3);
}

// [[Rcpp::export]]
NumericVector withscope() {
   RNGScope scope;
   Rcpp::Function rt("rt");
   return rt(5, 3);
}

然后

set.seed(45)
noscope() # [1]  0.6438 -0.6082 -1.9710 -0.1402 -0.6482

set.seed(45)
withscope() # [1]  0.6438 -0.6082 -1.9710 -0.1402 -0.6482

set.seed(45)
rt(5, 3) # [1]  0.6438 -0.6082 -1.9710 -0.1402 -0.6482

所以,我的问题是双重的。首先,RNGScope 何时会有所作为,它与不使用它究竟有何不同?其次,有没有人有代码示例,显示有和没有它的不同结果?

如果 RNGScope 在较新的版本中被弃用,那么我很抱歉提出这个问题。

当使用 Rcpp 属性时,自动生成的代码接口将自动插入 RNGScope 对象的适当结构——所以在这种情况下,它已经在幕后为您完成了。例如,如果你写 sourceCpp(..., verbose = TRUE),你会看到这样的输出:

Generated extern "C" functions 
--------------------------------------------------------


#include <Rcpp.h>

RcppExport SEXP sourceCpp_38808_timesTwo(SEXP xSEXP) {
BEGIN_RCPP
    Rcpp::RObject __result;
    Rcpp::RNGScope __rngScope;
    Rcpp::traits::input_parameter< NumericVector >::type x(xSEXP);
    __result = Rcpp::wrap(timesTwo(x));
    return __result;
END_RCPP
}

注意 RNGScope 对象的自动构造。

如果您在 Rcpp 属性范围之外操作,则只需要手动构造该对象。

一旦您阅读 Writing R Extensions manual, Section 6.3, "Random Numbers" 中的 原始 文档,这一切就会变得更加清晰。

RNGScope scope 所做的只是 automagic 调用 "get" 和 "put" 以保持 RNG 的状态.

正如 Kevin 所解释的那样,您的测试代码存在的问题是 您已经遇到了。所以你只能通过手动 .Call() 来测试,在这种情况下你 肯定会 如果你使用它 并且做不 get/put 正确。