Python的编码快速而简单,但在进行密集的数字运算时可能会很慢。将代码翻译成Cython可能会有帮助,但在大多数情况下需要进行一些试验和错误,以达到最佳效果。Cython的教程包含了很多信息,但对于像用Cython进行优化这样的迭代工作流程,看到它 "现场 "完成往往很有用。
出于这个原因,我决定录制一些截屏,展示这个迭代优化过程,使用一个Ising模型,作为一个应用实例。
何时使用Cython¶
在播放视频之前,我想先说说什么时候以及为什么会选择Cython。
对于科学的Python代码,在转向Cython之前,我建议尽可能多地使用矢量化。矢量化包括明智地使用NumPy、SciPy、Pandas和其他库中的内置例程来减少代码中显式for-loops的数量。它在很多情况下都能很好地工作,而且在运行你的代码时不需要任何特殊的编译步骤。请看我在PyCon 2015的演讲《失去你的循环》,了解这种方法的介绍。
当一个问题不能用标准的矢量化方法轻易解决时,Cython是一个不错的选择。Cython提供了Python和C代码之间的桥梁,并且相当成熟和可靠:它构成了PyData/Scientific Python生态系统的大部分基础(例如,Cython在NumPy、SciPy、Pandas、Scikit-Learn和许多其他软件包中被大量使用)。
其他优化Python代码的方法也有,但我倾向于不像Cython那样经常使用它们。
PyPy项目是Python的另一种实现,它避免了默认CPython实现的慢速循环。虽然它很有前途,但目前它不支持许多核心科学软件包,所以不是科学代码的最佳选择(尽管这一点已经在改变)。
Numba是一个Python-to-LLVM转换器,通过给Python函数添加一个简单的编译装饰器,通常可以使你的Python速度提高100倍。关于Numba用于本笔记本中的代码的例子,见Matthew Rocklin的文章。虽然它很方便,但Numba还不支持所有的Python结构,而且当最直接的方法失败时,可能很难优化。
视频¶
最后,这里有使用Cython优化Ising模型的演示。
在[1]中。
from
第1部分¶
在第一部分中,我写了一个在Python中演化Ising模型的函数,以及一些可视化演化结果的工具。
在[2]中。
YouTubeVideo
Out[2]:
第2部分¶
在第二部分中,我通过Cython优化这个函数的过程。
在[3]中。
YouTubeVideo
Out[3]:
代码¶
下面你可以看到我在这两个视频中写的代码。
1.简单的Python Ising模型¶。
显示一个Ising字段¶。
In[4]:
import
Out[4]:
array([[ 1, -1, -1, 1, -1, -1, 1, -1, 1, 1],
[ 1, -1, 1, -1, -1, 1, -1, -1, -1, -1],
[-1, 1, 1, 1, -1, -1, 1, 1, 1, -1],
[ 1, -1, -1, 1, -1, 1, -1, 1, 1, -1],
[-1, 1, -1, -1, -1, 1, -1, -1, -1, -1],
[-1, 1, 1, -1, 1, -1, 1, 1, -1, -1],
[ 1, -1, 1, -1, 1, -1, -1, 1, 1, -1],
[-1, 1, -1, -1, 1, -1, -1, -1, -1, -1],
[ 1, -1, -1, -1, 1, 1, -1, 1, -1, 1],
[ 1, 1, 1, -1, 1, -1, 1, 1, -1, -1]])
在[5]中。
# pip install pillow
Out[5]:
实现Ising模型¶。
在[6]中。
def
在[7]中。
display_spin_field
输出[7]:
为Ising序列制作动画¶。
注意,这需要一个活的内核,所以不会出现在博客或其他静态渲染上。
在[8]中。
from
在[9]中。
images
结果将看起来像这样。
2.使用Cython来加快速度¶。
在[10]中。
%
在[11]中。
%%
对结果进行计时¶。
在[12]中。
field
317 ms ± 10.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
2.64 ms ± 132 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
实现结果的可视化¶。
(请注意,下面的代码需要一个实时的内核,而不会在静态的渲染中显示,如博客文章)。
在[13]中。
images
结果将看起来像这样。