当在R中使用foreach启动时,完美精细循环将无限期运行

当在R中使用foreach启动时,完美精细循环将无限期运行,r,foreach,parallel-processing,R,Foreach,Parallel Processing,上周,我一直在寻找答案,并致力于解决这个问题,但根本没有成功 我想建立一个相互依赖的实体网络。实体有特定的阈值:一个要求它们做出反应以生存,另一个要求它们做出特定的死亡。因此,如果实体A死亡,这可能迫使实体B采取行动,但实体C可能仍然可以接受A的损失。触发的反应可能反过来触发以前未受影响的实体的反应。 如果网络中的每一个实体都将消亡,那么这个循环应该会发现并记录它们对网络的影响 我下面的R代码在单独执行时工作得非常好,但如果在foreach循环中使用,它会一直运行到无穷远。我让它运行了9个小时

上周,我一直在寻找答案,并致力于解决这个问题,但根本没有成功

我想建立一个相互依赖的实体网络。实体有特定的阈值:一个要求它们做出反应以生存,另一个要求它们做出特定的死亡。因此,如果实体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部分,就一直在运行。即使我只有一次迭代,它也不会停止。 更奇怪的是,一旦我手动停止计算,R将保持非常高的处理器使用率,并显著降低系统速度。我只能通过完全重新启动R来停止此操作

供参考: -函数包括for和while循环,循环遍历所有实体。但这应该是并行的,对吗? -我列出了使用过的包,以防它们干扰并行化

我在foreach命令中做错了什么?这个精确的foreach代码对于我尝试的其他任意代码来说效果很好。 非常感谢您的帮助,提前谢谢

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

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

data$reaction <<- 0
data$reaction <<- 0

这对于手动运行代码很好,但在并行化中不起作用。我本应该更好地避开这一部分。

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

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

data$reaction <<- 0
data$reaction <<- 0

这对于手动运行代码很好,但在并行化中不起作用。我本应该更好地避开这一部分。

请提供一个最小的可复制示例。我为自己创建了一个最小的示例,用于测试原因,它在两种情况下都能完美地工作。我试图让它无限期运行,即重现问题,但尚未成功。工作示例会有帮助吗?不幸的是,我不这么认为。另一个很好的例子说明了为什么应该避免@HenrikB,我必须在函数中使用它,使它们能够修改数据。实际代码中的一个是打字错误。我从未使用过你也不想使用我有一个嵌套函数,它可以改变10k x 10k矩阵中的许多单个值。我在考虑返回,但手动替换矩阵中的值是不可行的。