底部是我现在拥有的代码。似乎工作正常。但是,我并不完全理解。我以为如果没有.join()
,在该池完成执行之前,我会冒着进入下一个for循环的风险。我们不需要这3条注释掉的行吗?
另一方面,如果我采用.close()
和.join()
的方式,是否有任何方法可以“重新打开”已关闭的池而不是每次都Pool(6)
?
import multiprocessing as mp
import random as rdm
from statistics import stdev, mean
import time
def mesh_subset(population, n_chosen=5):
chosen = rdm.choices(population, k=n_chosen)
return mean(chosen)
if __name__ == '__main__':
population = [x for x in range(20)]
N_iteration = 10
start_time = time.time()
pool = mp.Pool(6)
for i in range(N_iteration):
print([round(x,2) for x in population])
print(stdev(population))
# pool = mp.Pool(6)
population = pool.map(mesh_subset, [population]*len(population))
# pool.close()
# pool.join()
print('run time:', time.time() - start_time)
答案 0 :(得分:1)
建立一个工人池是相对昂贵的事情,因此(如果可能)应该只执行一次(通常在脚本开始时)。
pool.map
命令将阻塞,直到所有任务完成。毕竟,它返回结果列表。除非在所有输入上都调用mesh_subset
并为每个输入返回结果,否则无法这样做。相反,pool.apply_async
之类的方法不会阻塞。 apply_async
返回带有get
方法的ApplyResult对象,该方法将阻塞,直到从工作进程获取结果为止。
pool.close
sets the worker handler's state关闭。这会导致处理程序终止signal the workers。
pool.join
阻塞,直到所有工作进程都终止。
因此,您不需要调用-实际上,您不应该调用pool.close
和pool.join
,直到您完成池为止。一旦工人被派遣信号终止(通过pool.close
),就无法“重新打开”他们。您将需要启动一个新池。
在您的情况下,由于您要做希望循环等待直到所有任务完成,因此使用pool.apply_async
而不是pool.map
没有好处。但是,如果您使用pool.apply_async
,则可以通过调用get
而不是诉诸于关闭并重新启动池来获得与以前相同的结果:
# you could do this, but using pool.map is simpler
for i in range(N_iteration):
apply_results = [pool.apply_async(mesh_subset, [population]) for i in range(len(population))]
# the call to result.get() blocks until its worker process (running
# mesh_subset) returns a value
population = [result.get() for result in apply_results]
循环完成后,len(population)
不变。
如果您不希望在所有任务完成之前阻塞每个循环,则可以使用apply_async
的{{1}}功能:
callback
现在,当任何N_pop = len(population)
result = []
for i in range(N_iteration):
for i in range(N_pop):
pool.apply_async(mesh_subset, [population]),
callback=result.append)
pool.close()
pool.join()
print(result)
返回mesh_subset
时,
return_value
被调用。对result.append(return_value)
的呼叫不会
块,因此apply_async
任务被推入N_iteration * N_pop
s任务
一次全部排队。但是,由于池中有6个工人,最多只能有6个电话
pool
在任何给定时间运行。当工人完成任务时,
谁完成了第一个呼叫mesh_subset
的工作人员。所以
result.append(return_value)
中的值是无序的。这与result
不同
返回一个列表,其返回值与其对应值的顺序相同
参数列表。
除非有例外,否则pool.map
最终将包含result
返回值一次
所有任务都完成了。上方,N_iteration * N_pop
和pool.close()
用于
等待所有任务完成。