用 mclapply 控制种子
controlling seeds with mclapply
假设我们正在做一些我想在程序开始时设置一个整体种子的过程:例如
mylist <- list( as.list(rep(NA,3)), as.list(rep(NA,3)) )
foo <- function(x){ for(i in 1:length(x)){
x[[i]] <- sample(100,1)
}
return(x)
}
# start block
set.seed(1)
l1 <- lapply(mylist, foo)
l2 <- lapply(mylist, foo)
# end
当然在一个块内 l1
和 l2
是不同的,但是如果我 运行 上面的块再次 l1
将与以前相同并且 l2
将与以前相同。
假设 foo
非常耗时,所以我想使用 mclapply
而不是 lapply
,所以我这样做:
library(parallel)
# start block
set.seed(1)
mclapply(mylist , foo, mc.cores = 3)
mclapply(mylist , foo, mc.cores = 3)
# end
如果我再次运行这个块,下次我会得到不同的结果。如何产生与使用 lapply
但使用 mclappy
设置一个整体种子相同的行为。我查看了 mclapply
文档,但我不确定,因为使用:
set.seed(1)
l1 <- mclapply(mylist , foo, mc.cores = 3, mc.set.seed=FALSE)
l2 <- mclapply(mylist , foo, mc.cores = 3, mc.set.seed=FALSE)
结果l1
和l2
一样,这不是我想要的...
parallel
软件包特别支持 "L'Ecuyer-CMRG" 随机数生成器,它与 parallel
同时引入。您可以使用以下方式阅读该支持的文档:
library(parallel)
?mc.reset.stream
要使用它,您首先需要启用"L'Ecuyer-CMRG":
RNGkind("L'Ecuyer-CMRG")
完成后,代码如下:
set.seed(1)
mclapply(mylist, foo, mc.cores=3)
mclapply(mylist, foo, mc.cores=3)
将是可重现的,但是对 mclapply
的两次调用将 return 产生相同的结果。这是因为调用 mclapply
.
不会改变主进程中随机数生成器的状态
我使用以下函数跳过 mclapply
工作人员使用的随机数流:
skip.streams <- function(n) {
x <- .Random.seed
for (i in seq_len(n))
x <- nextRNGStream(x)
assign('.Random.seed', x, pos=.GlobalEnv)
}
您可以使用此函数来获得我认为您想要的行为:
set.seed(1)
mclapply(mylist, foo, mc.cores=3)
skip.streams(3)
mclapply(mylist, foo, mc.cores=3)
skip.streams(3)
假设我们正在做一些我想在程序开始时设置一个整体种子的过程:例如
mylist <- list( as.list(rep(NA,3)), as.list(rep(NA,3)) )
foo <- function(x){ for(i in 1:length(x)){
x[[i]] <- sample(100,1)
}
return(x)
}
# start block
set.seed(1)
l1 <- lapply(mylist, foo)
l2 <- lapply(mylist, foo)
# end
当然在一个块内 l1
和 l2
是不同的,但是如果我 运行 上面的块再次 l1
将与以前相同并且 l2
将与以前相同。
假设 foo
非常耗时,所以我想使用 mclapply
而不是 lapply
,所以我这样做:
library(parallel)
# start block
set.seed(1)
mclapply(mylist , foo, mc.cores = 3)
mclapply(mylist , foo, mc.cores = 3)
# end
如果我再次运行这个块,下次我会得到不同的结果。如何产生与使用 lapply
但使用 mclappy
设置一个整体种子相同的行为。我查看了 mclapply
文档,但我不确定,因为使用:
set.seed(1)
l1 <- mclapply(mylist , foo, mc.cores = 3, mc.set.seed=FALSE)
l2 <- mclapply(mylist , foo, mc.cores = 3, mc.set.seed=FALSE)
结果l1
和l2
一样,这不是我想要的...
parallel
软件包特别支持 "L'Ecuyer-CMRG" 随机数生成器,它与 parallel
同时引入。您可以使用以下方式阅读该支持的文档:
library(parallel)
?mc.reset.stream
要使用它,您首先需要启用"L'Ecuyer-CMRG":
RNGkind("L'Ecuyer-CMRG")
完成后,代码如下:
set.seed(1)
mclapply(mylist, foo, mc.cores=3)
mclapply(mylist, foo, mc.cores=3)
将是可重现的,但是对 mclapply
的两次调用将 return 产生相同的结果。这是因为调用 mclapply
.
我使用以下函数跳过 mclapply
工作人员使用的随机数流:
skip.streams <- function(n) {
x <- .Random.seed
for (i in seq_len(n))
x <- nextRNGStream(x)
assign('.Random.seed', x, pos=.GlobalEnv)
}
您可以使用此函数来获得我认为您想要的行为:
set.seed(1)
mclapply(mylist, foo, mc.cores=3)
skip.streams(3)
mclapply(mylist, foo, mc.cores=3)
skip.streams(3)