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

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

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

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 и продолжила работу с остальными. Тем не менее, у меня все еще есть проблемы, что это терпит неудачу менее чем изящно.

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

Любые идеи, решения или трюки приветствуются!


person Maiasaura    schedule 08.06.2012    source источник
comment
вы смотрели в setTimeLimit() или inside-r.org/node/81211? Может быть то, что вам нужно.   -  person frankc    schedule 08.06.2012


Ответы (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"
person Josh O'Brien    schedule 08.06.2012
comment
Большое спасибо, Джош. Сейчас я тестирую это на своем кластере (локально работает нормально, но не уверен, что тайм-аут хорошо работает на кластере). - person Maiasaura; 11.06.2012