如何使用 Pool 在 Python 中使用多处理

How to use multiprocessing in Python using Pool

我正在尝试加快某些进程,并试图为 Python 脚本使用多个内核。在我将它应用到我正在做的事情之前,我试图把框架弄下来。到目前为止,我有一些有用的东西,但它有两个缺点: 1)它输出每次迭代的信息——我只想要最终值 2) 它只加快了一点点速度(大约是我测试时原始时间的 60%),这是更好的,但不是游戏规则的改变者。

代码:

import multiprocessing as mp
import time
import itertools
start = time.clock()
processes = []
output_list = [] 

def all_combinations(count_arg):
    returns_list = []
    for i in range(1,count_arg+1):
        tmp_comb = list(itertools.combinations(range(0,count_arg),i))
        for tmp_tup in tmp_comb:
            returns_list.append(tmp_tup)
    return returns_list
def worker(num):   
    tmp_output = len(all_combinations(num))
    return tmp_output
if __name__ =='__main__':
    pool = mp.Pool(8)
    num_list = range(24)
    output_list2 = pool.map(worker, num_list)   
    pool.close()
    pool.join       
elapsed = (time.clock() - start)
results = output_list
print elapsed

这是我在非多处理情况下使用的:

import time
import itertools
start = time.clock()
processes = []
def all_combinations(count_arg):
    returns_list = []
    for i in range(1,count_arg+1):
        tmp_comb = list(itertools.combinations(range(0,count_arg),i))
        for tmp_tup in tmp_comb:
            returns_list.append(tmp_tup)
    return returns_list

def worker(num,output):
    """thread worker function"""
    tmp_output = len(all_combinations(num))
    return tmp_output

for i in range(24):
    processes.append(worker(i,"hi"))

elapsed = (time.clock() - start)

print len(processes)
print elapsed

你生成了很多列表只是为了把它们扔掉......我会把 all_combinations 变成一个生成器:

def all_combinations(count_arg):
    for i in range(1,count_arg+1):  # xrange on python2.x
        # yield from itertools.combinations(...) on python3.3+
        for comb in itertools.combinations(range(0,count_arg),i)):
            yield comb

现在 worker 需要更改以从生成器而不是列表中获取项目数...

def worker(num):
    return sum(1 for _ in all_combinations(num))

这些变化大多只是美学上的——你可能不会注意到这样或那样的大加速(尽管我可能是错的,就像任何事情一样,你永远不会知道直到你分析......)。

既然那已经不在了,开始你的真实问题...

1) It outputs information from each iteration ...

当然 multiprocessing.Pool.map 会为池中的每个进程提供一个结果。在这种情况下,您将获得 24 个(每个 num_list 个)。幸运的是,这个 "reduce" 阶段真的很简单——因为 worker 返回的每个元素只是一个部分和,你可以只得到输出列表的和:

print sum(output_list2)

2) It only speeds things up a little bit...

这是因为您的算法无法很好地扩展。你的速度只会和你最慢的 运行 工人一样快——而且你的工人并不都在相似的时间执行。请注意,随着数字越来越高,您在给定的 worker 中进行越来越多的组合。这使得计算较大数字(例如 24)的工作人员比计算较小数字(例如 12)的工作人员的计算成本高得多。为了获得更好的加速,您需要更好的负载平衡。