【问题标题】:Python multiprocessing numpy.linalg.pinv cause segfaultPython 多处理 numpy.linalg.pinv 导致段错误
【发布时间】:2016-08-08 20:27:38
【问题描述】:

我使用来自 python 的多处理包编写了一个函数,并试图提高我的代码速度。

from arch.univariate import ARX, GARCH
from multiprocessing import Process
import multiprocessing
import time

def batch_learning(X, lag_array=None):
    """
    X is a time series array
    lag_array contains all possible lag numbers
    """
    # init a queue used for triggering different processes
    queue = multiprocessing.JoinableQueue()
    data = multiprocessing.Queue()

    # a worker called ARX_fit triggered by queue.get()
    def ARX_fit(queue):
        while True:
            q = queue.get()
            q.volatility = GARCH()
            print "Starting to fit lags %s" %str(q.lags.size/2)
            try:
                q_res=q.fit(update_freq=500)
            except:
                print "Error:...."
            print "finished lags %s" %str(q.lags.size/2)
            queue.task_done()
    # init four processes
    for i in range(4):
        process_i = Process(target=ARX_fit, name="Process_%s"%str(i),   args=(queue,))
        process_i.start()
    # put ARX model objects into queue continuously
    for num in lag_array:
        queue.put(ARX(X, lags=num))

    # sync processes here
    queue.join()   

    return

调用函数后:

batch_learning(a, lag_array=range(1,10))

但是它卡在了中间,我得到了如下的打印信息:

Starting to fit lags 1
Starting to fit lags 3
Starting to fit lags 2
Starting to fit lags 4
finished lags 1
finished lags 2
Starting to fit lags 5
finished lags 3
Starting to fit lags 6
Starting to fit lags 7
finished lags 4
Starting to fit lags 8
finished lags 6
finished lags 5
Starting to fit lags 9

它永远运行,但在我的 Mac OS El Captain 上没有任何打印输出。然后使用 PyCharm 调试模式并感谢 Tim Peters 的建议,我成功地发现进程实际上意外退出。在调试模式下,我可以查明它实际上是拱库使用的 numpy.linalg.pinv() 中的 svd 函数导致了这个问题。那么我的问题是:为什么?它适用于单进程 for-loop,但不能适用于 2 个或以上进程。我不知道如何解决这个问题。这是一个麻木的错误吗?有谁能帮帮我吗?

【问题讨论】:

  • 奇怪的是,如果我删除了try: q_res=q.fit(update_freq=500) except: print "Error:...."。它工作正常。我猜fit函数有问题?
  • 您使用的是什么平台/操作系统? OS X Accelerate 框架存在以类似方式表现出来的多处理问题。
  • @aganders3:我正在使用 Mac OS El Captain。你知道如何解决这个问题吗?
  • 据我所知,没有解决方案,但有一些解决方法。这是我们实验室的一大挫折。请参阅此问题以获得进一步解释:stackoverflow.com/questions/9879371/…
  • 在对我的“答案”的评论中建议了这一点:尝试使用 Python 3(3.4 或更高版本)和 multiprocessing spawn 启动方法。或 Windows 上的任何 Python 版本。这些将fork() 排除在外。 Python 本身承受着巨大的痛苦,以使 threading.Thread 线程与 fork() 配合得很好,但不能做任何事情来使其他软件的线程正常。

标签: python numpy python-multiprocessing statsmodels


【解决方案1】:

我必须自己回答这个问题并提供我的解决方案。感谢@Tim Peters 和@aganders 的帮助,我已经解决了这个问题。

当您在 Mac OS 上使用 numpy/scipy 库时,多处理通常会挂起,因为 Apple OS 中使用的 Accelerate Framework 是 OpenBlas numpy 的替代品。简单地说,为了解决类似的问题,您必须执行以下操作:

  1. 卸载numpy和scipy(scipy需要匹配正确的numpy版本)
  2. 按照link 上的过程使用 Openblas 重建 numpy。

  3. 重新安装 scipy 并测试您的代码,看看它是否有效。

有些人建议在 Mac OS 上测试你的多处理代码,当你运行你的代码时,最好设置一个环境变量来运行你的代码:

OPENBLAS_NUM_THREADS=1 python import_test.py

这样做的原因是 OpenBlas 默认为每个内核创建 2 个线程来运行,在这种情况下,即使您设置了 4 个进程,也会有 8 个线程在运行(每个内核 2 个)。这为线程切换产生了一些开销。我测试了 OPENBLAS_NUM_THREADS=1 配置来限制每个内核上的每个进程 1 个线程,它确实比默认设置快。

【讨论】:

    【解决方案2】:

    这里没有太多可做的,而且代码缩进是错误的,所以很难猜出你真正在做什么。在我可以猜测的范围内,如果操作系统以没有引发 Python 异常的方式终止进程,您所看到的可能会发生。

    要尝试的一件事:首先列出您的四个 process_i 对象的列表 ps。然后在queue.join()之前加上:

    while ps:
        new_ps = []
        for p in ps:
            if p.is_alive():
                new_ps.append(p)
            else:
                print("*********", p.name, "exited with", p.exitcode)
        ps = new_ps
        time.sleep(1)
    

    所以大约每秒一次,这只是通过工作进程列表来查看是否有任何(意外!)死亡。如果有一个(或多个),它会显示进程名称(您已经提供)和进程退出代码(由您的操作系统给出)。如果这触发了,那将是一个很大的线索。

    如果没有人死亡,那么我们不得不怀疑是否

    q_res=q.fit(update_freq=500)
    

    对于某些q 状态,“简单”需要很长时间。

    【讨论】:

    • 抱歉出现缩进问题。我现在修好了。它应该是可读的。我想要做的只是创建一个多处理函数来用不同的参数训练一个拱模型很多次。 q.fit() 函数是我需要多个进程并行处理的函数。完成6个任务后卡住了。我不知道为什么。您可以从打印输出中看到这一点。 lags=7 时卡住,lags >= 7 时永远不会继续完成任务
    • 嗨,蒂姆。感谢您的回复。我试图将您的 sn-p 添加到我的代码中,但进程意外终止。输出为('*********', 'Process_0', 'exited with', 1) ('*********', 'Process_1', 'exited with', -11) ('*********', 'Process_2', 'exited with', -11) ('*********', 'Process_3', 'exited with', -11)。我对多处理编程不是很先进。我想知道进程被杀死的原因是什么。
    • 这张票上有一些额外的cmets。我尝试了 Pycharm 中的代码,它告诉我python quits unexpected with _u_math_linalg.so crash (segfault)。然后我开始调试错误所在的位置。我发现问题很深。然后它是由 q 引起的,它是基于 numpy 构建的 arch 库中的 ARX 对象。更深入地确定了 np.linalg.pinv 函数内的 numpy 函数svd(a, 0)。似乎当它达到 lag num = 8 时,svd 崩溃导致进程退出。我跟踪了a inside svd(a, 0)。似乎是不恰当的a 导致了崩溃。
    • 但是,我仍然无法弄清楚为什么单个 for 循环可以毫无问题地运行它,但使用多处理会导致崩溃。怀疑 np.linalg.pinv 不是线程安全的。我见过一些由相关的 np.linalg 函数引起的多处理崩溃。这是另一个错误吗?请帮忙!
    • 是的,Linux-y 系统上的“-11”表示进程被段错误杀死。退出状态“1”没有一般适用的含义 - 取决于您正在运行的精确软件。我没有使用arch 的经验。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2011-04-13
    • 2019-05-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-11
    相关资源
    最近更新 更多