首页 > 解决方案 > 如何使用 R 中的 foreach 循环修改共享对象?

问题描述

我正在尝试通过将 for-loop 并行转换为 for-each 循环来加速它。但是,当它需要修改一些共享对象时,会带来一些问题。一个玩具示例如下。

library(doParallel)
registerDoParallel(cores = 4)
a <- c()
b <- c()
foreach(i = 1:100, .combine = cbind) %dopar% {
  a <- c(a, i)
  b <- c(b, i^2)
  NULL  # to take up a place for the return statement
}
a
b

理想情况下,我希望向量ac(1, 2, 3, ..., 100),并且bc(1, 4, 9, ..., 10000),元素的顺序无关紧要。但是,上述代码片段的结果是 vectora和 vectorb都是空的。

任何人都知道发生了什么以及如何解决它?

谢谢!

-- 编辑 --
为了给你更多的上下文,我试图在 R 中并行化 BFS 算法。代码的骨架如下所示:

q <- queue()
s <- set()
l <- list(...)
while(length(q) > 0){
  element <- pop(q)
  for(edge connect to element){
    if(!s contains edge && some other conditions){
      s <- set_union(s, <something new>)
      pushback(q, <something new>)
      l[[1]] <- <something new>
    }
  }
}

我正在尝试将内部 for 循环转换为一个 foreach 循环,该循环可以将这些边缘的计算扩展到不同的核心。但是,数据结构集、队列和列表是共享的。如果没有简单的方法来获取它们的锁,那么它们是否有任何对应的并发数据结构,比如 Java 中的 HashMap 的 ConcurrentHashMap?

标签: rparallel-foreach

解决方案


我不确定这是否是 OP 所追求的,但它按预期返回一个带有两个向量的 data.frame:

library(doParallel)
registerDoParallel(cores = 4)
result <- foreach(i = 1:10, .combine = rbind) %dopar% {
  a <- i
  b <- i^2
  data.frame(a, b)
}
result
    a   b
1   1   1
2   2   4
3   3   9
4   4  16
5   5  25
6   6  36
7   7  49
8   8  64
9   9  81
10 10 100

请注意,我已将迭代次数减少到 10 次以进行演示。


推荐阅读