Странный многопроцессорный блок, импортирующий функцию Numba

Окружающая среда

  • GNU/Linux (Fedora 25).
  • Окружение Конды.
  • Питон 3.6.1.
  • Нумба 0.33.0 (np112py36_0).

Первоначальная настройка (работает нормально)

Два файла main.py и numbamodule.py:

main.py

Что порождает 2 процесса для запуска функции execute_numba.

import time
from importlib import import_module
from multiprocessing import Process


def execute_numba(name):
    # Import the function
    importfunction = 'numbamodule.numba_function'
    module = import_module(importfunction.split('.')[0])
    function = getattr(module, importfunction.split('.')[-1])
    while True:
        print(str(name) + ' - executing Numba function...')
        # Execute the function
        function(10)
        time.sleep(0.1)


if __name__ == '__main__':
    processes = [Process(target=execute_numba, args=(i,)) for i in range(2)]
    [p.start() for p in processes]
    time.sleep(1)
    [p.terminate() for p in processes]

numbamodule.py

Который определяет простую функцию numba_function:

import numba


@numba.jit()
def numba_function(x):
    total = 0
    for i in range(x):
        total += i
    return total

Я могу запустить скрипт main.py и увидеть печать обоих процессов:

$ python main.py
0 - executing Numba function...
1 - executing Numba function...
0 - executing Numba function...
1 - executing Numba function...
0 - executing Numba function...
1 - executing Numba function...
[...]

Ломать это

То, как я его ломаю, немного странное, но это то, на что я наткнулся, пытаясь свести к минимуму воспроизводимый тестовый пример. Пожалуйста, скажите мне, можете ли вы воспроизвести такое же поведение.

В main.py я просто добавляю один из предложенных (ниже) импортов после последнего импорта Process (т.е. раскомментируйте одну строку и попробуйте):

import time
from importlib import import_module
from multiprocessing import Process

#
# Adding one of the import lines bellow results in a block...
# (you may need to install the packages first in the virtual environment)
#
#import matplotlib
#import Pyro4
#import scipy
#import dill


def execute_numba(name):
# [...]

Тогда один процесс может заблокироваться на функции execute_numba (в частности, на вызове import_module()):

$ python main.py 
1 - executing Numba function...
1 - executing Numba function...
1 - executing Numba function...
1 - executing Numba function...
1 - executing Numba function...
1 - executing Numba function...
[...]

Для меня импорт matplotlib и Pyro4 работает лучше всего. Я даже не могу получить блок в 100% случаев... :-/

Обратите внимание, что я просто добавляю одну строку импорта, фактически не используя package. Некоторые другие внешние импорты также приводят к блокировке, но я обнаружил, что предложенные выше «работают» лучше всего (блокируют больше всего).

Что происходит?

Прежде всего, можете ли вы воспроизвести такое же поведение? (особенно интересует невиртуализированные машины GNU/Linux)

Я не знаю, как это отладить или почему это может происходить. Любые идеи?

Тот факт, что добавление одного случайного import xxx вызывает блокировку, меня пугает и не имеет большого смысла. Может ли это зависеть от времени/задержек, и поэтому некоторые импорты нарушают его, а некоторые нет?

Примечания

  • Как видите, трассировки нет, процесс просто блокируется.
  • Если я уберу import numba и @numba.jit из numbamodule.py, то он всегда будет работать, так что, возможно, это как-то связано с Numba?
  • Я могу воспроизвести такое же поведение и со старыми версиями Numba/Python. Пробовал с Numba 0.25.0 и 0.22.1 (оба с Python 3.5.3).

Обновления

  • 03.07.2017: Просто чтобы было понятно, я не ищу обходной путь (у меня он уже есть в реальном коде). Мне искренне интересно узнать, как поступить в таком случае. Поймите, что происходит, и узнайте, как отлаживать и находить проблему, чтобы сообщить о ней, если это неработающий пакет/сборка/среда. Как бы вы поступили?
  • 10.07.2017: Блокировка возникает, в частности, при вызове import_module().
  • 11.07.2017: ошибка Numba подтверждена.

person Peque    schedule 26.06.2017    source источник
comment
Я не могу воспроизвести ошибку при установке Anaconda в Windows 10 Python 3.5. Однако я также не смогу запустить ваш код, если не поставлю import numba в main.py.. Не могли бы вы повторить попытку запустить свой код, внеся это небольшое изменение, чтобы посмотреть, исчезнут ли ваши ошибки? Неважно, что я потом импортирую, это всегда работает.   -  person Matt    schedule 08.07.2017
comment
@Matt Что ты имеешь в виду, когда говоришь, что не можешь? Можете ли вы воспроизвести такое же поведение или вы действительно получаете исключение? (т. е. вы видите трассировку, напечатанную на stderr)   -  person Peque    schedule 10.07.2017
comment
Это работает каждый раз, когда я не могу воспроизвести сбой   -  person Matt    schedule 10.07.2017
comment
@Matt Спасибо за отзыв. :-)   -  person Peque    schedule 10.07.2017
comment
может быть, попробовать запустить его с трассировкой python -m, чтобы получить дополнительную информацию?   -  person MacHala    schedule 31.08.2017
comment
@Peque, похоже, это была ошибка в numba, и теперь она исправлена. Может быть, вы могли бы добавить ответ из информации, полученной из системы отслеживания проблем Github?   -  person jcgiret    schedule 13.05.2018
comment
@jcgiret Да, вы правы ... Здесь добавлен ответ. :-)   -  person Peque    schedule 14.05.2018


Ответы (3)


Похоже, это была ошибка Numba, обнаруженная в issue 2431.

Кажется, теперь это исправлено. Если вы столкнетесь с этим, обновите свои установки numba и llvmlite. Если это не решит проблему, вам, вероятно, следует добавить комментарий к этой проблеме, чтобы открыть ее снова.

Как прокомментировал @stuartarchibald:

[...] похоже, что один обработанный блокируется, потому что на самом деле он [...]

[...] Segfaults, появляющиеся из этого места, почти всегда связаны с потоками, выполняющими параллельные операции внутри LLVM, или с какой-то проблемой, связанной с установкой функций во время последовательности инициализации Numba. [...]

[...] не может больше воспроизводиться с llvmlite==0.22.0dev0 и numba==0.37.0.dev [...]

person Peque    schedule 13.05.2018

Это относится только к отладке matplotlib и действительно предполагает предположение, но может помочь вам немного сузить проблему.

Вы можете запустить свою программу при включении matplotlib с помощью:

python main.py --verbose-helpful

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

Вот обзор доступных режимов отладки: https://matplotlib.org/users/customizing.html< /а>

person devnull    schedule 08.07.2017
comment
Спасибо за Ваш ответ. Однако проблема не имеет прямого отношения к Matplotlib. Обратите внимание, что matplotlib — это только один из внешних импортов, которые нарушают код, но есть и другие. Кроме того, добавление --verbose-helpful говорит мне, что Matplotlib не запускается в интерактивном режиме. - person Peque; 10.07.2017
comment
Мне жаль. У меня была опечатка во флаге. Пожалуйста, попробуйте обновленную версию. Я так понял, что у вас проблемы и с другим импортом. Я никогда не использовал Pyro4. После короткого просмотра документов, matplotlib, а также Pyro4, похоже, используют потоки, которые могут создавать проблемы. Однако в matplotlib вы можете легко отключить интерактивный режим и получить дополнительную информацию, добавив предложенный флаг. Я не могу обещать, что это приведет к решению, но это может быть первым шагом. - person devnull; 10.07.2017
comment
ладно, все пробовал на нескольких системах на моем сайте, работало без всяких блокировок. Пробовали ли вы использовать strace, чтобы увидеть последний системный вызов, который выполняет python? - person devnull; 10.07.2017
comment
Последние строки выглядят так. Хотя я не могу понять, что они означают. ???? - person Peque; 10.07.2017
comment
Вы завершили программу с помощью crtl-c? Так как он, кажется, выходит в конце. Я понял ваш первый отчет так, что программа зависает и никогда не выходит и не выдает никаких результатов. - person devnull; 10.07.2017
comment
Давайте продолжим обсуждение в чате. - person devnull; 10.07.2017

Вот воспроизведение в официальной среде Python Docker. Далее следует Dockerfile (поместите вместе с файлами .py).

FROM python:3.5

RUN pip install numba matplotlib pyro4

ADD . /opt
WORKDIR /opt

CMD python main.py

Затем:

docker build -t so-44764520 .
docker run --rm -it so-44764520

Оба работают одинаково, без "рабочих" импортов, matplotlib и Pyro4, и с ними в main.py.

person saaj    schedule 03.07.2017
comment
Спасибо. Это может быть полезно для других, чтобы попытаться воспроизвести ошибку, если они не хотят работать с Conda/virtualenv. Однако он по-прежнему оставляет много вопросов открытыми. ^^ Я сам не могу воспроизвести это с помощью Docker, но основная проблема остается: что происходит при возникновении блокировки и как ее решить? Не зная ответа на этот вопрос, мы не можем сказать, что Docker решает проблему. Может быть, это просто случайно, так как регистр очень чувствителен к небольшим изменениям (например, простое добавление строки импорта в код ломает его). - person Peque; 03.07.2017
comment
Да, смысл ответа в том, чтобы продемонстрировать, что он работает в официальной среде, и не стоит искать ошибку Python в вашем коде. Также это указывает на то, что, вероятно, ваша среда или определенная версия дистрибутива conda каким-то образом повреждены. Может помочь переустановка или другая версия. В противном случае вы можете просто использовать Docker или другую среду, поскольку нет никаких доказательств того, что это не решает проблему (или служит обходным путем). - person saaj; 03.07.2017
comment
Да, уже пытался переустановить и изменить версии Python/Numba безуспешно (как указано в примечаниях к вопросу). Отказаться от текущей среды и перейти на Docker на данный момент невозможно. Так что вопрос все еще требует ответа: что делать в таком случае? как отладить и найти проблему? (то есть: если что-то сломано: что это? чтобы я мог сообщить об этом или исправить) - person Peque; 03.07.2017
comment
По сути, если я хочу убедиться, что Docker (или что-то еще) решит проблему, мне нужно сначала узнать, в чем проблема. Если что-то сломано, я скорее найду это и сообщу об этом сейчас, когда у меня есть среда, которая это воспроизводит. ;-) - person Peque; 03.07.2017
comment
Я согласен, что это хорошая идея — попытаться воспроизвести ошибки и сообщить о них сопровождающим. Тот факт, что вы не искали обходной путь, изначально не был ясен. Однако использование изображения на основе continuumio/anaconda3 также работает. Так что с дистрибутивом тоже все в порядке. Вы пробовали на другой машине? - person saaj; 03.07.2017
comment
Также к вопросу, как это отлаживать. Это немного сложнее, чем в случае с одним процессом, но применяются те же правила. Добавьте ведение журнала и посмотрите, до какой строки кода может добраться ваш подпроцесс. Добавьте точки останова и попробуйте отладить подпроцесс с помощью отладчика pdb или PyDev. Соответствующие теги содержат некоторые детали. - person saaj; 03.07.2017