是什么导致了这种奇怪的随机数生成器行为?
What's causing this strange random number generator behaviour?
我正在尝试为某些模拟研究制作一些可重现的示例,因此我使用 set.seed
从 "random" 部分获得一致的结果。但是,我注意到我有时会得到不同的结果。
我试图将其缩小到一个最小的可重现示例,但似乎需要多个元素才能触发错误。
这是应该发生的事情:
library(RcppExamples)
set.seed(1)
RcppRNGs(3)
# rnorm rt rpois
# 1 -0.6264538 1.5144787 1
# 2 0.1836433 -0.3536704 0
# 3 -0.8356286 11.4386179 1
rnorm(3)
# [1] 1.12493092 -0.04493361 -0.01619026
这段代码似乎是激活错误的原因:
library(plyr)
S <- llply(1:100, function(.) Sys.sleep(1), .progress="text")
# |========================== | 25%
注意:
- 我在
llply
完成之前点击了 "stop" 按钮。
- 我知道您通常会在这种情况下使用
rlply
,但这不会触发错误。
现在是这样:
set.seed(1)
RcppRNGs(3)
# rnorm rt rpois
# 1 -0.6264538 1.5144787 1
# 2 0.1836433 -0.3536704 0
# 3 -0.8356286 11.4386179 1
rnorm(3)
# [1] -0.6264538 0.1836433 -0.8356286
我应该得到与第一个示例相同的结果,但是 rnorm
给出了不同的数字。
问题似乎是 Rcpp 不再影响随机数种子:
set.seed(1)
rnorm(3)
# [1] -0.6264538 0.1836433 -0.8356286
考虑到这里所有的交互部分,我应该向谁提交错误报告?
这是我的 sessionInfo()
输出:
R version 3.1.2 (2014-10-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)
locale:
[1] LC_COLLATE=English_New Zealand.1252 LC_CTYPE=English_New Zealand.1252 LC_MONETARY=English_New Zealand.1252 LC_NUMERIC=C
[5] LC_TIME=English_New Zealand.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] plyr_1.8.1 RcppExamples_0.1.6 Rcpp_0.11.3
loaded via a namespace (and not attached):
[1] tools_3.1.2
llply
下降到 loop_apply
最终调用此函数:
// [[Rcpp::export]]
List loop_apply(int n, Function f) {
List out(n);
for(int i = 0; i < n; ++i) {
out[i] = f(i + 1);
}
return out;
}
因此,作为 Rcpp::export
业务的一部分,我们接到了 enterRNGScope
的电话
// [[Rcpp::register]]
unsigned long enterRNGScope() {
if (RNGScopeCounter == 0) GetRNGstate();
RNGScopeCounter++;
return RNGScopeCounter ;
}
并且在 loop_apply
结束时我们应该接到 exitRNGScope
的电话。
// [[Rcpp::register]]
unsigned long exitRNGScope() {
RNGScopeCounter--;
if (RNGScopeCounter == 0) PutRNGstate();
return RNGScopeCounter ;
}
问题是,由于中断,我们永远不会到达 exitRNGScope
,因此当 RcppRNGs
调用 enterRNGScope
时,我们认为不需要调用 GetRNGstate
所以种子处理不当。
也许 loop_apply
应该调用 checkUserInterrupt
,但我不确定这能否完全解决问题。
我正在尝试为某些模拟研究制作一些可重现的示例,因此我使用 set.seed
从 "random" 部分获得一致的结果。但是,我注意到我有时会得到不同的结果。
我试图将其缩小到一个最小的可重现示例,但似乎需要多个元素才能触发错误。
这是应该发生的事情:
library(RcppExamples)
set.seed(1)
RcppRNGs(3)
# rnorm rt rpois
# 1 -0.6264538 1.5144787 1
# 2 0.1836433 -0.3536704 0
# 3 -0.8356286 11.4386179 1
rnorm(3)
# [1] 1.12493092 -0.04493361 -0.01619026
这段代码似乎是激活错误的原因:
library(plyr)
S <- llply(1:100, function(.) Sys.sleep(1), .progress="text")
# |========================== | 25%
注意:
- 我在
llply
完成之前点击了 "stop" 按钮。 - 我知道您通常会在这种情况下使用
rlply
,但这不会触发错误。
现在是这样:
set.seed(1)
RcppRNGs(3)
# rnorm rt rpois
# 1 -0.6264538 1.5144787 1
# 2 0.1836433 -0.3536704 0
# 3 -0.8356286 11.4386179 1
rnorm(3)
# [1] -0.6264538 0.1836433 -0.8356286
我应该得到与第一个示例相同的结果,但是 rnorm
给出了不同的数字。
问题似乎是 Rcpp 不再影响随机数种子:
set.seed(1)
rnorm(3)
# [1] -0.6264538 0.1836433 -0.8356286
考虑到这里所有的交互部分,我应该向谁提交错误报告?
这是我的 sessionInfo()
输出:
R version 3.1.2 (2014-10-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)
locale:
[1] LC_COLLATE=English_New Zealand.1252 LC_CTYPE=English_New Zealand.1252 LC_MONETARY=English_New Zealand.1252 LC_NUMERIC=C
[5] LC_TIME=English_New Zealand.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] plyr_1.8.1 RcppExamples_0.1.6 Rcpp_0.11.3
loaded via a namespace (and not attached):
[1] tools_3.1.2
llply
下降到 loop_apply
最终调用此函数:
// [[Rcpp::export]]
List loop_apply(int n, Function f) {
List out(n);
for(int i = 0; i < n; ++i) {
out[i] = f(i + 1);
}
return out;
}
因此,作为 Rcpp::export
业务的一部分,我们接到了 enterRNGScope
// [[Rcpp::register]]
unsigned long enterRNGScope() {
if (RNGScopeCounter == 0) GetRNGstate();
RNGScopeCounter++;
return RNGScopeCounter ;
}
并且在 loop_apply
结束时我们应该接到 exitRNGScope
的电话。
// [[Rcpp::register]]
unsigned long exitRNGScope() {
RNGScopeCounter--;
if (RNGScopeCounter == 0) PutRNGstate();
return RNGScopeCounter ;
}
问题是,由于中断,我们永远不会到达 exitRNGScope
,因此当 RcppRNGs
调用 enterRNGScope
时,我们认为不需要调用 GetRNGstate
所以种子处理不当。
也许 loop_apply
应该调用 checkUserInterrupt
,但我不确定这能否完全解决问题。