在Python中加速数学计算

3

我目前正在尝试优化一个程序。主要瓶颈实际上是针对numpy数组进行的相当简单的一行计算,例如:

(p-1) * c**(p-1)/(v_dt+c)**p

这个计算在我的机器上大约需要1/50秒的时间

(使用timeit进行计时:1000次循环,3次取最佳结果:每个循环花费21.8毫秒)

问题是,这个小函数(我还有几个类似的函数)在一个循环中被调用了约500次,在变量循环大约100次左右。因此,这一行代码突然增加了20分钟的运行时间。

有哪些最好的方法可以加速Python中的数学计算?Python技巧可以做多少?我已经研究过c_types和可能的Cython,但我应该如何使用它们?我需要为这些瓶颈函数编写c代码,还是可以使用已经编译好的库(我没有使用c的经验)?

非常感谢。

编辑: 我忘了提到,我已经在寻找循环的并行化选项,但仍希望直接加速这些瓶颈函数,因为这是性能关键代码。


4
在深入优化前,我建议先寻找宏观优化:您确定程序需要循环那么多次吗?嵌套循环是否需要每次执行此计算?有些计算能否被保存以供稍后引用? - TigerhawkT3
3
也许在这里尝试一下:http://codereview.stackexchange.com/ - Mihai
5
请注意,代码审查需要完整的、可运行的代码才能接受问题。这段代码是“示例代码”,可能不会被很好地接受。如果您在发布整个情境(包括用例)的话,我们非常欢迎。 :) - Der Kommissar
2
指数运算一般很耗费计算资源。不要使用(p-1) * c**(p-1)/(v_dt+c)**p,可以尝试使用(p-1) * (c/(v_dt+c))**p / c来提高运算速度。 - user447688
3
在没有给出代码行的任何上下文情况下,很难建议优化措施。其中哪些参数会因为每次调用而有所不同?你可以预先计算一些表达式。你用结果做什么?我们并不知道,可能有方法可以完全跳过中间数组的计算。 - ali_m
显示剩余6条评论
2个回答

0

我认为这篇文章非常惊人和有趣。

简要概述:

  • 最有趣的是,对于小数组(<150个元素),他发现Python实际上比Numpy更快。我猜是因为它的开销更小。

  • 您还可以在C++中编写内部循环,然后通过Python调用它。

  • 您可以尝试使用Numba,这似乎是一种非常简单的加速简单计算的方法。

最后,通过重新组织函数,使向量部分仅被访问一次,我已经获得了加速。

例如,而不是(a * (b * (c * vector))),它执行3个向量乘法,您可以执行(a * b * c) * vector,它只执行一次。


0
在我的初步测试中,这看起来并不是很昂贵:
In [65]: p,c =2.,2.
In [66]: v_dt=np.ones(500)*1.5
In [67]: x=(p-1)*c**(p-1)/(v_dt+c)**p
In [68]: timeit x=(p-1)*c**(p-1)/(v_dt+c)**p
10000 loops, best of 3: 23.5 µs per loop

有一点贵,因为使用了不同的pc

In [77]: p,c =2.123,1.324
In [78]: timeit x=(p-1)*c**(p-1)/(v_dt+c)**p
10000 loops, best of 3: 95.9 µs per loop

大多数时间都花在向量的指数运算上:

In [82]: %timeit v_dt**p
10000 loops, best of 3: 75.5 µs per loop

(这是一台Windows7老式Centron笔记本电脑)。

这不是cython或其他自行编译的代码可以更好地完成的计算类型。numpy已经调整为高效执行此类数学运算。

我认为你需要看到更大的画面。为什么需要如此频繁地调用它?您能否使用更大的数组少调用几次?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接