[英]Foreach throws error with %dopar% but executes successfully with %do%
我正在尝试使用foreach
和%dopar%
将以下代码转换为并行代码。
library(doSNOW)
library(foreach)
cl<- makeCluster(4, type = "SOCK")
registerDoSNOW(cl)
min_subid <- c()
max_subid <- c()
p_typ <- c()
p_nm <- c()
st_tm<-c()
end_tm <- c()
supp <- c()
chart_type <- c()
foreach(j =1:noOfPhases) %dopar%
{
start_time <-phases[j, colnames(phases)=="StartTime"]
end_time <-phases[j, colnames(phases)=="StopTime"]
phase_type <-phases[j, colnames(phases)=="Phase_Type_Id"]
phase_name <-phases[j, colnames(phases)=="Phase_Name"]
suppress <-phases[j, colnames(phases)=="Suppression_Time"]
chart_typ <-phases[j, colnames(phases)=="chartType"]
conft<-(masterData$Time.Subgroup>=start_time & masterData$Time.Subgroup<=end_time)
masterData[which(conft), colnames(masterData)=="Phase_Type"]<-phase_type
masterData[which(conft), colnames(masterData)=="Phase_Name"]<-phase_name
min_subid <- rbind(min_subid, min(which(conft)))
max_subid <- rbind(max_subid, max(which(conft)))
p_typ <- rbind( p_typ, masterData$Phase_Type[min(which(conft))])
p_nm <- rbind( p_nm, masterData$Phase_Name[min(which(conft))])
st_tm <- rbind( st_tm, as.character(start_time))
end_tm <- rbind( end_tm, as.character(end_time))
supp <- rbind(supp,as.character(suppress))
chart_type <- rbind(chart_type,as.character(chart_typ))
phase_info <- data.frame(Subgrp_No_Start=min_subid, Subgrp_No_End=max_subid, Phase_Type=p_typ,
Phase_Name=p_nm, Start_Time=st_tm, Stop_Time=end_tm,
Suppression_Time=supp,ChartType=chart_type)
}
phase_output<-merge(phase_info, phases, by.x=c("Start_Time",
"Stop_Time","ChartType"), by.y=c("StartTime", "StopTime","chartType"))
当包含%do%
而不是%dopar%
时,以上代码成功执行。 谁能帮助我理解为什么我在并行运行( %dopar%
)并在顺序运行( %do%
)时成功出现以下错误
Error in merge(phase_info, phases, by.x = c("Start_Time", "Stop_Time", :
object 'phase_info' not found
解决方案确实很简单,但是我首先解释执行代码解释错误时发生的情况。
在您的foreach
块中, phase_info
j
每个值创建一个数据帧( phase_info
),并将它们一起返回到列表中。 但是,由于您的赋值phase_info <- data.frame(...)
位于foreach
内部而不是外部,因此该列表不会存储在任何地方,并且会被丢弃。 造成混淆的原因是,使用%do%
您将在主节点上顺序创建所有数据帧,而使用%dopar%
,则在工作节点上并行创建帧。 如果您使用%dopar%
,则在主节点上执行以下merge
命令会导致错误,因为phase_info
在其工作空间中不存在。 还要注意,当像上面那样使用%do%
时, foreach
每次迭代都会覆盖前一个的结果( 即,您仅获得最后一次迭代的结果)。
这个较小的更改可解决此问题:
phase_info <- foreach(...) %dopar% {
...
data.frame(Subgrp_No_Start=min_subid, Subgrp_No_End=max_subid, Phase_Type=p_typ,
Phase_Name=p_nm, Start_Time=st_tm, Stop_Time=end_tm,
Suppression_Time=supp,ChartType=chart_type)
# No need to give it a name as it will be returned and the name forgotten
}
phase_output <- merge(phase_info, ...)
如上所述, phase_info
现在将是一个列表,其中每个元素都是一个数据帧。 我现在只是猜测,但是您可能想要然后按元素方式执行merge
,如下所示:
phase_output <- lapply(phase_info, merge, phases, by.x=c("Start_Time",
"Stop_Time","ChartType"), by.y=c("StartTime", "StopTime","chartType"))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.