从R中的foreach开始时,完美的循环无限期地运行

时间:2018-07-17 13:06:54

标签: r foreach parallel-processing

上周,我一直在寻找答案并为此寻求解决方案,但并没有成功。

我想建立一个相互依赖的实体网络。实体有一定的门槛:一种要求他们做出反应以生存下来,另一种要求其死亡。因此,如果实体A死亡,这可能会迫使实体B采取行动,但实体C可能仍然可以接受A的损失。触发的反应又可能触发以前未受影响的实体的反应。
如果该循环消失,则应该查找并记录每个单一实体在网络上的影响。

下面的我的R代码在单独执行时可以很好地工作,但是如果在foreach循环中使用(直到它运行了大约9个小时),它会一直运行到无限远。

由于网络是随机生成的,并且每次迭代都不同,所以我需要使用尽可能多的随机生成的网络。我的想法是,每个并行过程都会生成整个网络,并经历每个实体死亡的影响。

我的代码如下(简化版):

library(foreach)  
library(doParallel)        

iterations <- … # number of iterations of the model
cl <- makeCluster((detectCores() -1), outfile = "")
registerDoParallel(cl)
parallel_loop <- foreach(iteration=(1:iterations), .packages=c("VGAM","network","igraph")) %dopar%{

# generate data set
data <- … # VGAM package is needed for this
adjacency_matrix <- …
data$reaction <- 1 # need this later for a while loop
documentation <- matrix(0, nrow = number_entities, ncol = 6) # for documentation (obviously)
documentation <- as.data.frame(documentation) 
some_network_analysis # network and igraph packages are needed for this
save(data, file=”data”)
save(adjacency_matrix, file =”adjacency_matrix”)

# define functions
check_effect_function <- function{… # determines the effect of the dead entity on the others, sets data$reaction[affected_entity] <- 1 if the effect on an entity is sufficiently strong to require a reaction
quick_reaction_test <- function{… # quick and dirty test if the triggered reactions do not cause other entities to react. == 1 if yes, ==0 if not
reaction_function <- function{… # a reaction function for affected entities
documentation_function <- function{… # filling data frame “documentation”

# the killing loop
for (dead_entity in 1:number_entities) {
    load(data) # so we have clean data and no remnants of earlier runs
    load(adjacency_matrix)
    adjacency_matrix[,dead_entity] <- 0 # the effect of the entity’s death
    while (sum(data$reaction) != 0) { # finding new equilibrium
        data$reaction <- 0
        effect_function() # sets data$reaction[entity] <- 1 if threshold is exceeded
        if (sum(data$reaction) != 0) {
            quick_test_function()
            if (quick_test ==1) 
                {documentation_function() # end of the loop 
            } else reaction_function()
        } else {documentation_function} # end of the loop
            if (reaction_needed == 0) {documentation_function()} # end of the loop
} # end of the killing loop

return(documentation)

} # end of foreach loop

docu_loop <- as.data.frame(do.call(rbind,lapply(parallel_loop,function(x){x}))) # to get me the documentation file

stopCluster(cl)

如果我手动运行代码(即,除了foreach部分以外的所有代码),它会在一分钟内完成。一旦包含了foreach部分,就继续运行。即使我只有1次迭代,它也不会停止。 甚至更陌生,一旦我手动停止计算,R就会保持很高的处理器使用率,并显着降低系统速度。我只能通过完全重新启动R来停止此操作。

仅供参考:
-函数包括for和while循环遍历所有实体。但这甚至可以并行工作,对吧?
-我列出了所使用的软件包,以防它们干扰并行化

我的foreach命令在做什么错?这个确切的foreach代码对于我尝试过的其他任意代码也能正常工作。 非常感谢您的帮助,谢谢您!

++++解决方案++++
如果有人也有这个问题,我已经找到了解决方案:在这一点上

while (sum(data$reaction) != 0) { # finding new equilibrium
    data$reaction <- 0

我不小心吃了

data$reaction <<- 0

对于手动运行代码工作正常,但不能并行化。我本来应该更好地躲避这部分。

1 个答案:

答案 0 :(得分:1)

如果有人也有这个问题,我已经找到了解决方案:在这一点上

while (sum(data$reaction) != 0) { # finding new equilibrium
    data$reaction <- 0

我不小心吃了

data$reaction <<- 0

对于手动运行代码工作正常,但不能并行化。我本来应该更好地躲避这部分。