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

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

  • GNU/Linux (Fedora 25).
  • среда Conda.
  • Python 3.6.1.
  • Numba 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 script и посмотреть, как печать обоих процессов:

$ 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% пробегов...: -/

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

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

Во-первых, можете ли вы воспроизвести одно и то же поведение? (специально заинтересованные в не виртуализированных машинах GNU/Linux)

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

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

Примечания

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

Обновления

  • 2017-07-03: просто, чтобы было ясно, я не ищу обходного пути (у меня уже есть один в реальном коде). Я искренне заинтересован в том, как действовать в таком случае. Понимайте, что происходит, и узнайте, как отлаживать и находить проблему, чтобы сообщить об этом, если это сломанный пакет/сборка/среда. Как вы продолжите?
  • 2017-07-10: Блок возникает, в частности, при вызове import_module().
  • 2017-07-11: Сообщить о выпуске Numba.

Ответы

Ответ 1

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

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

python main.py --verbose-helpful

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

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

Ответ 2

Здесь воспроизводится на официальной среде Pockon 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.