Python多处理numpy.linalg.pinv导致段错误

时间:2016-08-08 20:27:38

标签: python numpy python-multiprocessing statsmodels

我使用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的建议,我成功地发现这些进程实际上已经意外退出。在调试模式下,我可以确定它是由arch库使用的numpy.linalg.pinv()中的实际svd函数导致此问题。然后我的问题是:为什么?它适用于单个进程for循环,但它不能用于2个进程或更高级别。我不知道如何解决这个问题。这是一个numpy bug吗?有人可以帮我一点吗?

2 个答案:

答案 0 :(得分:3)

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

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

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

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

  4. 有些人会在Mac OS上测试你的多处理代码,当你运行你的代码时,最好设置一个env变量来运行你的代码:

    OPENBLAS_NUM_THREADS=1 python import_test.py
    

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

答案 1 :(得分:1)

这里没什么可去的,代码缩进是错误的,因此很难猜出你真正在做什么。在我可以猜测的程度上,如果操作系统以不引发Python异常的方式杀死进程,那么你所看到的就会发生。

要尝试的一件事:首先列出四个ps对象的列表process_i。然后在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州而言,“简单地”需要很长时间。