在osx而非Linux上使用numpy的lapack_lite进行多重处理的segfault


问题内容

以下测试代码在OSX 10.7.3上对我来说是段错误,在其他机器上不是:

from __future__ import print_function

import numpy as np
import multiprocessing as mp
import scipy.linalg

def f(a):
    print("about to call")

    ### these all cause crashes
    sign, x = np.linalg.slogdet(a)
    #x = np.linalg.det(a)
    #x = np.linalg.inv(a).sum()

    ### these are all fine
    #x = scipy.linalg.expm3(a).sum()
    #x = np.dot(a, a.T).sum()

    print("result:", x)
    return x

def call_proc(a):
    print("\ncalling with multiprocessing")
    p = mp.Process(target=f, args=(a,))
    p.start()
    p.join()


if __name__ == '__main__':
    import sys
    n = int(sys.argv[1]) if len(sys.argv) > 1 else 50

    a = np.random.normal(0, 2, (n, n))
    f(a)

    call_proc(a)
    call_proc(a)

段错误之一的示例输出:

$ python2.7 test.py
about to call
result: -4.96797718087

calling with multiprocessing
about to call

calling with multiprocessing
about to call

弹出OSX“问题报告”,抱怨类似的段错误KERN_INVALID_ADDRESS at 0x0000000000000108这是一个完整的

如果我使用来运行它n <= 32,它将运行良好;对于任何n >= 33,它崩溃。

如果我注释掉f(a)在原始过程中完成的调用,call_proc则两个都可以。如果我调用f另一个大数组,它仍然会出现段错误。如果我在另一个小型数组上调用它,或者如果我调用f(large_array)然后传递f(small_array)给另一个进程,则它可以正常工作。它们实际上并不需要相同的功能。np.inv(large_array)然后np.linalg.slogdet(different_large_array)假装也发生段错误。

所有注释掉的np.linalg东西都会f导致崩溃;np.dot(self.a, self.a.T).sum()scipy.linalg.exp3m做工精细。据我所知,区别在于前者使用numpy的lapack_lite,而后者则不使用。


这对于我来说在我的桌面上发生

  • python 2.6.7,numpy 1.5.1
  • python 2.7.1,numpy 1.5.1,scipy 0.10.0
  • python 3.2.2,numpy 1.6.1,scipy 0.10.1

我认为2.6和2.7是默认系统安装。我从源tarball手动安装了3.2版本。所有这些numpy都链接到系统Accelerate框架:

$ otool -L `python3.2 -c 'from numpy.core import _dotblas; print(_dotblas.__file__)'`
/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/site-packages/numpy/core/_dotblas.so:
    /System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate (compatibility version 1.0.0, current version 4.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.1)

在另一台具有类似设置的Mac上,我得到相同的行为。

但是f在其他正在运行的计算机上工作的所有选项

  • 带有Python 2.6.1和numpy 1.2.1的OSX 10.6.8已链接到Accelerate 4和vecLib 268(但它没有scipy或slogdet
  • 具有Python 3.2.2,numpy 1.6.1和scipy 0.10.1的Debian 6已链接到系统ATLAS
  • 具有Python 2.7.1,numpy 1.5.1和scipy 0.8.0的Ubuntu 11.04链接到系统ATLAS

我在这里做错什么了吗?可能是什么原因造成的?我看不到在被腌制和去腌制的numpy数组上运行函数如何可能导致它以后在另一个进程中出现段错误。


更新: 当我执行核心转储时,回溯路径位于内部dispatch_group_async_f,即Grand Central
Dispatch接口。大概这是numpy /
GCD与多处理之间的交互中的错误。我将其报告为一个小错误,但如果有人对变通办法或就此问题如何解决有任何想法,将不胜感激。:)


问题答案:

事实证明,OSX上默认使用的Accelerate框架仅不支持在的两侧使用BLAS调用fork。除了链接到不同的BLAS之外,没有其他真正的方法可以解决此问题,而且似乎他们没有兴趣解决此问题。