Пока l oop не сломается в python многопроцессорности - PullRequest
0 голосов
/ 14 января 2020

Поскольку я не получил обратной связи, для этого вопроса я переосмысливаю (и упрощаю) проблему здесь. В этом упрощенном случае мне интересно, как я могу перезапустить какое-то время l oop, которое не сломается в многопроцессорной очереди.

Я хочу запустить функцию на нескольких ядрах, используя библиотеку multiprocessing.

p = multiprocessing.Pool(5)                     # Start a pool with 5 cores
analysis = p.map(function_to_call,'abcdefghij') # Call function_to_call on every core 
                                                # each time with a different letter from
                                                # string 'abcdefghij' and collect results
print(analysis)

def function_to_call(arg):
    result = []
    time = timeit.default_timer()               # timeit library needed
    time_even = int(str(time)[-1])              # get last number of time
########## below can't be changed ###########
    while True:
        if (time_even % 2) == 0:                # if last number is even, do stuff
            result.append('problem')
        else:                                   # else append arg to result
            result.append(str(arg))
            break 
########## above can't be changed ###########
    print(result) 
    return(result)                              # and return result

Результат всегда будет отличаться в зависимости от того, когда скрипт компилируется. В моем случае вывод в терминале:

['b']
['c']
['g']
['h']
['i']
['e']  # <--- note that the process run in parallel and not serial

Вывод таков: вызов функции застревает в то время как l oop при вызове с аргументами 'a', 'd', 'f' и 'j' (потому что последний номер временной метки, очевидно, даже в этих случаях). Однако, если я добавлю and False к оператору if в то время как l oop, чтобы он всегда ломался, на терминал выводится следующее, указывая, что все работает идеально (print (result) скомпилировано):

['a']
['b']
['d']
['c']
['g']
['h']
['f']
['j']
['i']
['e']
[['a'], ['b'], ['c'], ['d'], ['e'], ['f'], ['g'], ['h'], ['i'], ['j']]

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

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

1 Ответ

0 голосов
/ 14 января 2020

Перезапустите его с экспоненциально увеличивающимся таймаутом:

from stopit import ThreadingTimeout
timeout = 3600 # should probably be set slightly above the expected runtime
while True:
    with ThreadingTimeout(timeout) as timeout_ctx:
        result = function_to_call()
    if timeout_ctx.state != timeout_ctx.TIMED_OUT:
        return result
    timeout *= 2

Таким образом, вы уверены, что в среднем вы не будете выполнять больше, чем в два раза больше работы.

Примечание: Я использую в моем примере библиотеку stopit https://github.com/glenfant/stopit

...