Гарантируется ли 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
там не показывайся)