Подтвердить что ты не робот

Гарантировано ли 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 всегда возвращает свои результаты по порядку, независимо от необязательных аргументов, которые он задает?

4b9b3361

Ответ 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 там не отображается)