【问题标题】:Set comparison optimization设置比较优化
【发布时间】: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


【解决方案1】:

这在我的测试中运行速度快了一个数量级:

import collections

reverse_map = collections.defaultdict(set)
for idx, elements in enumerate(B):
    for element in elements:
        reverse_map[element].add(idx)

def find_sets(A):
    union = set()
    emptyset = set()
    for element in A:
        union |= reverse_map.get(element, emptyset)
    return [B[idx] for idx in union]

【讨论】:

  • 这太棒了!它比我最初的解决方案快大约 15 倍!不知道 defaultdict
【解决方案2】:

你可以使用理解而不是find_sets

 result = [[b for b in B if a & b] for i in A]

【讨论】:

  • 我喜欢它的简单性,但不幸的是,它在速度方面与我最初的解决方案相当(或稍慢)。
  • 这是绝对正确的,我正在尝试找出更好的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-24
  • 1970-01-01
  • 2021-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多