首页 > 解决方案 > Python过滤具有多处理的大规模迭代器

问题描述

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

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 能力尽可能快地完成这个过滤任务?多处理和多线程真的让我很困惑。:(

标签: pythonpython-3.xmultithreadingmultiprocessing

解决方案


itertools.permutations. 同时,几乎所有与排列有关的问题都可以使用简单的阶乘来解决。

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

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

话虽如此,有factorial(len(data))可能的总排列。如果data没有重复,那么factorial(len(data) - len(pattern))除了 中的项目之外还有可能的项目安排pattern,以及可以居住的len(data) - len(pattern) + 1地方。pattern

从 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)

对于data存在重复的情况pattern,您可以在 Google 上搜索“多少个排列将包含特定序列”之类的内容,以帮助您找出分析公式。


推荐阅读