我有一个python脚本,作为进化优化算法的一部分,我对偏导数进行了数千次计算。我做了一个逐行的概要,这个偏导数计算占用了大部分的运行时间。我使用scipy.optimize.approx_fprime来计算偏导数,并尝试用Cython语言重写它,但没有成功。
逐行配置文件如下所示。我的scipy.optimize.approx_fprime的cythonized版本被简单地称为approx_fprime。
Line # Hits Time Per Hit % Time Line Contents
==============================================================
84 @profile
100 1500 14889652 9926.4 25.3 df1 = approx_fprime(inp_nom,evaluate1,epsilon)
101 1500 14939889 9959.9 25.4 df2 = scipy.optimize.approx_fprime(inp_upp,evaluate1,epsilon)下面是我的cython文件。
import numpy as np
cimport numpy as np
cimport cython
@cython.boundscheck(False) # turn of bounds-checking for entire function
def approx_fprime(np.ndarray xk, f, double epsilon, *args):
# From scipy.optimize.approx_fprime
f0 = f(*((xk,) + args))
cdef np.ndarray grad = np.zeros((len(xk),), float)
cdef np.ndarray ei = np.zeros((len(xk),), float)
cdef np.ndarray d = epsilon * ei
for k in xrange(len(xk)):
ei[k] = 1.0
grad[k] = (f(*((xk + d,) + args)) - f0) / d[k]
ei[k] = 0.0
return grad我已经尝试放入所有相关的类型声明,并确保它能很好地与numpy配合使用。然而,正如他们所说,最终的证据在布丁中。这个版本并不比scipy版本快多少。该函数只有几个变量,所以它不是一个巨大的计算,并且在一次迭代中可能只有增量改进的空间。然而,这个函数会被反复调用,因为这是在进化优化算法中使用的,所以我期望/希望成倍增加的性能收益会有很大的回报。
一位cython专家可以看一看这段代码,并帮我找出我是在正确的轨道上,还是这只是一个愚蠢的差事?
谢谢!
发布于 2014-11-12 16:29:01
首先要注意的是,优化代码就是找到代码中的瓶颈。通常只有很少的函数、循环等占用了大部分时间。这些都是进行优化的合适候选者。所以最重要的事情是:使用分析器评估代码性能。
优化python代码的第一件事是逐行检查代码,并检查是否创建了新对象。这是因为与简单的算术相比,创建对象的开销非常大。经验法则:尽可能避免创建对象。但请确保您不会在时间关键型循环中创建任何新对象。
看看f*((xk + d,) + args)吧。这是非常好的python代码--但是如果你需要高性能的话就不合适了。它将在循环的每一步中创建一个新的参数元组。以不创建任何对象的方式重写它可能会给您带来巨大的性能提升。
下一步是开始静态输入。确保键入循环中使用的所有内容。输入k可能会给您带来很多好处。
之后,您可以尝试通过取消设置boundscheck等来进一步优化。
最重要的是:迭代地进行优化,并通过分析代码来检查您的性能增益。大多数情况下,很难看出代码中真正的瓶颈是什么。分析将给您一些提示:如果优化没有给您带来太多好处,那么您可能错过了瓶颈。
https://stackoverflow.com/questions/26877141
复制相似问题