2013-06-20 2 views
5

У меня есть код R, который включает несколько рабочих foreach для выполнения некоторых задач параллельно. Для этого я использую foreach и doMC. Я хочу, чтобы каждый из рабочих foreach набирал новых рабочих и раздавал им некоторые части своего кода, который является параллелизуемым.Позвольте работникам foreach регистрировать и распространять подзадачи другим работникам

текущий код выглядит следующим образом:

require(doMC) 
require(foreach) 
registerDoMC(cores = 8) 

foreach (i = (1:8)) %dopar% { 
<<some code here>> 
    for (j in c(1:4)) { 
    <<some other code here>> 
    } 
} 

Ищу идеальный код, который будет выглядеть так:

require(doMC) 
require(foreach) 
registerDoMC(cores = 8) 

foreach (i = (1:8)) %dopar% { 
<<some code here>> 
    foreach (j = (1:4)) %dopar% { 
    <<some other code here>> 
    } 
} 

Я видел пример мульти-парадигмы параллелизм с использованием doSNOW и DoMC here (https://www.rmetrics.org/files/Meielisalp2009/Presentations/Lewis.pdf#page=17) , Однако я не знаю, делает он то, что я хочу, или нет.

Кроме того, кажется Nested foreach не применимо, поскольку для этого требуется слияние двух петель (see here), в то время как в моем случае это не является предпочтительным; второй цикл помогает только первой части кода. Пожалуйста, поправьте меня, если я ошибаюсь.

Спасибо.

+0

Возможно, не совсем то, что вы хотите, но вы можете иметь вложенные выражения foreach: http://cran.r-project.org/web/packages/foreach/vignettes/nested.pdf. Однако я не знаю о наборе большего числа рабочих в петлях. – ialm

+0

Спасибо. Тем не менее, кажется, что вложенный foreach не применим к моему случаю, потому что он требует слияния двух вложенных циклов, тогда как мне нужен внутренний цикл, который вызывается только для части кода. Я уточню вопрос, чтобы отразить это. – imriss

ответ

6

Нет особой проблемы с наличием петли foreach внутри цикла foreach. Вот пример цикла DoMC внутри цикла doSNOW:

library(doSNOW) 
hosts <- c('host-1', 'host-2') 
cl <- makeSOCKcluster(hosts) 
registerDoSNOW(cl) 
r <- foreach(i=1:4, .packages='doMC') %dopar% { 
    registerDoMC(2) 
    foreach(j=1:8, .combine='c') %dopar% { 
    i * j 
    } 
} 
stopCluster(cl) 

кажется мне естественным использовать DoMC для внутреннего цикла, но вы можете сделать это в любом случае вы хотите. Вы также можете использовать doSNOW для обеих петель, но тогда вам нужно будет создать и остановить снежный кластер внутри внешнего цикла foreach.

Ниже приведен пример использования DoMC внутри цикла DoMC:

library(doMC) 
registerDoMC(2) 
r <- foreach(i=1:2, .packages='doMC') %dopar% { 
    ppid <- Sys.getpid() 
    registerDoMC(2) 
    foreach(j=1:2) %dopar% { 
    c(ppid, Sys.getpid()) 
    } 
} 

Результаты показывают, что в общей сложности шесть процессов раздвоенной пакетом DoMC, хотя только четыре выполнить тело внутреннего цикла:

> r 
[[1]] 
[[1]][[1]] 
[1] 14946 14949 

[[1]][[2]] 
[1] 14946 14951 


[[2]] 
[[2]][[1]] 
[1] 14947 14948 

[[2]][[2]] 
[1] 14947 14950 

Конечно, вам нужно быть осторожным, чтобы не запускать слишком много процессов на одном узле. Я нашел такое гнездование немного неудобным, что привело к развитию оператора гнездования.

+0

Спасибо. Я использую MOAB для отправки заданий, поэтому я не могу выбирать имена хостов. Существует ли какая-либо передовая практика для определения количества узлов и процессоров в запросе MOAB, чтобы избежать слияния процессоров? Например, в первом примере выше я должен попросить узлы = 4; ppn = 8? – imriss

+0

@imriss Вы хотите использовать MPI или кластер SOCK? Если MPI, вы используете Open MPI или что-то еще? И вы используете Torque в качестве менеджера ресурсов с Moab? –

+0

Строки сценария msub начинаются с #PBS, поэтому я думаю, что это Torque/Moab. В текущем коде я использую doMC и foreach для внешнего цикла, а внутренний цикл - серийный. У меня нет прав администратора, но я могу установить пакеты в свою домашнюю папку. Благодарю. – imriss