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

时间:2015-01-21 22:11:31

标签: python multiprocessing

我正在尝试加速某些进程,并尝试将多个内核用于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

1 个答案:

答案 0 :(得分:0)

你生成了很多列表只是为了扔掉它们......我将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)它输出每次迭代的信息......

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

print sum(output_list2)
  

2)它只会加速一点......

这是因为您的算法无法很好地扩展。你只会和最慢的跑步工人一样快 - 而你的工人并不都在同样的时间里执行。请注意,随着数字越来越高,您在给定的工作人员中执行的组合越来越多。这使得较高数量(例如24)的工人比较低数量的工人(例如12)更昂贵。为了获得更好的加速,您需要更好的负载平衡。