理解 foreach 循环的含义

4

我刚接触使用foreach并行执行for循环,对它的工作原理感到困惑。举个练习的例子,我根据一个数据框(input)创建了一个简单的列表(input2),尝试通过遍历h和j来计算b。

library(doParallel)
library(foreach)
library(dplyr)

input <- data.frame(matrix(rnorm(200*200, 0, .5), ncol=200))
input[input <=0] =0
input['X201'] <- seq(from = 0, to = 20, length.out = 10)
input <- input %>% select(c(X201, 1:200))
input2 <- split(input, f= input$X201)

a = 0
b= 0
cl <- parallel::makeCluster(20)
doParallel::registerDoParallel(cl)
tm1 <- system.time(
  y <- 
    foreach (h = length(input2),.combine = 'cbind') %:%
    foreach (j = nrow(input2[[h]]),.combine = 'c',packages = 'foreach') %dopar%{
      a = input2[[h]][j,3]
      b = b + a
    } 

)
parallel::stopCluster(cl)
registerDoSEQ()
print("Cluster stopped.")

y的值约为0.55(确切值取决于所生成的随机数),这是input2[[10]][20,3]的值,而不是我所期望的累积值。我查看了foreach包的手册,但仍不确定是否完全理解foreach函数的机制。


1
请在使用的所有非基础包中包含。我推断出 dplyrparallelforeach,但请在示例代码中明确说明。 - r2evans
1
好的,我已经添加了这三个库。 - Roger
foreach 基本上像 lapply 一样工作。它使用表达式而不是函数,语法也不同,但原理完全相同,即没有副作用,如在循环外更新变量。所需(由赏金)的官方来源是包文档。 - Roland
1个回答

3

R foreach返回结果,允许更改外部变量。因此,请不要指望a、b被正确更新。

请尝试以下操作:

cl <- parallel::makeCluster(20)
doParallel::registerDoParallel(cl)

tm2 <- system.time(
results <- foreach(h = (1:length(input2)), .combine = "c") %dopar%{
    sum( input2[[h]][1:nrow(input2[[h]]),3])
},
b <- sum(results[1:length(results)])
)
parallel::stopCluster(cl)
registerDoSEQ()
b
tm2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接