Сохранение нескольких выходов foreach dopar loop

Я хотел бы знать, если / как можно было бы возвращать несколько выходов как часть цикла foreach dopar .

Давайте рассмотрим очень упрощенный пример. Предположим, что я хотел бы сделать 2 операции как часть цикла foreach и хотел бы вернуть или сохранить результаты обеих операций для каждого значения i .

Для возврата только одного результата было бы просто:

 library(foreach) library(doParallel) cl <- makeCluster(3) registerDoParallel(cl) oper1 <- foreach(i=1:100000) %dopar% { i+2 } 

oper1 будет списком с 100000 элементами, каждый элемент будет результатом операции i+2 для каждого значения i.

Предположим теперь, что я хотел бы вернуть или сохранить результаты двух разных операций отдельно, например, i+2 и i+3 . Я попробовал следующее:

 oper1 = list() oper2 <- foreach(i=1:100000) %dopar% { oper1[[i]] = i+2 return(i+3) } 

надеясь, что результаты i+2 будут сохранены в списке oper1 и что результаты второй операции i+3 будут возвращены foreach . Однако ничего не заseleniumо в списке oper1 ! В этом случае из цикла возвращается только результат i+3 .

Есть ли способ возврата или сохранения обоих выходов в двух отдельных списках?

Не пытайтесь использовать побочные эффекты с foreach или любым другим параллельным программным пакетом. Вместо этого верните все значения из тела цикла foreach в списке. Если вы хотите, чтобы ваш конечный результат был списком из двух списков, а не списком из 100 000 списков, укажите функцию объединения, которая переносит результаты:

 comb <- function(x, ...) { lapply(seq_along(x), function(i) c(x[[i]], lapply(list(...), function(y) y[[i]]))) } oper <- foreach(i=1:10, .combine='comb', .multicombine=TRUE, .init=list(list(), list())) %dopar% { list(i+2, i+3) } oper1 <- oper[[1]] oper2 <- oper[[2]] 

Обратите внимание, что для этой функции объединения требуется использовать аргумент .init для установки значения x для первого вызова функции объединения.

Я предпочитаю использовать class для хранения нескольких результатов для цикла% dopar%.

Этот пример объединяет 3 ядра, вычисляет несколько результатов на каждом ядре, а затем возвращает список результатов в вызывающий stream.

Протестировано под RStudio , Windows 10 и R v3.3.2 .

 library(foreach) library(doParallel) # Create class which holds multiple results for each loop iteration. # Each loop iteration populates two properties: $result1 and $result2. # For a great tutorial on S3 classes, see: # http://www.cyclismo.org/tutorial/R/s3Classes.html#creating-an-s3-class multiResultClass <- function(result1=NULL,result2=NULL) { me <- list( result1 = result1, result2 = result2 ) ## Set the name for the class class(me) <- append(class(me),"multiResultClass") return(me) } cl <- makeCluster(3) registerDoParallel(cl) oper <- foreach(i=1:10) %dopar% { result <- multiResultClass() result$result1 <- i+1 result$result2 <- i+2 return(result) } stopCluster(cl) oper1 <- oper[[1]]$result1 oper2 <- oper[[1]]$result2 

Этот пример игрушек показывает, как вернуть несколько результатов из цикла% dopar%.

Этот пример:

  • Вращает 3 ядра.
  • Отображает график на каждом ядре.
  • Возвращает график и прикрепленное сообщение.
  • Распечатывает графики и прилагается сообщение.

Мне посчастливилось ускорить использование Rmarkdown для печати 1800 графиков в PDF-документе.

Протестировано под Windows 10 , RStudio и R v3.3.2 .

R-код:

 # Demo of returning multiple results from a %dopar% loop. library(foreach) library(doParallel) library(ggplot2) cl <- makeCluster(3) registerDoParallel(cl) # Create class which holds multiple results for each loop iteration. # Each loop iteration populates two properties: $resultPlot and $resultMessage. # For a great tutorial on S3 classes, see: # http://www.cyclismo.org/tutorial/R/s3Classes.html#creating-an-s3-class plotAndMessage <- function(resultPlot=NULL,resultMessage="?") { me <- list( resultPlot = resultPlot, resultMessage = resultMessage ) # Set the name for the class class(me) <- append(class(me),"plotAndMessage") return(me) } oper <- foreach(i=1:5, .packages=c("ggplot2")) %dopar% { x <- c(i:(i+2)) y <- c(i:(i+2)) df <- data.frame(x,y) p <- ggplot(df, aes(x,y)) p <- p + geom_point() message <- paste("Hello, world! i=",i,"\n",sep="") result <- plotAndMessage() result$resultPlot <- p result$resultMessage <- message return(result) } # Print resultant plots and messages. Despite running on multiple cores, # 'foreach' guarantees that the plots arrive back in the original order. foreach(i=1:5) %do% { # Print message attached to plot. cat(oper[[i]]$resultMessage) # Print plot. print(oper[[i]]$resultPlot) } stopCluster(cl) 
Interesting Posts

CSS: маржа-верх, когда у родителя нет границы

Почему я могу добавить именованные свойства в массив, как если бы это был объект?

Как получить доступ к параметрам задания из ItemReader, в Spring Batch?

Почему я не должен называть setVisible (true) перед добавлением компонентов?

Как перенести некоторые данные в другой fragment?

Как использовать invokeAll (), чтобы все пулы streamов выполняли свою задачу?

Как обрабатывать событие click в Listview в android?

Как сгенерировать сертификат аннулирования после создания отзыва с помощью GnuPG

OS X: почему Software Update предлагает обновить удаленное приложение?

Селен ждать, пока документ не будет готов

Сохранение входа пользователя / пароля пользователя в сценарии Greasemonkey при установке

Используйте bash для чтения строки за строкой и сохраняйте пространство

Черный экран, воспроизводящий видео на YouTube в Google Chrome

Правильная локализация приложения WinForms

Как добавить события в элементы управления, созданные во время выполнения в Excel с помощью VBA

Давайте будем гением компьютера.