Параллельный mapply() для Windows; как mcmapply()

#r #performance #parallel-processing #apply

#r #Производительность #параллельная обработка #применить

Вопрос:

Мне интересно, существует ли версия mapply() , которая работает параллельно для Windows. parallel Пакет имеет отличные возможности для распараллеливания apply функций, но, похоже, в нем отсутствует опция Windows для mapply() . parallel Пакет имеет mcapply функции для пользователей, не являющихся пользователями Windows (ie mcapply() , mclapply() mcmapply() и т.д.), И parApply функции для пользователей Windows (ie parApply() , parLapply() и т.д.). Однако parLapply() их нет.

Есть ли эквивалент mcmapply() для Windows?

Вот два списка:

 list1 <- list(elem1 = 1:3, elem2 = 4:6, elem3 = 7:9)
list2 <- list(elem1 = 10:12, elem2 = 13:15, elem3 = 15:17)
  

Я хочу добавить их вместе;

 (result <- mapply(FUN = function(x, y){
  x   y
}, list1, list2, SIMPLIFY = FALSE))
  

Как я могу воссоздать это параллельно для пользователей Windows?

Примечание: parApply функции не являются заменяющими элементами, как mcapply функции. Смотрите ссылку для получения хорошей документации о том, как их использовать. https://dept.stat.lsa.umich.edu/~jerrick/courses/stat701/notes/parallel.html

Ответ №1:

(отказот ответственности: Я автор)

Пакет future.apply предоставляет взаимно однозначные параллельные версии всех функций R apply. Поскольку он работает поверх платформы future, он работает практически со всеми известными параллельными серверными системами в R.

 library(future.apply)
plan(multicore)  ## forked processing

list1 <- list(elem1 = 1:3, elem2 = 4:6, elem3 = 7:9)
list2 <- list(elem1 = 10:12, elem2 = 13:15, elem3 = 15:17)

(result <- future_mapply(FUN = function(x, y){
  x   y
}, list1, list2, SIMPLIFY = FALSE))
  

В приведенном выше примере используется разветвленная обработка, точно так же, как parallel::mcmapply() . Для использования PSOCK cluster workers, который также поддерживается в MS Windows, необходимо, чтобы конечный пользователь установил:

 plan(multisession)
  

С вышесказанным вам не нужно выполнять условное кодирование, например:

 if (parallel == "forks") {
  ...
} else if (parallel == "this") {
  ...
} else if (parallel == "that") {
  ...
} else {
  ...
}
  

Все, что вам нужно, это один future_mapply() вызов.

Комментарии:

1. @ HenrikB, это решение работает на моем простом примере. Однако у меня возникла проблема с моим реальным сценарием. Я получаю эту ошибку: Ошибка в get(как.character (FUN), mode = «функция», envir = envir): объект ‘myExpl1’ режима ‘функция’ не найден. Это как если бы глобальная среда не использовалась совместно со всеми сеансами. Я пропустил шаг?

2. Вот мой код; myBiomodData <- future_mapply(fun = функция(a, b, d){ write.csv(as.matrix(print(system.time(w <- mapply(FUN = функция (e, f, g){ mapply(FUN = функция (h, i, j){ mapply(FUN = функция(k, l, m){ BIOMOD_FormatingData(соответственно var = l , expl.var = k, resp.name = m, соответственно.xy = myRespXY) }, h, i, j, SIMPLIFY = FALSE) }, e, f, g, SIMPLIFY = FALSE) }, a, b, d, SIMPLIFY = FALSE)))), «myBiomodData_time.csv») }, myExpl1, myResp1, myRespName1, SIMPLIFY = FALSE)

3.1. Можно явно указать дополнительные глобальные переменные, которые фреймворк future не сможет автоматически обнаружить (см. Справку об этом). 2. Если бы вы могли создать минимальный воспроизводимый пример, который я могу воспроизвести, тогда я мог бы изучить проблему и, возможно, даже исправить восходящий поток. ТАК что комментарии для этого не подходят, поэтому не стесняйтесь публиковать в будущем.применить отслеживание проблем.

4. Дело в том, что если каждый вызов Opt() занимает всего лишь короткое время, то распараллеливать его не стоит. Много кода не стоит распараллеливать. Только вы знаете, сколько времени Opt() занимает. Сравните future_mapply() с mapply() , чтобы понять, стоит ли первое.

5. Да, 2 минуты достаточно. Он определенно должен выполняться быстрее параллельно. Если это медленнее, возможно, вы сталкиваетесь с другими узкими местами, например, с нехваткой памяти, что приводит к большой замене файлов. Кстати, обратите внимание, что data.table уже выполняется параллельно, поэтому, если 2 минуты потрачены на data.table , это не поможет запустить другой уровень распараллеливания поверх него. О проблеме с data.table см. github.com/HenrikBengtsson/future/discussions /… .