如何使用多重处理在一个很大的列表中删除重复项?

如何使用多重处理在一个很大的列表中删除重复项?,第1张

如何使用多重处理在一个很大的列表中删除重复项?

我怀疑您的最大清单是否足够大,以至于多处理将改善时间安排。使用numpy和 多线程 可能是最好的机会。

多重处理会带来相当大的开销,并且会增加内存消耗,例如前面提到的@Frank
Merrow。但是,对于多线程来说,情况并非如此。不要混淆这些术语,因为进程和线程是不同的,这一点很重要。同一进程中的线程共享其内存,而不同进程则不共享。

在Python中使用多核的问题是GIL,它不允许多个线程(在同一进程中)并行执行Python字节码。一些C扩展(例如numpy)可以释放GIL,这使您可以从具有多线程的多核并行中获利。这是您仅使用numpy即可获得重大改进的机会。

from multiprocessing.dummy import Pool  # .dummy uses threadsimport numpy as npr = np.random.RandomState(42).randint(0, 25000000000, 100_000_000)n_threads = 8result = np.unique(np.concatenate(    Pool(n_threads).map(np.unique, np.array_split(r, n_threads)))).tolist()

使用numpy和线程池,拆分数组,使子数组在单独的线程中唯一,然后连接子数组并使重组后的数组再次变得唯一。最终删除重组数组的重复项是必要的,因为在子数组中只能识别
本地 重复项。

对于 低熵数据 (许多重复项),使用

pandas.unique
而不是
numpy.unique
可以更快。与
numpy.unique
它不同的是,它还保留外观顺序。

请注意,使用线程池一样,如果numpy的功能是上述品牌只是感觉 没有多线程的
引擎盖下通过调用低级别的数学库。因此,请始终进行测试以查看它是否确实提高了性能,并且不要将其视为理所当然。


使用100M随机生成的整数进行测试,范围为:

  • 高熵:0-25_000_000_000(199560个重复项)
  • 低熵:0-1000
import timeimport timeitfrom multiprocessing.dummy import Pool  # .dummy uses threadsimport numpy as npimport pandas as pddef time_stmt(stmt, title=None):    t = timeit.repeat(        stmt=stmt,        timer=time.perf_counter_ns, repeat=3, number=1, globals=globals()    )    print(f"t{title or stmt}")    print(f"tt{min(t) / 1e9:.2f} s")if __name__ == '__main__':    n_threads = 8  # machine with 8 cores (4 physical cores)    stmt_np_unique_pool = """np.unique(np.concatenate(    Pool(n_threads).map(np.unique, np.array_split(r, n_threads)))).tolist()"""    stmt_pd_unique_pool = """pd.unique(np.concatenate(    Pool(n_threads).map(pd.unique, np.array_split(r, n_threads)))).tolist()"""    # -------------------------------------------------------------------------    print(f"nhigh entropy (few duplicates) {'-' * 30}n")    r = np.random.RandomState(42).randint(0, 25000000000, 100_000_000)    r = list(r)    time_stmt("list(set(r))")    r = np.asarray(r)    # numpy.unique    time_stmt("np.unique(r).tolist()")    # pandas.unique    time_stmt("pd.unique(r).tolist()")        # numpy.unique & Pool    time_stmt(stmt_np_unique_pool, "numpy.unique() & Pool")    # pandas.unique & Pool    time_stmt(stmt_pd_unique_pool, "pandas.unique() & Pool")    # ---    print(f"nlow entropy (many duplicates) {'-' * 30}n")    r = np.random.RandomState(42).randint(0, 1000, 100_000_000)    r = list(r)    time_stmt("list(set(r))")    r = np.asarray(r)    # numpy.unique    time_stmt("np.unique(r).tolist()")    # pandas.unique    time_stmt("pd.unique(r).tolist()")    # numpy.unique & Pool    time_stmt(stmt_np_unique_pool, "numpy.unique() & Pool")    # pandas.unique() & Pool    time_stmt(stmt_pd_unique_pool, "pandas.unique() & Pool")

就像您在下面的时间中看到的那样,仅使用numpy而不使用多线程已成为最大的性能改进。另请注意

pandas.unique()
numpy.unique()
对于许多重复项,其速度比(仅)快。

high entropy (few duplicates) ------------------------------    list(set(r))        32.76 s    np.unique(r).tolist()        12.32 s    pd.unique(r).tolist()        23.01 s    numpy.unique() & Pool        9.75 s    pandas.unique() & Pool        28.91 slow entropy (many duplicates) ------------------------------    list(set(r))        5.66 s    np.unique(r).tolist()        4.59 s    pd.unique(r).tolist()        0.75 s    numpy.unique() & Pool        1.17 s    pandas.unique() & Pool        0.19 s


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5664323.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存