Python 使用多处理过滤大量迭代器

Python filter massive iterator with multiprocessing

这是我在使用多处理之前的代码。获取满足指定条件的大规模迭代器中的项目数是一项任务:

from itertools import permutations

def f(input_):
    if 'AB' in ''.join(input_):
        return True
    else:
        return False

if __name__ == "__main__":
    iterator = permutations(['A', 'B',...])
    count = 0
    for item in iterator:  # it is an itertools.permutations object, with str inside
        if f(item):
            count += 1
    print(count)

但是迭代器太大了,我需要进行多处理或多线程(不确定哪个更好)来加快处理速度。

我在Python中参考了很多关于多任务的在线参考资料,并且尝试了一些方法。不幸的是,我仍然找不到解决方案,因为我尝试的每种方法都有一些问题。 例如:

from multiprocessing import Pool

def f(input_):
    if 'AB' in ''.join(input_):
        return True
    else:
        return False

if __name__ == "__main__":
    pool = Pool()
    result = pool.imap_unordered(f, iterator)
    print(sum(result))

在这个例子中,问题是这段代码比我原来的代码运行得更慢。我也试过使用 pool.map(),但它也比以前慢了,而且它耗尽了我所有的内存。

我应该如何尽我的CPU能力使这个过滤任务尽快完成?多处理和多线程真的让我很困惑。 :(

itertools.permutations 相比,多处理具有巨大的开销。同时,几乎任何排列问题都可以使用简单的阶乘来解决。

你的“巨大”迭代器可以写成

data = ['A', 'B', 'C', ...]
pattern = ('A', 'B')
sum(pattern in x for x in permutations(data))

也就是说,总共有 factorial(len(data)) 种可能的排列。如果 data 没有重复,那么除了 pattern 之外还有 factorial(len(data) - len(pattern)) 种可能的物品排列方式,以及 pattern 可以居住的 len(data) - len(pattern) + 1 处。

从 python 3.8 开始,您可以

from math import prod

count = prod(range(2, len(data) - len(pattern) + 2))

对于以前的版本,您必须这样做

from functools import reduce
from operator import mul

count = reduce(mul, range(2, len(data) - len(pattern) + 2), 1)

对于 datapattern 中存在重复的情况,您可以 google 搜索类似“多少排列将包含特定序列”之类的内容以提供帮助你算出解析式