我怀疑您的最大清单是否足够大,以至于多处理将改善时间安排。使用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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)