当使用带有numpy和PySide导入的pytnon多处理池时,我的机器上发生了这种非常特殊的悬挂 . 这是我迄今为止在生活中看到的最纠结的错误:)以下代码:
import numpy as np
import PySide
def hang():
import multiprocessing
pool = multiprocessing.Pool(processes = 1)
pool.map(f, [None])
def f(ignore):
print('before dot..')
np.dot(np.zeros((128, 1)), np.zeros((1, 32)))
print('after dot.')
if __name__ == "__main__":
hang()
print('success!')
只在'点之前'挂起打印 . 但它应该打印
before dot..
after dot.
success!
我不是gdb专家,但看起来像gdb显示进程在'np.dot'行退出(或崩溃):
[Inferior 1 (process 2884) exited normally]
我可以采取一些神奇的修改来防止悬挂:
-
如果减少进入'dot'的数组形状(例如从128到127)
-
(!)如果你将进入'dot'的数组的形状从128增加到256
-
如果你不使用多处理并只运行函数'f'
-
(!!!)如果你注释掉在代码中没有使用的PySide导入
任何帮助表示赞赏!
包装版本:
numpy = 1.8.1或1.7.1 PySide = 1.2.1或1.2.2
Python版本:
在达尔文上的Python 2.7.5(默认,2013年9月12日,21:33:34)[GCC 4.2.1兼容的Apple LLVM 5.0(clang-500.0.68)]
要么
在达尔文的Python 2.7.6(默认,2014年4月9日,11:48:52)[GCC 4.2.1兼容的Apple LLVM 5.1(clang-503.0.38)]
Notice :在寻找信息时,我简化了原始代码并提出了一些问题 . 但是这里有一堆更新来保存可能遇到此错误的其他人的历史记录(例如,我开始使用matplotlib,而不是使用pyside)
Update :我缩小了pylab import以导入带有pyside后端的matplotlib,并更新了要运行的代码 .
Update :我正在修改帖子只导入PySide而不是:
import matplotlib
matplotlib.use('qt4agg')
matplotlib.rcParams['backend.qt4']='PySide'
import matplotlib.pyplot
Update :初步统计显示这是一个仅限Mac的问题 . 有3人在Ubuntu上工作,2人在Mac上挂了它 .
Update :在点操作之前打印(os.getpid())给了我一个pid,我没有't see in ' top'显然意味着它崩溃并且多处理等待一个死进程 . 出于这个原因,我无法附加调试器 . 我相应地编辑了主要问题 .
3 回答
我认为这是多处理模块的一个问题 .
请尝试使用以下代码 .
我遇到了这个问题 . 当子进程使用numpy.dot时出现死锁 . 但是当我缩小矩阵的大小时就会运行 . 因此,不是在具有156000个浮点数的矩阵上的点积,而是执行了每个52000的3个点积并将结果连接起来 . 我不确定最大限制是什么,是否取决于子进程数,可用内存或任何其他因素 . 但是,如果可以通过反复试验来识别没有死锁的最大矩阵,那么以下代码应该有所帮助 .
这是numpy为
dot
使用的一些BLAS库的一般问题 .已知使用GNU Openmp构建的Apple Accelerate和OpenBlas在fork的两侧都不安全(父进程和子进程多处理创建) . 他们将陷入僵局 .
numpy无法解决这个问题,但有三种解决方法:
使用基于pthreads的netlib BLAS,ATLAS或git master OpenBlas(2.8.0不起作用)
使用python 3.4及其新的多处理
spawn
或forkserver
启动方法使用线程而不是多处理,numpy为最昂贵的操作释放gil,因此您可以在典型的桌面计算机上存档正常的线程加速