首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Python,使用dict的高效并行操作

Python,使用dict的高效并行操作
EN

Stack Overflow用户
提问于 2018-07-27 20:54:34
回答 1查看 462关注 0票数 3

首先,为我的英语不太好而道歉。

我想,我的问题很容易解释。

代码语言:javascript
复制
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++中生成数组的向量(这就是我的判断值)。

第二个问题与此类似:

代码语言:javascript
复制
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域中;但我愿意接受任何建议。

谢谢

EN

回答 1

Stack Overflow用户

发布于 2018-07-28 06:46:52

@a_guest的代码:

代码语言:javascript
复制
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)进行了一点简化:

代码语言:javascript
复制
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

它为满足条件的每个条目更新一次字典条目。

和他的样本数据:

代码语言:javascript
复制
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]]})

时间测试:

代码语言:javascript
复制
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版本速度更快:

代码语言:javascript
复制
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)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51558415

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档