使用串行和并行后端的foreach给出不同的结果

时间:2017-04-06 09:23:35

标签: r foreach doparallel

我有一个奇怪的例子,使用带有串行和并行后端的foreach会在我第一次调用时给出不同的结果,但稍后会在两个结果匹配时使用。我使用RNG使结果可以重现seed

下面是一个解释场景的示例函数:

func <- function(ncores = NULL, seed = 1234){
  if (!is.null(ncores)){ # this block registers for parallel backend
    cl <- makeCluster(ncores)
    registerDoParallel(cl)
    registerDoRNG(seed, once = TRUE)
    on.exit(stopCluster(cl)) 
  } else {              # this block registers for serial computation
    registerDoSEQ() 
    registerDoRNG(seed, once = TRUE)
  }
  w = foreach(i = 1:10, .combine = 'c') %dorng% {
    mean(sample(1:100, 50, replace = TRUE))
  }
  attr(w, "rng") <- NULL
  return(w)
}

# first time running below 2 lines
# case 1 : serial
w1 <- func(ncores = NULL)
# Case 2 : parallel
w2 <- func(ncores= 5)
identical(w1, w2)

# second time running below 2 lines
# case 1: serial
w3 <- func(ncores = NULL)
# case 2: parallel 
w4 <- func(ncores= 5)

identical(w1, w2)
# [1] FALSE
identical(w3, w4)
# [1] TRUE

我在注册顺序流程时遗漏了什么?

1 个答案:

答案 0 :(得分:1)

解决方案是使用以下表达式:

w = foreach(i = 1:10, .combine = 'c', .options.RNG=seed) %dorng% {
    mean(sample(1:100, 50, replace = TRUE))}

您可以在小插图here找到解释。

所以你的功能看起来像这样:

func <- function(ncores = NULL, seed = 1234){
  if (!is.null(ncores)){ # this block registers for parallel backend
    cl <- makeCluster(ncores)
    registerDoParallel(cl)
    on.exit(stopCluster(cl)) 
  } else {              # this block registers for serial computation
    registerDoSEQ() 
  }
  w = foreach(i = 1:10, .combine = 'c', .options.RNG=seed) %dorng% {
    mean(sample(1:100, 50, replace = TRUE))
  }
  attr(w, "rng") <- NULL
  return(w)
}