Когда я использую mclapply, время от времени (действительно беспорядочно), он дает неверные результаты. Проблема довольно подробно описана в других сообщениях через Интернет, например. (http://r.789695.n4.nabble.com/Bug-in-mclapply-td4652743.html). Однако решение не предоставляется. Кто-нибудь знает, как решить эту проблему? Спасибо!
Mclapply возвращает NULL случайным образом
Ответ 1
Проблема, о которой говорил Уинстон Чанг, которую вы цитируете, была исправлена в R 2.15.3. В mccollect
произошла ошибка, которая произошла при назначении результатов работникам списку результатов:
if (is.raw(r)) res[[which(pid == pids)]] <- unserialize(r)
Это не удается, если unserialize(r)
возвращает NULL, так как присвоение NULL списку таким образом удаляет соответствующий элемент списка. Это было изменено в R 2.15.3:
if (is.raw(r)) # unserialize(r) might be null
res[which(pid == pids)] <- list(unserialize(r))
который является безопасным способом присвоить список неизвестному значению.
Итак, если вы используете R <= 2.15.2, решение должно обновиться до R >= 2.15.3. Если у вас возникла проблема с использованием R >= 2.15.3, то, вероятно, это другая проблема, чем тот, о котором сообщил Уинстон Чанг.
Я также прочитал вопросы, обсуждаемые в потоке R-справки, начатом Элизабет Пурдом. Без конкретного теста я предполагаю, что проблема связана не с ошибкой в mclapply, потому что я могу воспроизвести те же симптомы со следующей функцией:
work <- function(i, poison) {
if (i == poison) quit(save='no')
i
}
Если рабочий, запущенный mclapply, умирает во время выполнения задачи по какой-либо причине (получение сигнала, seg faulting, exiting), mclapply возвращает NULL для всех задач, которые были назначены этому работнику:
> library(parallel)
> mclapply(1:4, work, 3, mc.cores=2)
[[1]]
NULL
[[2]]
[1] 2
[[3]]
NULL
[[4]]
[1] 4
В этом случае NULL были возвращены для задач 1 и 3 из-за предварительной настройки, хотя фактически выполнялась только задача 3.
Если рабочий умирает при использовании функции, такой как parLapply или clusterApply, сообщается об ошибке:
> cl <- makePSOCKcluster(3)
> parLapply(cl, 1:4, work, 3)
Error in unserialize(node$con) : error reading from connection
Я видел много таких отчетов, и я думаю, что они, как правило, происходят в больших программах, которые используют множество пакетов, которые трудно превратить в воспроизводимые тестовые примеры.
Конечно, в этом примере вы также получите ошибку при использовании lapply, хотя ошибка не будет скрыта, как и при использовании mclapply. Если проблема не возникает при использовании lapply, это может быть из-за того, что проблема редко возникает, поэтому это происходит только при очень больших запусках, которые выполняются параллельно с использованием mclapply. Но также возможно, что ошибка возникает не потому, что задачи выполняются параллельно, а потому, что они выполняются разветвленными процессами. Например, при выполнении в разветвленном процессе различные графические операции будут терпеть неудачу.
Ответ 2
Я добавляю этот ответ, чтобы другие, затрагивающие этот вопрос, не должны были пробираться сквозь длинный поток комментариев (я - грантодатель щедрости, но не OP).
mclapply
изначально заполняет список, который он создает с помощью NULLS. Когда рабочие обрабатывают возвращаемые значения, эти значения перезаписывают NULLS. Если процесс умирает без возврата значения, mclapply
вернет NULL.
Когда память становится низкой, Linux-убийца из памяти (oom killer)
https://lwn.net/Articles/317814/
начнет бесшумно убивать процессы. Он ничего не выводит на консоль, чтобы вы знали, что он делает, хотя в системном журнале отображаются активности убийцы oom. В этой ситуации вывод mclapply
, по-видимому, был случайно заражен NULLS.