如何使用 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)的工作人员的计算成本高得多。为了获得更好的加速,您需要更好的负载平衡。
我正在尝试加快某些进程,并试图为 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)的工作人员的计算成本高得多。为了获得更好的加速,您需要更好的负载平衡。