Python 多处理 numpy.linalg.pinv 导致段错误
Python multiprocessing numpy.linalg.pinv cause segfault
我使用 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-loop,但不能用于 2 个或以上进程。我不知道如何解决这个问题。这是一个麻木的错误吗?有人可以帮我一下吗?
这里没什么可继续的,而且代码缩进是错误的,所以很难猜出你到底在做什么。就我 可以 猜测的程度而言,如果 OS 以未引发 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)
所以大约每秒一次,这只是遍历工作进程列表以查看是否有任何进程(意外地!)死亡。如果一个(或多个)有,它会显示进程名称(您已经提供)和进程退出代码(由您的 OS 给出)。如果那触发了,那将是一个大线索。
如果none死了,那我们就得想
q_res=q.fit(update_freq=500)
"simply" 对于某些 q
个状态需要很长时间。
我必须自己回答这个问题并提供我的解决方案。感谢@Tim Peters 和@aganders 的帮助,我已经解决了这个问题。
当您在 Mac OS 上使用 numpy/scipy 库时,多处理通常会挂起,因为 Apple OS 中使用的 Accelerate Framework 是 OpenBlas numpy 的替代品建造在。很简单,为了解决类似的问题,你必须这样做:
- 卸载numpy和scipy(scipy需要匹配合适的numpy版本)
按照此 link 上的步骤使用 Openblas 重建 numpy。
重新安装 scipy 并测试您的代码以查看其是否有效。
请注意在 Mac OS 上测试您的多处理代码,当您 运行 您的代码时,最好将环境变量设置为 运行你的代码:
OPENBLAS_NUM_THREADS=1 python import_test.py
这样做的原因是 OpenBlas 默认为每个核心创建 2 个线程 运行,在这种情况下有 8 个线程 运行ning(每个核心 2 个线程),即使您设置4个进程。这为线程切换创建了一点开销。我测试了 OPENBLAS_NUM_THREADS=1 配置以限制每个内核上每个进程 1 个线程,它确实比默认设置更快。
我使用 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-loop,但不能用于 2 个或以上进程。我不知道如何解决这个问题。这是一个麻木的错误吗?有人可以帮我一下吗?
这里没什么可继续的,而且代码缩进是错误的,所以很难猜出你到底在做什么。就我 可以 猜测的程度而言,如果 OS 以未引发 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)
所以大约每秒一次,这只是遍历工作进程列表以查看是否有任何进程(意外地!)死亡。如果一个(或多个)有,它会显示进程名称(您已经提供)和进程退出代码(由您的 OS 给出)。如果那触发了,那将是一个大线索。
如果none死了,那我们就得想
q_res=q.fit(update_freq=500)
"simply" 对于某些 q
个状态需要很长时间。
我必须自己回答这个问题并提供我的解决方案。感谢@Tim Peters 和@aganders 的帮助,我已经解决了这个问题。
当您在 Mac OS 上使用 numpy/scipy 库时,多处理通常会挂起,因为 Apple OS 中使用的 Accelerate Framework 是 OpenBlas numpy 的替代品建造在。很简单,为了解决类似的问题,你必须这样做:
- 卸载numpy和scipy(scipy需要匹配合适的numpy版本)
按照此 link 上的步骤使用 Openblas 重建 numpy。
重新安装 scipy 并测试您的代码以查看其是否有效。
请注意在 Mac OS 上测试您的多处理代码,当您 运行 您的代码时,最好将环境变量设置为 运行你的代码:
OPENBLAS_NUM_THREADS=1 python import_test.py
这样做的原因是 OpenBlas 默认为每个核心创建 2 个线程 运行,在这种情况下有 8 个线程 运行ning(每个核心 2 个线程),即使您设置4个进程。这为线程切换创建了一点开销。我测试了 OPENBLAS_NUM_THREADS=1 配置以限制每个内核上每个进程 1 个线程,它确实比默认设置更快。