使用多核处理器与python进行粗粒度并行化

时间:2011-08-26 14:55:59

标签: python multithreading parallel-processing multicore

我有一个python程序,它调用外部程序(foo)。这个外部程序需要运行几次。确切的次数(num_pros)是可变的,取决于输入。 因为这个外部程序是我的Python程序中最耗时的部分,所以我希望利用多个核心处理器同时运行多个外部程序实例。

我提出了以下解决方案,考虑到num_pros是先验未知的,并且解决方案应该适用于任意数量的核心。

cores=2
proc_list=[]
for i in range(0,num_pros):
    proc=Popen(['foo'], stdin=PIPE)
    proc_list.append(proc)
    if i%cores == cores-1: 
        for process in proc_list:
            process.wait()

我有两个问题:

有更好的(更高效或pythonic)解决方案吗?

此代码仅在核心为真时才减少执行时间。这是硬件问题吗?或者可以使用python修复的东西?

为澄清第二个问题,让我举一个例子。 在我的笔记本(运行linux)comnand'cat / proc / cpuinfo | grep处理器| wc -l'表示存在4个处理器,如果我在我的代码中使用cores = 2我得到的结果是一半的时间(如预期的那样),但是当使用cores = 3或cores = 4时,我得到的结果与使用时相同核= 2。我有一个Intel核心I3(2核和4个线程),因此我猜问题是只有2个核是真实的(我测试其他计算机/处理器中的代码我得到相同的结果,只有真正的核似乎是有用的)。

2 个答案:

答案 0 :(得分:0)

我认为multiprocessing更适用于您想要修剪的工作是在python中的情况,而不是完全不同的过程。这都是关于使用fork并将内容从python进程传递给python进程,所以我认为它不适合你。

在当前的实现中,一旦产生了最大子进程数,您的代码就会阻止新子进程的生成,直到 all 当前批处理完成,因为Popen.wait()阻塞直到< em>特定的子流程完成。

我认为你想要的是os.wait()。我通过保持pid映射的subprocess.Popen个实例的映射来完成very similar的操作。只需旋转最大数量的子流程,然后让os.wait()告诉您其中一个子流程何时完成。 os.wait()将为您提供接下来完成的Popen个实例的pid,您可以使用它来为 子进程执行任何剩余的清理。然后让你的代码启动下一个子进程。

答案 1 :(得分:0)

简单方法:采用N核系统,执行一些基准测试运行,以确定应用程序需要以最高效率执行的进程数。它可能是N,N + 1或N + 2个过程(例如,对于通常的软件构建make运行,文档通常建议将-j设置为N + 1)。然后,对于生产运行,只需向用户或操作系统询问物理内核(而不是线程)的数量,并生成N或N + 1或任何进程。

更复杂,更酷,并且不一定更好的方法:如果您可以测量已完成工作单元的吞吐量,您可以尝试在不知道/检测cpu /核心数量的情况下即时调整进程数量线程 - 如果你愿意,可以像TCP窗口大小。从2个进程的目标开始,当第一个进程结束时测量吞吐量并且去目标+ = 1(即,将总数带到3个进程)。测量,冲洗,重复。只要总吞吐量持续上升,就保持递增,并在下降时递减。在混合中抛出一些滞后现象,并确保配置一个合理的上限。

关于你的笔记本示例,是的,这是一个多线程CPU,多个线程将比其他线程更有益于某些工作负载,你的是不会从中受益的那个:)