奇怪的多处理块导入 Numba 函数
Weird multiprocessing block importing Numba function
环境
- GNU/Linux(Fedora 25)。
- 康达环境。
- Python 3.6.1.
- Numba 0.33.0 (np112py36_0).
初始设置(工作正常)
两个文件main.py
和numbamodule.py
:
main.py
它为 运行 execute_numba
函数生成 2 个进程。
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
导入 "work" 是最好的。我什至无法获得 100% 的 运行s... :-/
请注意,我只是添加了一个导入行,而不是实际使用包。其他一些外部导入也会导致阻塞,但我发现上面提出的 "work" 最好(阻塞最多)。
发生了什么事?
首先,你能重现同样的行为吗? (对非虚拟化 GNU/Linux 机器特别感兴趣)
我不知道如何调试它或为什么会发生这种情况。有什么想法吗?
添加一个随机 import xxx
触发块这一事实让我感到害怕,对我来说毫无意义。这是否取决于 timing/delays,这就是为什么有些进口会破坏它而另一些则不会?
备注
- 如您所见,没有回溯,进程只是阻塞。
- 如果我从
numbamodule.py
中删除 import numba
和 @numba.jit
,那么它将始终有效,所以它可能与 Numba 有关?
- 我也可以用旧的 Numba/Python 版本重现相同的行为。尝试使用 Numba 0.25.0 和 0.22.1(均使用 Python 3.5.3)。
更新
- 2017-07-03:澄清一下,我不是在寻找解决方法(我已经在实际代码中找到了解决方法)。我真的很想知道在这种情况下如何处理。了解正在发生的事情并学习如何调试和发现问题,以便在出现问题时报告问题 package/build/environment。您将如何进行?
- 2017-07-10:该块特别发生在
import_module()
调用中。
- 2017-07-11: Numba issue acknowledged.
这里是官方PythonDocker环境的复现。 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
两者的工作方式相同,没有 "working" 导入,matplotlib
和 Pyro4
,并且在 main.py
中有它们。
这仅适用于 matplotlib 调试,确实是猜测,但可能会帮助您缩小问题范围。
您可以在包含 matplotlib 时启动您的程序:
python main.py --verbose-helpful
显示 matplotlib 初始化时的调试输出。由于这听起来像是只存在于您的特定系统上的问题,因此以交互模式启动的方式配置的 matplotlibrc 可能存在一些配置问题。
以下是可用调试模式的概述:
https://matplotlib.org/users/customizing.html
这似乎是一个 Numba 错误,已在 issue 2431 中确认。
现在好像修复了。如果遇到此问题,请更新 numba
和 llvmlite
安装。如果这不能解决问题,您可能应该在该问题中添加评论以重新打开它。
正如@stuartarchibald 评论的那样:
[...] it looks like one processed is blocked is because it has in actual fact segfaulted [...]
[...] Segfaults appearing from this location are almost always due to threads performing concurrent operations inside LLVM, or some issue to do with installing functions during Numba's initialisation sequence. [...]
[...] cannot reproduce any more with llvmlite==0.22.0dev0
and numba==0.37.0.dev
[...]
环境
- GNU/Linux(Fedora 25)。
- 康达环境。
- Python 3.6.1.
- Numba 0.33.0 (np112py36_0).
初始设置(工作正常)
两个文件main.py
和numbamodule.py
:
main.py
它为 运行 execute_numba
函数生成 2 个进程。
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
导入 "work" 是最好的。我什至无法获得 100% 的 运行s... :-/
请注意,我只是添加了一个导入行,而不是实际使用包。其他一些外部导入也会导致阻塞,但我发现上面提出的 "work" 最好(阻塞最多)。
发生了什么事?
首先,你能重现同样的行为吗? (对非虚拟化 GNU/Linux 机器特别感兴趣)
我不知道如何调试它或为什么会发生这种情况。有什么想法吗?
添加一个随机 import xxx
触发块这一事实让我感到害怕,对我来说毫无意义。这是否取决于 timing/delays,这就是为什么有些进口会破坏它而另一些则不会?
备注
- 如您所见,没有回溯,进程只是阻塞。
- 如果我从
numbamodule.py
中删除import numba
和@numba.jit
,那么它将始终有效,所以它可能与 Numba 有关? - 我也可以用旧的 Numba/Python 版本重现相同的行为。尝试使用 Numba 0.25.0 和 0.22.1(均使用 Python 3.5.3)。
更新
- 2017-07-03:澄清一下,我不是在寻找解决方法(我已经在实际代码中找到了解决方法)。我真的很想知道在这种情况下如何处理。了解正在发生的事情并学习如何调试和发现问题,以便在出现问题时报告问题 package/build/environment。您将如何进行?
- 2017-07-10:该块特别发生在
import_module()
调用中。 - 2017-07-11: Numba issue acknowledged.
这里是官方PythonDocker环境的复现。 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
两者的工作方式相同,没有 "working" 导入,matplotlib
和 Pyro4
,并且在 main.py
中有它们。
这仅适用于 matplotlib 调试,确实是猜测,但可能会帮助您缩小问题范围。
您可以在包含 matplotlib 时启动您的程序:
python main.py --verbose-helpful
显示 matplotlib 初始化时的调试输出。由于这听起来像是只存在于您的特定系统上的问题,因此以交互模式启动的方式配置的 matplotlibrc 可能存在一些配置问题。
以下是可用调试模式的概述: https://matplotlib.org/users/customizing.html
这似乎是一个 Numba 错误,已在 issue 2431 中确认。
现在好像修复了。如果遇到此问题,请更新 numba
和 llvmlite
安装。如果这不能解决问题,您可能应该在该问题中添加评论以重新打开它。
正如@stuartarchibald 评论的那样:
[...] it looks like one processed is blocked is because it has in actual fact segfaulted [...]
[...] Segfaults appearing from this location are almost always due to threads performing concurrent operations inside LLVM, or some issue to do with installing functions during Numba's initialisation sequence. [...]
[...] cannot reproduce any more with
llvmlite==0.22.0dev0
andnumba==0.37.0.dev
[...]