2011-11-10 216 views
2

我有一个用Python编写的项目,可以处理大量的数据。 我想加快执行时间。如何加快Python的执行速度?

在简单的话,让我们说我有这样的样品完全优化代码:

def foo(x): 
    doSomething 

main(): 
    for i in range(1,10000000): 
     foo(i) 

是否有某种方式来加速这个?例如通过使用多处理或其他的东西? 最重要的是,它值得吗?

感谢您的回复。我想我会尝试多处理的路线。有人可以给我一个指导或帮助我的例子吗?

+3

你真的应该使用'的xrange'代替'range' - 否则,你把所有的“数据”的存储只是遍历它。 – ThiefMaster

+1

持有onx的2.x,而不是3.x ... – glglgl

回答

7

唯一的真实知道的方法是配置和测量。你的代码可以做任何事情。 “doSomething”可能是time.sleep(10),在这种情况下,分叉10000000进程会使整个程序在大约10秒内运行(忽略分支开销和产生的减速)。

使用http://docs.python.org/library/profile.html并检查瓶颈位置,看看您是否可以使用更好的编码来优化“完全优化”程序。如果它已经够快了,停下来。

然后,根据是CPU还是I/O绑定以及硬件,您可能想尝试多处理或线程化。如果您的问题可以被分解,您也可以尝试分发到多台机器,并做一些地图/减少类型的事情。

+0

好的谢谢你的回复。那么,我的程序只是循环大量的数据,所以我不认为更多的优化会提高性能。 所以我的问题是:使用多处理我将获得多少速度? 想象一下,我的项目可以概括为一百万个单元格阵列中的循环。 对不起英语.. :) – blueSurfer

+0

那么,你可以将它分成100个相同大小的部分,并使用一个工作池来处理每个部分,然后加入结果。 –

3

您可以使用内置JIT编译器的PyPy解释器,它可能实际上改善了像这样的循环的性能。这里是一个link,它解释了PyPy解释器提供的超过常规CPython的一些加速功能。

或者您可以使用Cython来编写代码,该代码允许python中的本地c扩展。巨大块的numpy是这样写的,以获得良好的加速。

或者你可能忘记使用python,只是写在ASM。当然,这会很难做到,但是当你看到你的程序运行速度比所有人都快1%时?你会很开心,你走得更远。

+0

提PyPy +1。另外,我很确定在组装中重写它会给你提供超过1%的提升。 :) –

+1

是的,但任何那个关于优化的肛门都可以用闪光和安全胶水坐在角落里。 –

+0

它*有可能以另一种方式。 –

2

除了已经说过的,你可以看看cython。但是,在你做之前。此外,pypy可能值得一试。不应该有任何工作需要使其工作。

+1

这是怎么得到upvoted甚至没有解释什么pypy和cython? –

+0

他提供了足够的链接,尽管你的回答中的总结会更好。 –

9

要回答你最后一个问题,如果你的表现有问题,那就值得。这是唯一的标准,真的。

至于如何:

如果你的算法是缓慢的,因为它的计算量很大,考虑重写它作为C extension,或使用Cython,这将让你写在Python式的语言快速扩展。此外,PyPy正在变得越来越快,并且可能只是能够不加修改地运行你的代码。

如果代码在计算上并不昂贵,但它只是循环了大量的数据,可能会使用多处理来分解代码,因此它可以并行完成。

最后,如果这是某种基本数据溅射任务,请考虑使用快速数据存储。所有主要的关系数据库都在wazoo上进行了优化,您可能会发现只需让数据库为您完成任务,就可以加快您的任务速度。您甚至可以将其塑形以适合Redis商店,该商店可以出色地汇总大数据集。

+0

Redis是一款非常棒的工具 –

0

如果可以并行处理任务,则可以使用multiprocessing模块调查使用进程池,并将作业分布在子进程之间。

0

这真的取决于你的应用程序,但是如果doSomething可以很好地进行线程化(例如有很多沉重的C代码),那么你可能会感兴趣产生多个线程来完成这项工作。通常的模式是这样的:

def worker(): 
    while True: 
     item = q.get() 
     do_work(item) 
     q.task_done() 

q = Queue() 
for i in range(num_worker_threads): 
    t = Thread(target=worker) 
    t.daemon = True 
    t.start() 

for item in source(): 
    q.put(item) 

q.join()  # block until all tasks are done