Python中与内联函数或宏等价的实现
我刚刚意识到,执行
x.real*x.real+x.imag*x.imag
的速度是执行
abs(x)**2
的速度快三倍,其中 x 是一个包含复数的 numpy 数组。为了提高代码的可读性,我可以定义一个函数,比如
def abs2(x):
return x.real*x.real+x.imag*x.imag
这个函数的速度仍然比 abs(x)**2 快很多,但这样做的代价是需要调用这个函数。有没有办法像在 C 语言中使用宏或者 inline 关键字那样,把这个函数内联?
7 个回答
我同意大家的看法,这种优化在CPython上只会让你感到痛苦。如果你在意性能,应该考虑使用PyPy(不过我们的NumPy可能还不够完善,没法用)。不过我想说的是,在PyPy上你确实可以关注这些优化,虽然像之前提到的,这个特定的优化PyPy会自动处理。但如果你对PyPy很了解,你真的可以调整你的代码,让PyPy生成你想要的汇编代码,不过其实你几乎不需要这样做。
虽然这不是提问者想要的,但还是挺接近的:
Inliner 是一个可以把 Python 函数调用内联的工具。这是对这篇博客的概念验证。
from inliner import inline @inline def add_stuff(x, y): return x + y def add_lots_of_numbers(): results = [] for i in xrange(10): results.append(add_stuff(i, i+1))
在上面的代码中,add_lots_of_numbers 函数被转换成了这样:
def add_lots_of_numbers(): results = [] for i in xrange(10): results.append(i + i + 1)
另外,对这个问题感兴趣的人,如果想了解在 CPython 中实现这样的优化器的复杂性,也可以看看:
我能像在C语言中使用宏或者inline关键字那样,把这样的函数内联吗?
不可以。在执行到这个特定指令之前,Python解释器甚至不知道有没有这样的函数,更别提它具体是干什么的了。
正如评论中提到的,PyPy会自动进行内联(不过上面的说法依然成立——它“只是”在运行时生成一个优化过的版本,利用这个版本,但当这个版本失效时又会退出),不过在这个特定情况下并没有帮助,因为在PyPy上实现NumPy的工作才刚刚开始,至今还没有达到测试阶段。但总的来说:在Python中,不用担心这种层面的优化。要么实现者自己优化,要么就不优化,这不是你的责任。