【问题标题】:Weird multiprocessing block importing Numba function奇怪的多处理块导入 Numba 函数
【发布时间】:2017-11-29 13:51:00
【问题描述】:

环境

  • GNU/Linux (Fedora 25)。
  • Conda 环境。
  • Python 3.6.1。
  • Numba 0.33.0 (np112py36_0)。

初始设置(工作正常)

main.pynumbamodule.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...
[...]

对我来说,matplotlibPyro4 导入“工作”最好。我什至无法获得 100% 的运行... :-/

请注意,我只是添加了一个导入行,而不是实际使用包。其他一些外部导入也会导致阻塞,但我发现上面提出的那些“工作”最好(阻塞最多)。

发生了什么?

首先,你能重现同样的行为吗? (对非虚拟化 GNU/Linux 机器特别感兴趣)

我不知道如何调试它或为什么会发生这种情况。有什么想法吗?

添加一个随机的import xxx 会触发该块的事实让我感到害怕并且对我来说毫无意义。这是否取决于时间/延迟,这就是为什么有些导入会破坏它而另一些不会?

注意事项

  • 如您所见,没有回溯,进程只是阻塞。
  • 如果我从numbamodule.py 中删除import numba@numba.jit,那么它将始终有效,所以也许它与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 issue acknowledged.

【问题讨论】:

  • 我无法在 Windows 10 Python 3.5 Anaconda 安装中重现该错误。但是,如果我不将import numba 放入main.py.,我也无法运行您的代码,您能否重试运行您的代码,进行这个小改动,看看您的错误是否也消失了?不管我之后导入什么,它总是有效的。
  • @Matt 你说“你不能”是什么意思?您是否能够重现相同的行为,或者您实际上是否遇到了异常? (即:您会看到在stderr 上打印的回溯)
  • 每次无法重现故障时它都有效
  • @Matt 感谢您的反馈。 :-)
  • @jcgiret 是的,你是对的......在此处添加了答案。 :-)

标签: python numba


【解决方案1】:

这里是官方 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

两者的工作方式相同,没有“工作”导入,matplotlibPyro4,并在 main.py 中使用它们。

【讨论】:

  • 谢谢。如果其他人不想使用 Conda/virtualenv,这对于尝试重现错误可能很有用。然而,它仍然留下了很多问题。 ^^ 我自己无法使用 Docker 重现它,但主要问题仍然存在:当阻塞发生时会发生什么以及如何解决它?在不知道这个问题的答案的情况下,我们不能说 Docker 解决了这个问题。也许这只是偶然,因为这种情况对微小的变化非常敏感(即:简单地在代码中添加一个导入行会破坏它)。
  • 是的,答案的重点是证明它在官方环境中工作,并且看起来不值得在代码中寻找 Python 错误。它还表明您的环境或某些版本的 conda 发行版可能以某种方式损坏。重新安装或其他版本可能会有所帮助。否则,您可以使用 Docker 或其他环境,因为没有证据表明它不能解决问题(或作为一种解决方法)。
  • 是的,已经尝试重新安装和更改 Python/Numba 版本,但没有成功(如问题说明中所述)。在这一点上,放弃当前环境并使用 Docker 是不可能的。所以这个问题还是需要回答的:遇到这种情况怎么办?如何调试和发现问题? (即:如果有问题:它是什么?以便我可以报告或修复它)
  • 基本上,如果我想确保 Docker(或其他任何东西)解决问题,我首先需要知道问题是什么。如果有什么东西坏了,我宁愿找到它并报告它,因为我有一个可以重现它的环境。 ;-)
  • 我同意尝试重现错误并将其报告给维护人员是个好主意。首先并不清楚您没有寻找解决方法的事实。但是基于continuumio/anaconda3 的图像也可以。所以看起来分布也还可以。你在另一台机器上试过吗?
【解决方案2】:

这仅适用于 matplotlib 调试,并且确实是在猜测,但可能会帮助您缩小问题范围。

当包含 matplotlib 时,您可以使用以下命令启动程序:

python main.py --verbose-helpful

它显示了 matplotlib 初始化的调试输出。由于这听起来像是一个仅存在于您的特定系统上的问题,因此 matplotlibrc 可能存在一些配置问题,它以交互模式启动的方式进行配置。

以下是可用调试模式的概述: https://matplotlib.org/users/customizing.html

【讨论】:

  • 感谢您的回答。然而,这个问题与 Matplotlib 没有直接关系。请注意,matplotlib 只是“破坏”代码的外部导入之一,但还有其他导入。此外,添加 --verbose-helpful 告诉我 Matplotlib 没有以交互模式启动。
  • 对不起。我在国旗上有错字。请尝试更新版本。我确实了解您也会遇到其他进口问题。我从未使用过 Pyro4。在对文档进行简短扫描后,matplotlib 和 Pyro4 似乎使用了可能会产生问题的线程。但是,在 matplotlib 中,您可以通过添加建议的标志轻松停用交互模式并获取其他信息。我不能保证这会导致解决方案,但这可能是第一步。
  • 好的,在我网站上的多个系统上都进行了尝试,没有任何锁定。您是否尝试了 strace 来查看 python 正在执行的最后一个系统调用?
  • 最后几行look like this。虽然我无法解释它们的意思。 ?
  • 您是否使用 crtl-c 终止了程序?因为它似乎在最后退出。我理解你的第一份报告,程序挂起,永远不会退出,也不会产生任何输出。
【解决方案3】:

这似乎是一个 Numba 错误,已在 issue 2431 中确认。

现在好像解决了。如果您遇到这种情况,请更新您的 numballvmlite 安装。如果这不能解决问题,您可能应该在该问题中添加评论以重新打开它。

正如@stuartarchibald 评论的那样:

[...] 看起来一个被处理的被阻止是因为它实际上有段错误 [...]

[...] 从这个位置出现的段错误几乎总是由于线程在 LLVM 中执行并发操作,或者在 Numba 的初始化序列期间与安装函数有关。 [...]

[...] 无法再使用 llvmlite==0.22.0dev0numba==0.37.0.dev [...] 进行复制 [...]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-08
    • 1970-01-01
    • 2015-01-27
    • 1970-01-01
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 2021-02-27
    相关资源
    最近更新 更多