【问题标题】:R nested foreach %dopar% in outer loop and %do% in inner loopR 在外循环中嵌套 foreach %dopar% 在内循环中嵌套 %do%
【发布时间】:2018-07-15 21:53:11
【问题描述】:

我正在 R 中运行以下脚本。 如果我使用 %do% 而不是 %dopar% 脚本可以正常工作。但是,如果在外部循环中我使用 %dopar% 循环将永远运行而不会引发任何错误(内存使用量不断增加,直到内存不足)。 我正在使用 16 核。

library(parallel)
library(foreach)
library(doSNOW)
library(dplyr)


NumberOfCluster <- 16 
cl <- makeCluster(NumberOfCluster) 
registerDoSNOW(cl) 


foreach(i = UNSPSC_list, .packages = c('data.table', 'dplyr'), .verbose = TRUE) %dopar% 
    { 
      terms <- as.data.table(unique(gsub(" ", "", unlist(terms_list_by_UNSPSC$Terms[which(substr(terms_list_by_UNSPSC$UNSPSC,1,6) == i)])))) 
      temp <- inner_join(N_of_UNSPSCs_by_Term, terms, on = 'V1') 
      temp$V2 <- 1/as.numeric(temp$V2)
      temp <- temp[order(temp$V2, decreasing = TRUE),]
      names(temp) <- c('Term','Imp')
      ABNs <- unique(UNSPSCs_per_ABN[which(substr(UNSPSCs_per_ABN$UNSPSC,1,4) == substr(i,1,4)), 1])

      predictions <- as.numeric(vector()) 
      predictions <- foreach (j = seq(1 : nrow(train)), .combine = 'c', .packages = 'dplyr')  %do% 
      { 
        descr <- names(which(!is.na(train[j,]) == TRUE)) 
        if(unlist(predict_all[j,1]) %in% unlist(ABNs) || !unlist(predict_all[j,1]) %in% unlist(suppliers)) {union_all(predictions, sum(temp$Imp[which(temp$Term %in% descr)]))} else {union_all(predictions, 0)}    

      } 
    save(predictions, file = paste("Predictions", i,".rda", sep = "_")) 
    }

【问题讨论】:

  • 你试过NumberOfCluster &lt;- 2吗?
  • 刚刚试了,并没有解决问题。
  • 所以如果没有内部 %do% 循环,代码在 %dopar% 下运行良好?
  • 没有,只有当两者都是 %do% 时,代码才能正常运行。如果两者之一是 %dopar% 则它们不起作用。
  • 你读过这个吗,你可以用 %:%: cran.r-project.org/web/packages/foreach/vignettes/nested.pdf 嵌套循环?

标签: r foreach parallel-processing


【解决方案1】:

嵌套foreach 循环的正确方法是使用%:% 运算符。请参阅示例。我已经在 Windows 上测试过了。

library(foreach)
library(doSNOW)

NumberOfCluster <- 4
cl <- makeCluster(NumberOfCluster) 
registerDoSNOW(cl) 

N <- 1e6

system.time(foreach(i = 1:10, .combine = rbind) %:%
              foreach(j = 1:10, .combine = c) %do% mean(rnorm(N, i, j)))

system.time(foreach(i = 1:10, .combine = rbind) %:%
              foreach(j = 1:10, .combine = c) %dopar% mean(rnorm(N, i, j)))

输出:

> system.time(foreach(i = 1:10, .combine = rbind) %:%
+               foreach(j = 1:10, .combine = c) %do% mean(rnorm(N, i, j)))
   user  system elapsed 
   7.38    0.23    7.64 
> system.time(foreach(i = 1:10, .combine = rbind) %:%
+               foreach(j = 1:10, .combine = c) %dopar% mean(rnorm(N, i, j)))
   user  system elapsed 
   0.09    0.00    2.14 

使用嵌套循环的方案如下:

foreach(i) %:% foreach(j) {foo(i, j)}

运算符%:% 用于嵌套多个foreach 循环。您不能在嵌套之间进行计算。在您的情况下,您必须执行两个循环,例如:

# Loop over i
x <- foreach(i = 1:10, .combine = c) %dopar% 2 ^ i

# Nested loop over i and j
foreach(i = 1:10, .combine = rbind) %:% foreach(j = 1:10, .combine = c) %dopar% {x[i] + j}

未经测试的代码:

library(data.table)
library(foreach)
library(doSNOW)

NumberOfCluster <- 2
cl <- makeCluster(NumberOfCluster)
registerDoSNOW(cl)

# Create ABNs as list
ABNs <- foreach(i = UNSPSC_list, .packages = c('data.table', 'dplyr'), .verbose = TRUE) %dopar% {
  terms <- as.data.table(unique(gsub(" ", "", unlist(terms_list_by_UNSPSC$Terms[which(substr(terms_list_by_UNSPSC$UNSPSC, 1, 6) == i)]))))
  temp <- inner_join(N_of_UNSPSCs_by_Term, terms, on = 'V1')
  temp$V2 <- 1 / as.numeric(temp$V2)
  temp <- temp[order(temp$V2, decreasing = TRUE), ]
  names(temp) <- c('Term', 'Imp')
  unique(UNSPSCs_per_ABN[which(substr(UNSPSCs_per_ABN$UNSPSC,1,4) == substr(i,1,4)), 1])
}

# Nested loop
predictions <- foreach(i = UNSPSC_list, .packages = c('data.table', 'dplyr'), .verbose = TRUE) %:%
  foreach(j = seq(1:nrow(train)), .combine = 'c', .packages = 'dplyr') %dopar% {
    descr <- names(which(!is.na(train[j, ]) == TRUE))
    if (unlist(predict_all[j, 1]) %in% unlist(ABNs[[i]]) || !unlist(predict_all[j, 1]) %in% unlist(suppliers)) {
      sum(temp$Imp[which(temp$Term %in% descr)])
    } else 0
  }

for (i in seq_along(predictions)) save(predictions[[i]], file = paste("Predictions", i, ".rda", sep = "_"))

【讨论】:

  • 感谢 djhurio,我想到了使用 %:% 事实是我的代码结构为 foreach - 代码 - 嵌套 foreach。你的只是 foreach - 嵌套的 foreach。如果您向我展示如何使我的代码适应您的解决方案,那么 50 分就是您的了。
猜你喜欢
  • 1970-01-01
  • 2012-03-29
  • 2019-07-13
  • 2016-05-28
  • 2015-07-15
  • 1970-01-01
  • 2013-05-11
  • 2015-07-06
  • 1970-01-01
相关资源
最近更新 更多