Гарантируется ли mclapply возвращать результаты по порядку?

Я работаю с mclapply от multicore пакет (в Ubuntu), и я пишу функцию, которая требует, чтобы результаты mclapply(x, f) возвращаются в порядке (то есть f(x[1]), f(x[2]), ...., f(x[n])).

# multicore doesn't work on Windows

require(multicore)
unlist(mclapply(
    1:10,
    function(x){
        Sys.sleep(sample(1:5, size = 1))
        identity(x)}, mc.cores = 2))

[1] 1 2 3 4 5 6 7 8 9 10

Приведенный выше код, по-видимому, подразумевает, что mclapply возвращает результаты в том же порядке, что и lapply,

Однако, если это предположение неверно, мне придется потратить много времени на рефакторинг своего кода, поэтому я надеюсь получить от кого-то более знакомого с этим пакетным / параллельным вычислением уверенность в том, что это предположение верно.

Можно ли предположить, что mclapply всегда возвращает результаты по порядку, независимо от того, какие необязательные аргументы ему даны?

1 ответ

Решение

Краткий ответ: он возвращает результаты в правильном порядке.

Но, конечно, вы должны прочитать код самостоятельно (mclapply это функция R...)

Справочная страница для collect дает еще несколько советов:

Примечание. Если expr использует многоуровневые низкоуровневые функции, такие как sendMaster, одно задание может доставлять результаты несколько раз, и пользователь должен правильно их интерпретировать.

Однако, если вы не связываетесь с низким уровнем,

collect возвращает любые результаты, доступные в списке. Результаты будут иметь тот же порядок, что и указанные задания. Если заданий несколько, а задание имеет имя, оно будет использоваться для именования результата, в противном случае будет использоваться идентификатор процесса.

(мой акцент)

Теперь для mclapply, Быстрый взгляд на исходный код дает:

  • если !mc.preschedule и нет больше рабочих мест, чем ядра (length (X) <= cores) parallel а также collect используются, см. выше.
  • если mc.preschedule или больше рабочих мест, чем ядра, mclapply Сам заботится о порядке - см. код.

Однако вот немного измененная версия вашего эксперимента:

> unlist (mclapply(1:10, function(x){
    Sys.sleep(sample(1:5, size = 1)); 
    cat (x, " ");    
    identity(x)}, 
  mc.cores = 2, mc.preschedule = FALSE))
1  2  4  3  6  5  7  8  9  10   [1]  1  2  3  4  5  6  7  8  9 10
> unlist (mclapply(1:10, function(x){
    Sys.sleep(sample(1:5, size = 1)); 
    cat (x, " ");    
    identity(x)}, 
  mc.cores = 2, mc.preschedule = TRUE))
1  3  2  5  4  6  7  8  10  9   [1]  1  2  3  4  5  6  7  8  9 10

Это показывает, что результаты возвращаются в другом порядке дочерними заданиями (точнее: дочерние задания заканчиваются в другом порядке), но результат собирается в исходном порядке.

(работает на консоли, но не в RStudio - catтам не показывайся)

Другие вопросы по тегам