我试图为某些模拟研究制作一些可重复的示例,因此我使用set.seed
从"随机"获得一致的结果。部分。但是,我注意到我有时会得到不同的结果。
我试图将其缩小到一个可重复性最小的示例,但似乎需要多个元素来触发错误。
这是应该发生的事情:
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
完成前的按钮。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
答案 0 :(得分:3)
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
,但我不确定这会完全解决问题。