Python高性能编程四:Python编译成C

类型检查有助于代码更快运行

Python 是动态类型的——一个变量能够引用任何类型的对象,并且任意代码行都能够改变被引用对象的类型。这使得虚拟机难以在机器码层面优化代码的运行方式,因为它不知道哪种基础数据类型会用于将来的运算。让代码保持泛型就会让代码运行更慢。

在下面的例子中,v 或是一个浮点数,或是一对代表复数的浮点数。两个条件会先后在相同循环的不同位置发生,或者在相关代码的串行区域发生:

abs 函数会根据底层数据类型来以不同方式工作。对一个整数或浮点数来说,abs只是简单地把负值转换为正值来作为结果。对复数来说,abs 涉及对分量的平方和开平方根。

还是复数的例子,它的机器码涉及更多的指令并且会运行得更久。在对一个变量调用abs 之前,Python 首先不得不查看变量的类型,接着决定调用哪个函数版本——当做出很多重复调用的时候,这个开销会累积。

在CPU 密集型的代码区域内部,不改变变量类型的情况很常见。这就给了我们一个机会来做静态编译和加快代码运行。

使用Cython编译纯Python版本

一个扩展编译模块的简单方法涉及:

  • 调用它的Python代码(如julia1.py,构建输入列表并调用计算函数)。
  • 在一个新的.pyx文件中要被编译的函数(cythonfn.pyx)。
  • 一个setup.py,包含了调用Cython来制作扩展模块的指令(运行setup.py的结果就是获得一个能够被导入的模块)。

使用这个方法,setup.py 脚本调用Cython 把.pyx 文件编译成一个编译模块。在类UNIX 系统上,编译模块可能会是一个.so 文件;在Windows 上应该是一个.pyd(类DLL 的Python 库)。julia1.py:

#导入新编译模块到主代码中
import calculate # as defined in setup.py

def calc_pure_python(desired_width, max_iterations):
start_time = time.time()
output = calculate.calculate_z(max_iterations, zs, cs)
end_time = time.time()
secs = end_time - start_time
print("Took", secs, "seconds")
在cythonfn.pyx(可以从.py重命名)中为Cython的setup.py准备的未改动过的纯Python代码:
#cythonfn.pyx
def calculate_z_serial_purepython(maxiter, zs, cs):
output = [0] * len(zs)
for i in range(len(zs)):
n = 0
z = zs[i]
c = cs[i]
while n < maxiter and abs(z) < 2:
z = z * z + c
n += 1
output[i] = n
return output

<< · Back Index ·>>

发表回复

相关推荐

证券账户销号后的严重后果吗?

这个没有什么严重后果,证券账户销号是您不想用了,或者是想更换券商了,把原来的账户注销。

· 21秒前

你真的對圖像格式瞭解麼?

圖像是人類視覺的基礎,是自然景物的客觀反映,是人類認識世界和人類本身的重要源泉。“圖”是物體反射或透射光的分佈,“像“是...

· 1分钟前

丰富故事背景的衍生电影——《猎魔人:狼之噩梦》

​ 今天聊聊美国电影《猎魔人:狼之噩梦》。 片名The Witcher: Nightmare of the Wolf (2021),别名巫师:狼之噩梦。 《猎 ...

· 1分钟前

房地產政策由嚴到松:認房又認貸、認房不認貸、認貸不認房、不認房不認貸

近日在北、上、廣、深都相繼宣佈“認房不認貸”的政策後,各省也先後接龍官宣。咱們都知道這是放松房地產的政策,出瞭政策,願...

· 2分钟前

論文中的不足之處怎麼寫?

畢業論文結論部分一般分為三個部分:第一部分是發現,這一部分的內容是講通過一系列的研究我發現瞭什麼。第二部分叫做不足,...

· 2分钟前