dopar foreach(运行并行for循环)

dopar foreach(运行并行for循环),r,foreach,doparallel,R,Foreach,Doparallel,这个问题特别与在多个核上运行for循环有关。我正在尝试学习如何使用并行内核运行代码。实际的代码有点复杂,所以我在这里重新创建了一个非常基本和稀释的代码。请注意,此示例仅用于说明目的,而不是实际代码 library(parallel) library(foreach) library(doParallel) #Creating a mock dataframe Event_ID = c(1,1,1,1,1,2,2,2,2,2,3,3,3,3) Type=c("A","B","C","D","E"

这个问题特别与在多个核上运行for循环有关。我正在尝试学习如何使用并行内核运行代码。实际的代码有点复杂,所以我在这里重新创建了一个非常基本和稀释的代码。请注意,此示例仅用于说明目的,而不是实际代码

library(parallel)
library(foreach)
library(doParallel)

#Creating a mock dataframe
Event_ID = c(1,1,1,1,1,2,2,2,2,2,3,3,3,3)
Type=c("A","B","C","D","E","A","B","C","D","E","A","B","C","D")
Revenue1=c(24,9,51,7,22,15,86,66,0,57,44,93,34,37)
Revenue2=c(16,93,96,44,67,73,12,65,81,22,39,94,41,30)
z = data.frame(Event_ID,Type,Revenue1,Revenue2)
#replicates z 5000 times
n =5000
zz=do.call("rbind", replicate(n, z, simplify = FALSE))
zz$Revenue3 = 0

#################################################################
#   **foreach, dopar failed attempt**
#################################################################
cl=parallel::makeCluster(14,type="PSOCK") #I have 8 core 16 threads but use 14 here. Please edit this accordingly.
registerDoParallel(cl)
home1 = function(zz1){
  foreach(i=1:nrow(zz1), .combine = rbind) %dopar% {
    zz1[i,'Revenue3'] = sqrt(zz1[i,'Revenue1'])+(zz1[i,'Revenue2'])
  }
  return(zz1)
}

zzz = home1(zz1=zz)
stopCluster(cl) 

#################################################################
#Non parallel implementation
#################################################################
home2 = function(zz2){
  zz3=zz2
  for (i in 1:nrow(zz3)){
    zz3[i,'Revenue3'] = sqrt(zz3[i,'Revenue1'])+(zz3[i,'Revenue2'])
  }
  return(zz3)
}
zzzz=home2(zz2=zz)
我创建了一个数据帧并尝试使用foreach和dopar,但它似乎不起作用。接下来,我将提供代码的非并行版本的实现。然而,并行版本不适合我。我得到的输出df与输入矩阵相同。我意识到我可能犯了一个基本的错误,但我没有足够的经验来找出到底是什么错了。任何帮助都将不胜感激


另外,我确实意识到我的非并行版本不是最优的,可以改进,但这只是一个例子。

首先要注意的是,使用
parallel
doParallel
foreach
包并行运行在覆盖现有data.frames中的值时有一定的局限性。当通过这个包执行并行化时,正在启动一个并行运行的R会话,一个worker,它执行计算,返回以某种方便的形式执行的任何结果。这意味着这些工作会话不包含原始会话中的任何对象,除非提供(带有.export或作为函数参数)。
future
promises
ipc
包可以允许异步处理,同时修改原始会话中的变量,但代价是一些简单性

请注意,由于每个会话将使用一个单独的核心,因此使用比核心更多的会话会降低总体性能

至于实现本身,如何实现并行化取决于计算所需的内容以及要返回的格式。如果要执行简单的按行计算,可以使用以下方法:

library(iterators)
cl=parallel::makeCluster(4) #I have 8 core 16 threads but use 14 here. Please edit this accordingly.
registerDoParallel(cl)
stopCluster(cl)
home1 <- function(zz1){
  output <- foreach(x = iter(zz1, by = "row"), .combine = rbind) %dopar% {
    x[["Revenue3"]] <- sqrt(x[["Revenue1"]]) + x[["Revenue2"]]
    x
  }
  output
}
zzz <- home1(zz1=zz)
stopCluster(cl)
库(迭代器)
cl=parallel::makeCluster(4)#我有8个核心16线程,但这里使用14个。请对此进行相应的编辑。
注册数字并行(cl)
停止簇(cl)

home1首先请注意,使用
parallel
doParallel
foreach
包并行运行在覆盖现有data.frames中的值时有一定的局限性。当通过这个包执行并行化时,正在启动一个并行运行的R会话,一个worker,它执行计算,返回以某种方便的形式执行的任何结果。这意味着这些工作会话不包含原始会话中的任何对象,除非提供(带有.export或作为函数参数)。
future
promises
ipc
包可以允许异步处理,同时修改原始会话中的变量,但代价是一些简单性

请注意,由于每个会话将使用一个单独的核心,因此使用比核心更多的会话会降低总体性能

至于实现本身,如何实现并行化取决于计算所需的内容以及要返回的格式。如果要执行简单的按行计算,可以使用以下方法:

library(iterators)
cl=parallel::makeCluster(4) #I have 8 core 16 threads but use 14 here. Please edit this accordingly.
registerDoParallel(cl)
stopCluster(cl)
home1 <- function(zz1){
  output <- foreach(x = iter(zz1, by = "row"), .combine = rbind) %dopar% {
    x[["Revenue3"]] <- sqrt(x[["Revenue1"]]) + x[["Revenue2"]]
    x
  }
  output
}
zzz <- home1(zz1=zz)
stopCluster(cl)
库(迭代器)
cl=parallel::makeCluster(4)#我有8个核心16线程,但这里使用14个。请对此进行相应的编辑。
注册数字并行(cl)
停止簇(cl)

家庭1你可能想读书。你可能想读书。太棒了。成功了。一个快速跟进问题。假设我想做多次(例如1000次),那么在运行一次循环之后,我需要做什么呢?每次运行循环时是否需要创建集群和stopCluster@OliverIf如果您不关闭它,它将在每次跑步后保持活动状态。不要运行stopCluster,它会继续重复使用同一个集群。太棒了。成功了。一个快速跟进问题。假设我想做多次(例如1000次),那么在运行一次循环之后,我需要做什么呢?每次运行循环时是否需要创建集群和stopCluster@OliverIf如果您不关闭它,它将在每次跑步后保持活动状态。只要不运行stopCluster,它就会继续重复使用同一个集群。