我编写了一个获取地理空间数据的算法,并执行了许多步骤。输入的数据是一个多边形的形状文件和一个大的栅格研究区域(约1.5亿像素)的协变量光栅。这些步骤如下:
整个过程需要多次迭代(例如100次),但每次迭代目前需要一个多小时的时间来进行串联处理。对于每一次迭代,最耗时的部分是步骤4和第5步,因为目标网格太大了,所以我一直在一次处理一个块(例如1000行)。
我有一个6核CPU,内存为32 Gb,因此在每次迭代中,我尝试使用Python的multiprocessing
模块和一个Pool
对象同时处理多个块(步骤4和步骤5),然后使用调用全局输出写入函数的回调函数将输出(预测)写入到常见的输出网格集。这似乎是可行的,但并不比串联处理每个块更快(实际上,可能更慢)。
所以我的问题是,有没有更有效的方法来做到这一点?我对多处理模块的Queue
类感兴趣,但我不太确定它是如何工作的。例如,我想知道是否有一个执行步骤4和步骤5的队列,然后将结果传递给另一个执行步骤6的队列,或者这是为了什么队列?
如有任何指示,将不胜感激。
发布于 2012-06-20 14:24:49
Python的多处理功能的当前状态对于CPU绑定处理不是很好。我恐怕要告诉您,使用multiprocessing
模块无法使其运行得更快,问题也不在于您对multiprocessing
的使用。
真正的问题是Python仍然受GlobalInterpreterLock(GIL)规则的约束(我强烈建议使用幻灯片)。有一些令人兴奋的理论和实验进展围绕吉尔工作。Python3.2事件包含一个新的GIL,它解决了一些问题,但引入了其他问题。
目前,使用单个串行线程执行多个Python进程要比尝试在一个进程中运行多个线程要快。这将使您避免在线程之间获取GIL的问题(通过有效地拥有更多的GIL)。但是,只有在您的Python进程之间的IPC开销没有超过处理的好处时,这才是有益的。
Eli写了一篇像样的概述条款,讲述了他试图通过多处理使CPU绑定进程运行得更快的经验。
值得注意的是,佩普371希望通过引入multiprocessing
模块(以前是一种名为pyProcessing
的非标准包)而“绕开”GIL。然而,GIL在Python解释器中仍然扮演着太大的角色,无法很好地处理CPU绑定算法。许多不同的人都致力于移除/重写GIL,但是没有什么东西能使它成为Python版本。
发布于 2012-06-15 22:31:13
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秒。它应该很容易修改它的更多。也许这将有助于调试当前代码,并确保您确实生成了多个独立的进程。
如果由于内存限制必须共享数据,那么我建议如下:http://docs.python.org/library/multiprocessing.html#sharing-state-between-processes
发布于 2012-06-20 08:32:33
因为python并不真正意味着要做大量的数字技巧,所以我通常开始将python程序的关键时间部分转换为C/C++,并大大加快速度。
而且,python多线程也不是很好。Python一直在使用全局信号量来处理各种事情。因此,即使您使用python提供的线程,事情也不会变得更快。线程对于应用程序很有用,在应用程序中,线程通常会等待IO之类的东西。
在生成C模块时,您可以在处理数据时手动释放全局信号量(当然,不再访问python值)。
它需要一些使用C API的练习,但它的结构清晰,使用起来比Java原生API容易得多。
请参阅python文档中的“扩展和嵌入”。
这种方法可以使时间关键部分在C/C++中运行,而速度较慢的部分在python中运行。
https://stackoverflow.com/questions/10843240
复制相似问题