Python,使用字典的高效并行操作

标签 python c++11 parallel-processing cython numba

首先抱歉我的英语不完美。

我认为我的问题很容易解释。

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 包含大约 20 万个元组,我必须非常快地执行此操作(在普通电脑上最多 2/3 秒)。

我的第一次尝试是在 cython 中使用 prange() 执行此操作(因此我可以从 cython 优化和并行执行中受益),但问题是(一如既往),GIL:在 prange() 我可以使用 cython memviews 管理列表和元组,但我无法将结果插入字典。

在 cython 中,我也尝试使用 c++ std 的 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 领域;但我乐于接受所有建议。

谢谢

最佳答案

还可以通过使用 numpy 的矢量化功能实现多项性能改进:

  1. minmax 值当前针对每个阈值重新计算。相反,它们可以预先计算,然后再用于每个阈值。
  2. 数据样本 (list_tuple) 的循环是在纯 Python 中执行的。此循环可以使用 numpy 进行矢量化。

在下面的测试中,我使用了 data.shape == (200000, 3); thresh.shape == (1000,) 如 OP 中所示。我还省略了对 result dict 的修改,因为根据数据,这可能会很快溢出内存。

应用 1.

v_min = [min(t) for t in data]
v_max = [max(t) for t in data]
for mi, ma in zip(v_min, v_max):
    for value in thresh:
        if ma > value and mi < value:
            pass

与 OP 的代码相比,这会产生 ~ 5 的性能提升。

应用 1. & 2.

v_min = data.min(axis=1)
v_max = data.max(axis=1)
mask = np.empty(shape=(data.shape[0],), dtype=bool)
for t in thresh:
    mask[:] = (v_min < t) & (v_max > t)
    samples = data[mask]
    if samples.size > 0:
        pass

与 OP 的代码相比,这会产生 ~ 30 的性能提升。这种方法还有一个额外的好处,即它不包含对列表的增量 append,因为可能需要重新分配内存,这会减慢程序的速度。相反,它会一次性创建每个列表(每个阈值)。

关于Python,使用字典的高效并行操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51558415/

相关文章:

c++ - 为什么析构函数会禁用隐式 move 方法的生成?

python - 在 Python 中使用正则表达式将一个字符串替换为另一个字符串 : Error: re. 错误:位置 0 处的错误转义\w

python - 用其他数据帧替换数据帧中的空值

python - 如何处理 KerasTensor 和 Tensor?

parallel-processing - 执行以下循环所需的循环数是多少?

performance - OpenMP 通过三重 for 循环并行化矩阵乘法(性能问题)

.net - 如何在 .net 4 中找到并行性的热点?

python - 在命令行解释器中轻松切换 Python 版本?

c++ - 使用 C+11 和 Newlib 时出现错误 "sigemptyset was not declared in this scope"

c++ - 静态转换如何在 C++ 中保持数字的精度?