Python 使用Numpy进行多线程处理会导致分段错误
我试图生成一个包含不同数据“分组”的报告。对于每一个,我必须以不同的方式查询postgres并应用不同的逻辑,这可能需要相当长的时间(约1小时) 为了提高性能,我为每个任务创建了一个线程,每个线程都有自己的连接,因为psycopg2会在每个连接上连续执行查询。我使用numpy来计算一部分数据的中值和平均值(这在各组之间是通用的) 下面是我的代码的一个简短示例:Python 使用Numpy进行多线程处理会导致分段错误,python,multithreading,numpy,segmentation-fault,Python,Multithreading,Numpy,Segmentation Fault,我试图生成一个包含不同数据“分组”的报告。对于每一个,我必须以不同的方式查询postgres并应用不同的逻辑,这可能需要相当长的时间(约1小时) 为了提高性能,我为每个任务创建了一个线程,每个线程都有自己的连接,因为psycopg2会在每个连接上连续执行查询。我使用numpy来计算一部分数据的中值和平均值(这在各组之间是通用的) 下面是我的代码的一个简短示例: # -*- coding: utf-8 -*- from postgres import Connection from lookup
# -*- coding: utf-8 -*-
from postgres import Connection
from lookup import Lookup
from queries import QUERY1, QUERY2
from threading import Thread
class Report(object):
def __init__(self, **credentials):
self.conn = self.__get_conn(**credentials)
self._lookup = Lookup(self.conn)
self.data = {}
def __get_conn(self, **credentials):
return Connection(**credentials)
def _get_averages(self, data):
return {
'mean' : numpy.mean(data),
'median' : numpy.median(data)
}
def method1(self):
conn = self.__get_conn()
cursor = conn.get_cursor()
data = cursor.execute(QUERY1)
for row in data:
# Logic specific to the results returned by the query.
row['arg1'] = self._lookup.find_data_by_method_1(row)
avgs = self._get_averages(row['data'])
row['mean'] = avgs['mean']
row['median'] = avgs['median']
return data
def method2(self):
conn = self.__get_conn()
cursor = conn.get_cursor()
data = cursor.execute(QUERY2)
for row in data:
# Logic specific to the results returned by the query.
row['arg2'] = self._lookup.find_data_by_method_2(row)
avgs = self._get_averages(row['data'])
row['mean'] = avgs['mean']
row['median'] = avgs['median']
return data
def lookup(self, arg):
methods = {
'arg1' : self.method1,
'arg2' : self.method2
}
method = methods(arg)
self.data[arg] = method()
def lookup_args(self):
return self._lookup.find_args()
def do_something_with_data(self):
print self.data
def main():
creds = {
'host':'host',
'user':'postgres',
'database':'mydatabase',
'password':'mypassword'
}
reporter = Report(**creds)
args = reporter.lookup_args()
threads = []
for arg in args:
thread = Thread(target=reporter.lookup, args=(arg,))
threads.append(thread)
for thread in threads:
thread.start()
for thread in threads:
thread.join()
reporter.do_something_with_data()
导入的Connection
类是围绕psycopg2的一个简单包装器,用于方便创建游标和连接到多个postgres数据库
导入的查找
类接受一个连接
实例,并用于执行短查询以查找相关数据,这些数据在合并到较大的查询中时会大大降低性能
\u get\u averages
示例方法所接受的数据
是一个decimal.decimal
对象列表
当我同时运行所有线程时,我得到一个segfault。如果我独立运行每个线程,脚本将成功完成
使用gdb
我发现numpy是罪魁祸首:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffedc8c700 (LWP 10997)]
0x00007ffff2ac33b7 in sortCompare (a=0x2e956298, b=0x2e956390) at numpy/core/src/multiarray/item_selection.c:1045
1045 numpy/core/src/multiarray/item_selection.c: No such file or directory.
in numpy/core/src/multiarray/item_selection.c
我知道numpy有很多缺点,但这似乎只会影响包含类实例和其他数值类型的排序列表。我的列表中的对象保证是decimal.decimal
实例。(是的,我核实了这一点)
什么会导致
numpy
在线程内部使用时导致segfault,但在其他情况下会按预期运行?我不知道这是否重要,但如果列表元素是decimal.decimal
,那么由它们构建的数组将是dtype=object
。但我发现,代码甚至试图访问.c
源文件,这让我感到困惑。这应该只在编译过程中发生。NumPy可以也将在C代码中出错,因为它主要是用C编写的,上面只有一层Python的外衣。@msw明白。我不明白的是,当多个线程运行时,它为什么会失败。我不知道这是否重要,但如果列表元素是decimal.decimal
,那么从它们构建的数组将是dtype=object
。但我发现,代码甚至试图访问.c
源文件,这让我感到困惑。这应该只在编译过程中发生。NumPy可以也将在C代码中出错,因为它主要是用C编写的,上面只有一层Python的外衣。@msw明白。我不明白的是,当多个线程运行时,它为什么会失败。