Mclapply возвращает NULL случайным образом

Когда я использую mclapply, время от времени (действительно беспорядочно), он дает неверные результаты. Проблема довольно подробно описана в других сообщениях через Интернет, например. (http://r.789695.n4.nabble.com/Bug-in-mclapply-td4652743.html). Однако решение не предоставляется. Кто-нибудь знает, как решить эту проблему? Спасибо!

Ответ 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.