Python多处理设计

2024-05-06 13:34:42 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经编写了一个算法,它可以获取地理空间数据并执行许多步骤。输入数据是大型光栅研究区域(约1.5亿像素)的多边形和协变量光栅的形状文件。步骤如下:

  1. 形状文件多边形内的采样点
  2. 对于每个采样点,从协变量光栅中提取值
  3. 对采样点建立预测模型
  4. 提取目标网格点的协变量
  5. 对目标网格应用预测模型
  6. 将预测写入一组输出网格

整个过程需要迭代很多次(比如100次),但是每次迭代都需要一个多小时。对于每个迭代,最耗时的部分是第4步和第5步。因为目标网格太大了,我一次只处理一个块(比如1000行)。在

我有一个6核CPU和32GB RAM,因此在每次迭代中,我都尝试使用Python的multiprocessing模块和Pool对象同时处理多个块(步骤4和5),然后使用调用全局输出写入函数的回调函数将输出(预测)写入公共输出网格集。这似乎是可行的,但并不比处理串联中的每个块快(实际上,它可能慢)。在

所以我的问题是,有没有一种更有效的方法?我对多处理模块的Queue类感兴趣,但我不太确定它是如何工作的。例如,我想知道让一个执行步骤4和步骤5的队列将结果传递给执行步骤6的另一个队列是否更有效。或者这就是排队的目的?在

如有任何建议,我们将不胜感激。在


Tags: 模块文件数据函数模型算法网格目标
3条回答

Python的多处理能力的当前状态对于CPU受限的处理来说不是很好。我害怕告诉您,使用multiprocessing模块无法使它运行得更快,您使用multiprocessing也不是问题所在。在

真正的问题是Python仍然受GlobalInterpreterLock(GIL)规则的约束(我强烈建议使用slides)。关于GIL的工作,已经有了一些令人兴奋的理论和experimental advances。python3.2事件包含一个新的GIL,它解决了一些问题,但引入了其他问题。在

现在,用一个串行线程执行多个Python进程比在一个进程中运行多个线程要快。这将允许您避免在线程之间获取GIL的问题(通过有效地拥有更多GIL)。但是,只有在Python进程之间的IPC开销没有掩盖处理的好处时,这才是有益的。在

Eli Bendersky写了一篇不错的overview article关于他尝试用多处理使CPU绑定的进程运行更快的经验。在

值得注意的是,PEP 371希望通过引入multiprocessing模块(以前是一个名为pyProcessing的非标准包装)来“绕过”GIL。然而,GIL似乎仍然在Python解释器中扮演了太大的角色,使得它不能很好地与CPU绑定的算法一起工作。许多不同的人都致力于删除/重写GIL,但是没有任何东西能让它成为Python版本。在

因为Python并不意味着要进行密集的数字压缩,所以我通常开始将Python程序的关键部分转换成C/C++,并加快速度。在

而且,python的多线程处理也不是很好。Python一直在为各种事情使用全局信号量。因此,即使使用python提供的线程,事情也不会变得更快。线程对于应用程序很有用,在这些应用程序中,线程通常会等待IO之类的东西。在

在制作C模块时,可以在处理数据时手动释放全局信号量(当然,这样就不再访问python值了)。在

使用capi需要一些练习,但是它的结构清晰,而且比Java原生API更容易使用。在

请参见python文档中的“扩展和嵌入”。在

这种方式可以在C/C++中制作时间关键部件,而在Python中用更快速的编程工作更慢的部分…在

中的一些多处理示例python.org网站我不太清楚,很容易从一个有缺陷的设计开始。下面是一个简单化的例子,让我开始一个项目:

import os, time, random, multiprocessing
def busyfunc(runseconds):
    starttime = int(time.clock())
    while 1:
        for randcount in range(0,100):
            testnum = random.randint(1, 10000000)
            newnum = testnum / 3.256
        newtime = int(time.clock())
        if newtime - starttime > runseconds:
            return

def main(arg):
    print 'arg from init:', arg
    print "I am " + multiprocessing.current_process().name

    busyfunc(15)

if __name__ == '__main__':

    p = multiprocessing.Process(name = "One", target=main, args=('passed_arg1',))
    p.start()

    p = multiprocessing.Process(name = "Two", target=main, args=('passed_arg2',))
    p.start()

    p = multiprocessing.Process(name = "Three", target=main, args=('passed_arg3',))
    p.start()

    time.sleep(5)

这将使3个处理器运行15秒。它应该很容易修改为更多。也许这将有助于调试您当前的代码,并确保您真正生成多个独立的进程。在

如果由于RAM限制而必须共享数据,那么我建议您: http://docs.python.org/library/multiprocessing.html#sharing-state-between-processes

相关问题 更多 >