首先,为我的英语不太好而道歉。
我想,我的问题很容易解释。
result={}
list_tuple=[(float,float,float),(float,float,float),(float,float,float)...]#200k tuples
threshold=[float,float,float...] #max 1k values
for tuple in list_tuple:
for value in threeshold:
if max(tuple)>value and min(tuple)<value:
if value in result:
result[value].append(tuple)
else:
result[value]=[]
result[value].append(tuple)
list_tuple包含大约200k个元组,我必须非常快地完成这个操作(在普通pc上最多2/3秒)。
我的第一个尝试是在cython中使用prange() (这样我就可以从cython优化和并行执行中受益),但问题是(像往常一样),GIL:在prange()中,我可以使用cython memviews管理列表和元组,但不能将结果插入到dict中。
在cython中,我也尝试使用c++标准的unordered_map,但现在的问题是,我不能在c++中生成数组的向量(这就是我的判断值)。
第二个问题与此类似:
list_tuple=[((float,float),(float,float)),((float,float),(float,float))...]#200k tuples of tuples
result={list_tuple[0][0]:[]}
for tuple in list_tuple:
if tuple[0] in result:
result[tuple[0]].append(tuple)
else:
result[tuple[0]]=[]
这里我还有另一个问题,如果想要使用prange(),我必须使用一个自定义的散列函数来使用一个数组作为c++ unordered_map的键
正如你所看到的,我的代码片段很容易并行运行。
我想尝试使用numba,但由于GIL,我更喜欢使用cython,因为我需要一个二进制代码(这个库可以是商业软件的一部分,所以只允许使用二进制库)。
一般来说,我希望避免使用c/c++函数,我希望找到一种方法来并行管理像字典/列表这样的东西,同时保持cython的性能,尽可能多地保留在Python域中;但我愿意接受任何建议。
谢谢
发布于 2018-07-28 06:46:52
@a_guest的代码:
def foo1(data, thresh):
data = np.asarray(data)
thresh = np.asarray(thresh)
condition = (
(data.min(axis=1)[:, None] < thresh)
& (data.max(axis=1)[:, None] > thresh)
)
result = {v: data[c].tolist() for c, v in zip(condition.T, thresh)}
return result
这段代码为thresh
中的每个条目创建一次字典条目。
操作码,使用default_dict
(来自collections
)进行了一点简化:
def foo3(list_tuple, threeshold):
result = defaultdict(list)
for tuple in list_tuple:
for value in threeshold:
if max(tuple)>value and min(tuple)<value:
result[value].append(tuple)
return result
它为满足条件的每个条目更新一次字典条目。
和他的样本数据:
In [27]: foo1(data,thresh)
Out[27]: {0: [], 1: [[0, 1, 2]], 2: [], 3: [], 4: [[3, 4, 5]]}
In [28]: foo3(data.tolist(), thresh.tolist())
Out[28]: defaultdict(list, {1: [[0, 1, 2]], 4: [[3, 4, 5]]})
时间测试:
In [29]: timeit foo1(data,thresh)
66.1 µs ± 197 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
# In [30]: timeit foo3(data,thresh)
# 161 µs ± 242 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [31]: timeit foo3(data.tolist(),thresh.tolist())
30.8 µs ± 56.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
对数组的迭代比对列表的迭代慢。tolist()
的时间很短;列表的np.asarray
较长。
对于较大的数据样本,array
版本速度更快:
In [42]: data = np.random.randint(0,50,(3000,3))
...: thresh = np.arange(50)
In [43]:
In [43]: timeit foo1(data,thresh)
16 ms ± 391 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [44]: %%timeit x,y = data.tolist(), thresh.tolist()
...: foo3(x,y)
...:
83.6 ms ± 68.6 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
https://stackoverflow.com/questions/51558415
复制相似问题