Непонятно, как правильно таймаутировать рабочих joblib Parallel
в python. У других были похожие вопросы здесь, здесь, здесь и здесь.
В моем примере я использую пул из 50 joblib
рабочих с бэкэндом threading
.
Параллельный вызов (threading):
output = Parallel(n_jobs=50, backend = 'threading')
(delayed(get_output)(INPUT)
for INPUT in list)
Здесь Parallel
зависает без ошибок, как только len(list) <= n_jobs
, но только когда n_jobs => -1
.
Чтобы обойти эту проблему, люди дают инструкции о том, как создать декоратор тайм-аута функции Parallel
(get_output(INPUT)
) в приведенном выше примере), используя multiprocessing
:
Основная функция (оформлена):
@with_timeout(10) # multiprocessing
def get_output(INPUT): # threading
output = do_stuff(INPUT)
return output
Многообъемный декоратор:
def with_timeout(timeout):
def decorator(decorated):
@functools.wraps(decorated)
def inner(*args, **kwargs):
pool = multiprocessing.pool.ThreadPool(1)
async_result = pool.apply_async(decorated, args, kwargs)
try:
return async_result.get(timeout)
except multiprocessing.TimeoutError:
return
return inner
return decorator
Добавление декоратора к другому рабочему коду приводит к утечке памяти после ~ 2x длины таймаута плюс крушение затмения.
Где эта утечка в декораторе?
Как отключить потоки во время многопроцессорной обработки в python?