【发布时间】:2023-01-10 01:59:51
【问题描述】:
描述
我有两个大的集合列表
A = [ {...}, ..., {...} ]
B = [ {...}, ..., {...} ]
我正在执行一个成本非常高的列表理解,对于 A 中每个集合中的每个元素,检查是否与 B 集合中的任何元素匹配,如果匹配则返回 B 各自的集合。
[find_sets(i) for i in A]
例子
一个最小的例子是这样的:
import secrets
# create sample data
def generate_random_strings(num_strings, string_length):
random_strings = []
for i in range(num_strings):
random_strings.append(secrets.token_hex(string_length))
random_strings = set(random_strings)
return random_strings
A = [generate_random_strings(5, 1) for i in range(10000)]
B = [generate_random_strings(5, 1) for i in range(10000)]
# set checker
def find_sets(A):
matching_sets = []
for b_set in B:
if A & b_set:
matching_sets.append(b_set)
return matching_sets
result = [find_set(i) for i in A]
多重处理
它在我所有的 32 个 CPU 内核上明显更快:
from tqdm.contrib.concurrent import process_map
pool = multiprocessing.Pool(processes=32)
results = process_map(find_sets, A, chunksize=100)
问题
虽然对于 A 和 B 的几千个元素,列表理解在我的机器上运行得相当快,并且多处理有助于将它扩展到大约 50.000 个元素,但对于我的实际大小的每个列表中的 500.000 个元素,它变得非常慢。
有什么方法可以通过矢量化、之前对集合进行哈希处理或使用某种优化数据类型(frozensets 没有帮助)来加速我的函数代码?
【问题讨论】:
-
集合已经散列,所以“散列集合”不会做任何事情
-
您可以将其更改为使用列表理解,使用像 Numba 这样的 JIT 编译器,您可以增加块大小,以便您的进程不必经常返回以获取更多数据,使用 Cython 编写更优化的代码等。 .我不确定你是否还有很多其他事情可以做
-
@AhmedAEK 是的,就像示例中一样,集合包含字符串。在这里,我缩短了它们,但在我的例子中,它们有 10-100 个字符。
-
A 中有多少百分比的集合在 B 中没有匹配项?
-
@JonSG 很少,就像最大一样。 5%。理想情况下,所有人都恰好有一场比赛。
标签: python pandas numpy multiprocessing vectorization