我想创建一个函数,在给定函数列表和相对参数的情况下,启动尽可能多的进程以并行化这些任务。运行进程的数量不能超过我的CPU核心数。当一个过程结束时,应该用另一个过程替换它,直到结束。
我尝试使用python Pools实现这样的功能。这是我的功能:
from multiprocessing import Pool, cpu_count
CPUS = cpu_count()
def parallelize(functions, args):
results = []
if CPUS > 1:
for i in xrange(0, len(functions), CPUS):
pool = Pool()
for j in xrange(CPUS):
if i + j >= len(functions):
break
results.append(pool.apply_async(functions[i + j], args = args[i + j]))
pool.close()
pool.join()
map(lambda x: x.get(), results)
else:
for i in xrange(len(functions)):
results.append(functions[i](*args[i]))
return results
此实现细分了批量中的函数列表。每个批量维度等于实际CPU的数量。问题是它实际上等待每个函数完成,然后再次启动另一大部分进程 我不想要这种行为,因为如果批量中的函数非常慢,那么另一个cpus会在开始新进程之前等待它完成。
什么是正确的方法?
答案 0 :(得分:2)
您似乎过度复杂了。无论您为其提供多少工作项,multiprocessing.Pool
将始终以您告诉它的流程数运行。因此,如果您创建Pool(CPUS)
,Pool
将永远不会同时运行超过CPUS
个任务,即使您提供了CPUS * 100
个任务。所以它满足了你的要求,即在没有你做任何特殊工作的情况下,永远不要运行比拥有CPU更多的任务。因此,您可以遍历整个方法和参数列表,并在其上调用apply_async
,而不必担心批量调用。 Pool
将执行所有任务,但一次只执行CPUS
个任务:
def parallelize(methods, args):
results = []
if CPUS > 1:
pool = Pool(CPUS)
for method, arg in zip(methods, args):
results.append(pool.apply_async(method, args=arg))
pool.close()
pool.join()
out = map(lambda x: x.get(), results)
else:
for i in xrange(len(methods)):
results.append(methods[i](*args[i]))
return results