Параллельные вычисления: загрузка пакетов в каждом потоке только один раз

В настоящее время я работаю с некоторыми большими наборами данных, поэтому распараллеливание рабочих процессов — единственный выход.

Мне нужно загрузить некоторые пакеты в каждый поток один раз в начале (например: for(this.thread in threads) { #load some packages }.

К сожалению, я не уверен, как это сделать.

Следующий код дополнительно иллюстрирует мою проблему, когда я пытаюсь использовать оператор канала из magrittr в %dopar% :

.

library(parallel)
library(doParallel)
library(foreach)
library(magrittr)


# Generate some random data and function :
# -----------------------------------------

randomData = runif(10^3)
randomFunction = function(x) {x * (2^x) } 

randomData[1] %>% randomFunction #Works



# And now ... The parallel part :
# --------------------------------

myCluster = makeCluster(6)
registerDoParallel(myCluster)


# Test that the do par is up and running: 
foreach(i = randomData) %dopar% { i }


# Use magrittr pipe operator: 
# Error in { : task 1 failed - "could not find function "%>%""
foreach(i = randomData) %dopar% { i %>% randomFunction }


# Load the library at each loop: (ie: length(data) times !)
# Other than unnecessarily loading the library (length(data) - numberOfThreads) times, 
# it works nicely
foreach(i = randomData) %dopar% { library(magrittr);  i %>% randomFunction }


# Now try without re-loading: 
# Tararaa - (ie: Works nicely)
foreach(i = randomData) %dopar% { i %>% randomFunction }

.

Любые идеи?


person Community    schedule 01.12.2015    source источник
comment
@VeerendraGadekar, я сгенерировал некоторые случайные данные в приведенном выше сценарии. Моя проблема не в запуске параллельных циклов. Я пытаюсь избежать загрузки пакетов n раз, где n = длина моих больших данных. Надеюсь, это проясняет это немного больше.   -  person    schedule 01.12.2015
comment
Два вызова library() обходятся примерно так же дорого, как и один (R проверяет, загружена ли уже библиотека, и если да, то ничего не делает), так что не нужно напрягаться. Пойдите с вашим, это прекрасно работает решение.   -  person Martin Morgan    schedule 01.12.2015
comment
Спасибо за ваш комментарий @VeerendraGadekar. На самом деле, моя проблема не конкретно в магриттре или операторе пайпа, а в концепции в целом. Например, я использую некоторые функции интерполяции из некоторых пакетов. Я использую magrittr здесь только для иллюстрации.   -  person    schedule 01.12.2015
comment
@MartinMorgan, вы абсолютно правы. Результаты тестирования вашей идеи: начальная загрузка: 31,5 миллисекунды, последующие загрузки: 133 микросекунды. Спасибо еще раз.   -  person    schedule 01.12.2015


Ответы (2)


Пакет doParallel наследует некоторые удобные низкоуровневые функции от parallel, включая clusterCall, который выполняет функцию один раз на каждом узле.

У меня была точно такая же проблема, и я решил ее, выполнив:

library(doParallel)
myCluster = makeCluster(6)
registerDoParallel(myCluster)
clusterCall(myCluster, function() library(magrittr))

Вы также можете использовать аргумент .packages:

foreach(i = 1:5, .packages = "magrittr") %dopar% {i %>% runif}
person mlegge    schedule 01.12.2015
comment
Идеальный! Не знал об этом! Спасибо @mkemp6! - person ; 02.12.2015

Вы можете попробовать это:

foreach(i = randomData,.packages=c("magrittr")) %dopar% {
  i %>% randomFunction
}
person user56134    schedule 06.09.2016