这可能是一个非常愚蠢的问题,但我没有找到任何可以完美回答这个问题的文档。我正在尝试熟悉 python 上的multiprocessing
库,尝试使用multiprocessing.Pool
滑翔伞任务。 我通过以下方式启动池中的进程数:Pool(processes=nmbr_of_processes)
. 问题是我不明白这个数量的过程是如何减少工作时间的。我写了一个脚本来评估它。
def test_operation(y):
sum = 0
for x in range(1000):
sum += y*x
def main():
time1 = time.time()
p = mp.Pool(processes=2)
result = p.map(test_operation, range(100000))
p.close()
p.join()
print('Parallel tooks {} seconds'.format(time.time() - time1))
final = list()
time2 = time.time()
for y in range(100000):
final.append(test_operation(y))
print('Serial tooks {} seconds'.format(time.time() - time2))
问题是,当我使用 2 个进程时mp.Pool(processes=2)
我通常会得到:
Parallel took 5.162384271621704 seconds
Serial took 9.853888034820557 seconds
如果我使用更多流程,例如p = mp.Pool(processes=4)
我得到:
Parallel took 6.404058218002319 seconds
Serial took 9.667300701141357 seconds
我正在开发MacMini DualCore i7 3Ghz。我知道我不能将工作持续时间减少到连续工作所花费时间的一半。但我不明白为什么与具有 2 个进程的工作相比,添加更多流程会增加工作时间。如果根据CPU启动的最佳进程数,那会是什么?
这里要注意的是,这适用于 CPU 密集型任务;您的代码占用大量 CPU 资源。首先要做的是检查你有多少个理论内核:
import multiprocessing as mp
print(mp.cpu_count())
对于像这样的 CPU 密集型任务,创建一个工作线程多于理论内核的池没有任何好处。如果不指定Pool
的大小,它将默认回此数字。但是,这忽略了其他一些东西;您的代码不是操作系统必须运行的唯一内容。
如果您启动与理论内核一样多的进程,系统别无选择,只能定期中断您的进程以保持运行,因此您可能会受到性能影响。你不能垄断所有的核心。这里的一般经验法则是池大小为cpu_count() - 1
,这使得操作系统可以在其他进程上自由使用核心。
我很惊讶地发现我找到的其他答案没有提到这个一般规则;它似乎仅限于评论等。但是,您自己的测试表明它适用于您的案例中的性能,因此是确定池大小的合理启发式方法。