Как отключить время, когда элемент списка выходит из строя или занимает слишком много времени?

В течение нескольких усилий, в которые я вовлечен, я запускаю большие наборы данных с многочисленными комбинациями параметров через ряд функций. У функций есть обертка (поэтому я могу mclapply) для удобства работы в кластере. Однако я столкнулся с двумя серьезными проблемами.

a) Мое сочетание параметров велико (думаю, 20k до 100k). Иногда отдельные комбинации будут терпеть неудачу (например, выживание слишком велико, а смертность слишком низкая, поэтому модель никогда не сходится как гипотетический сценарий). Мне тяжело судить заранее, какие комбинации не удастся (жизнь будет проще, если я смогу это сделать). Но сейчас у меня такой тип настройки:

failsafe <- failwith(NULL, my_wrapper_function)
# This is what I run
# Note that input_variables contains a list of variables in each list item
results <-  mclapply(input_variables, failsafe, mc.cores = 72)
# On my local dual core mac, I can't do this so the equivalent would be:
results <-  llply(input_variables, failsafe,  .progress = 'text')

Скелет для моей функции-оболочки выглядит следующим образом:

my_wrapper_function <- function(tlist) {
    run <- tryCatch(my_model(tlist$a, tlist$b, tlist$sA, tlist$Fec, m = NULL) , error=function(e) NULL)
...
return(run)
}

Это самый эффективный подход? Если по какой-то причине конкретная комбинация переменных вылетает из модели, мне нужно ее вернуть NULL и продолжить с остальными. Тем не менее, у меня все еще есть проблемы, из-за которых это происходит менее чем изящно.

b) Иногда некоторая комбинация входов не приводит к краху модели, но слишком долго подходит для схождения. Я установил лимит времени вычисления на моем кластере (скажем, 6 часов), поэтому я не трачу свои ресурсы на то, что застряло. Как включить тайм-аут таким образом, чтобы, если вызов функции занимает более одного раза в одном элементе списка, он должен двигаться дальше? Вычисление затраченного времени тривиально, но функция средней симуляции не может быть прервана, чтобы проверить время, правильно?

Любые идеи, решения или трюки оценены!

Ответ 1

Возможно, вы сможете управлять грациозным выводом на время с использованием комбинации tryCatch() и evalWithTimeout() из пакета R.utils. См. также этот пост, который представляет собой аналогичный код и немного распаковывает его.

require(R.utils)

myFun <- function(x) {Sys.sleep(x); x^2}

## evalWithTimeout() times out evaluation after 3.1 seconds, and then
## tryCatch() handles the resulting error (of class "TimeoutException") with 
## grace and aplomb.
myWrapperFunction <- function(i) {
    tryCatch(expr = evalWithTimeout(myFun(i), timeout = 3.1), 
             TimeoutException = function(ex) "TimedOut")
}

sapply(1:5, myWrapperFunction)
# [1] "1"        "4"        "9"        "TimedOut" "TimedOut"