提速30倍!这个加速包让Python代码飞起来

提速30倍!这个加速包让Python代码飞起来插图

大数据文摘出品

编译:啤酒泡泡、宁静

Python是社区里最受喜爱的编程语言!它是目前为止最易使用的语言,因为它的代码短小精悍,符合人们的思维方式,也符合人们的阅读习惯。

但是你会经常听到有人吐槽Python,尤其是有些C语言的大牛吐槽Python速度慢。

他们说得没错,相比其他高级程序设计语言,如C语言来说,Python确实速度很慢,这主要是因为C语言更面向计算机底层,像一些单片机、电路板的设计都使用C语言,C语言和汇编语言之间的转换也更快,但是“every coin has two sides”,没有完美无缺的编程语言,C语言也有着其诸如代码量大、面向过程的一些缺点,如何让Python兼顾C语言速度方面的优点呢?

一个很形象的例子,就像上图展示的一样,赛车手需要兼顾汽车的发动引擎的内耗磨损,也要兼顾赛车的运行速度,那么,如何在两者之间取得平衡呢?

其实有很多可以提高运行速度的办法,比如:

  • 利用多进程库来使用所有的CPU内核;

  • 如果你正在使用NumPy,Pandas,或是Scikit-Learn库,那么可以使用Rapids来提高GPU的处理速度。

但是这只针对你的任务可以并行的情况,例如数据预处理、矩阵操作等,上述办法都很棒,可是如果你只使用纯Python语言,那该怎么办呢?再比如,你必须使用一个很大的for循环,而且因为数据必须被顺序处理导致你无法使用矩阵,在这种情况下,有没有办法提高Python本身的速度呢?

Cython就是用来加速纯Python代码的。

什么是Cython?

从本质上讲,Cython是Python和C/C++的桥梁。它允许你对Python代码稍作修改,然后把Python代码直接翻译成C语言代码。

你唯一需要修改Python代码的地方就是在每一个变量前面加上它的类型,通常,我们在Python里会这样声明变量:


1
<span class="code-snippet_outer"><span class="code-snippet__attr">x</span> = <span class="code-snippet__number">0.5</span></span>

如果使用Cython,我们会给变量加上它的类型:


1
<span class="code-snippet_outer">cdef <span class="code-snippet__built_in">float</span> x = 0.5</span>

这会告诉Cython,我们的变量是浮点型变量,这和我们在C语言中的操作一样。使用纯Python语言,变量的数据类型在赋值后被自动定义。Cython这种显式的变量声明方法使得Python代码转换成C代码成为可能,因为C语言要求变量的数据类型必须在声明变量时写出来。

使用pip安装Cython只需一行代码:


1
<span class="code-snippet_outer"><span class="code-snippet__attribute">pip</span> install cython</span>

Cython的数据类型

使用Cython时,Cython提供两类类型,一类用于变量,一类用于函数。

对于变量,我们可以这样写(请注意,这些类型都来自C/C++):

  • cdef int a, b, c
  • cdef char *s
  • cdef float x = 0.5 (single precision)
  • cdef double x = 63.4 (double precision)
  • cdef list names
  • cdef dict goals_for_each_play
  • cdef object card_deck

对于函数,我们可以这样写:
  • def – 普通的Python函数,只用Python解释器
  • cdef – Cython专用函数,不能通过纯Python代码使用该函数,必须在Cython内使用
  • cpdef – C语言和Python共用。可以通过C语言或者Python代码使用该函数

有了对Cython的了解,我们可以更进一步,开始加速我们的代码了!

使用Cython提高代码的运行速度

首先,我们建立一个Python代码的基准——使用一个for循环来计算某个数的阶乘。以下是用纯Python语言写的代码:


1
<span class="code-snippet_outer"><span class="code-snippet__function"><span class="code-snippet__keyword">def</span> <span class="code-snippet__title">test</span><span class="code-snippet__params">(x)</span>:</span></span>
1
<span class="code-snippet_outer">    y = <span class="code-snippet__number">1</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">for</span> i <span class="code-snippet__keyword">in</span> range(<span class="code-snippet__number">1</span>, x+<span class="code-snippet__number">1</span>):</span>
1
<span class="code-snippet_outer">        y *= i</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">return</span> y</span>
使用Cython写出的函数和纯Python代码写出的函数很类似,首先,我们要确保Cython代码文件的扩展名是.pyx。然后,我们唯一修改的地方就是在我们已声明的每个变量和函数前加上它们的类型,run_cython.pyx代码如下:


1
<span class="code-snippet_outer"><span class="code-snippet__function">cpdef <span class="code-snippet__keyword">int</span> <span class="code-snippet__title">test</span>(<span class="code-snippet__params"><span class="code-snippet__keyword">int</span> x</span>):</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet_outer">    cdef <span class="code-snippet__keyword">int</span> y</span> = <span class="code-snippet__number">1</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__function">cdef <span class="code-snippet__keyword">int</span> i</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">for</span> i <span class="code-snippet__keyword">in</span> <span class="code-snippet__title">range</span>(<span class="code-snippet__params"><span class="code-snippet__number">1</span>, x+<span class="code-snippet__number">1</span></span>):</span>
1
<span class="code-snippet_outer"><span class="code-snippet_outer">        y *</span>= i</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">return</span> y</span>
请注意,函数前有cpdef,以确保我们可以通过Python调用该函数。同时请注意,for循环里的变量i也有类型信息,你需要设定函数中所有变量的类型,这样C语言编译器才能知道需要使用什么类型!

接下来,创建一个setup.py文件,把Cython代码翻译成C代码:


1
<span class="code-snippet_outer"><span class="code-snippet__keyword">from</span> distutils.core <span class="code-snippet__keyword">import</span> setup</span>
1
<span class="code-snippet_outer"><span class="code-snippet__keyword">from</span> Cython.Build <span class="code-snippet__keyword">import</span> cythonize</span>
1
<span class="code-snippet_outer">setup(ext_modules = cythonize(<span class="code-snippet__string">'run_cython.pyx'</span>))</span>
然后执行汇编过程,在命令行输入如下命令:


1
<span class="code-snippet_outer"><span class="code-snippet__selector-tag">python</span> <span class="code-snippet__selector-tag">setup</span><span class="code-snippet__selector-class">.py</span> <span class="code-snippet__selector-tag">build_ext</span> <span class="code-snippet__selector-tag">--inplace</span></span>

我们的C代码已经被编译了,可以使用了!你可以在文件夹里看见你的Cython代码,你有了所有运行C代码所需要的文件,包括run_cython.c文件,文摘菌在win10系统尝试后文件夹结构如下:
提速30倍!这个加速包让Python代码飞起来插图1
打开run_cython.c后的部分代码(代码有点长,此处只展示开头变量声明和结尾的函数实现)


1
<span class="code-snippet_outer"><span class="code-snippet__comment">/***the beginning part of the code***/</span> </span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">/* Generated by Cython 0.29.13 */</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">/* BEGIN: Cython Metadata</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">{</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">    "distutils": {</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">        "name": "run_cython",</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">        "sources": [</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">            "run_cython.pyx"</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">        ]</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">    },</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">    "module_name": "run_cython"</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">}</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">END: Cython Metadata */</span></span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">define</span> PY_SSIZE_T_CLEAN</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string">"Python.h"</span></span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">ifndef</span> Py_PYTHON_H</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">error</span> Python essay-headers needed to compile C extensions, please install development version of Python.</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">elif</span> PY_VERSION_HEX &lt; 0x02060000 || (0x03000000 &lt;= PY_VERSION_HEX &amp;&amp; PY_VERSION_HEX &lt; 0x03030000)</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">error</span> Cython requires Python 2.6+ or Python 3.3+.</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">else</span></span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">define</span> CYTHON_ABI <span class="code-snippet__meta-string">"0_29_13"</span></span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">define</span> CYTHON_HEX_VERSION 0x001D0DF0</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">define</span> CYTHON_FUTURE_DIVISION 0</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">include</span> <span class="code-snippet__meta-string"><stddef.h></stddef.h></span></span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">ifndef</span> offsetof</span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">define</span> offsetof(type, member) ( (size_t) &amp; ((type*)0) -&gt; member )</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">endif</span></span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">if</span> !defined(WIN32) &amp;&amp; !defined(MS_WINDOWS)</span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">ifndef</span> __stdcall</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">define</span> __stdcall</span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">endif</span></span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">ifndef</span> __cdecl</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">define</span> __cdecl</span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">endif</span></span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">ifndef</span> __fastcall</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">define</span> __fastcall</span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">endif</span></span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">endif</span></span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">ifndef</span> DL_IMP</span></span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer"><span class="code-snippet__comment">/****the end part of the code***/</span></span>
1
<span class="code-snippet_outer"><span class="code-snippet__keyword">static</span> CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {</span>
1
<span class="code-snippet_outer">  Py_ssize_t ival;</span>
1
<span class="code-snippet_outer">  PyObject *x;</span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">if</span> PY_MAJOR_VERSION &lt; 3</span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__keyword">if</span> (likely(PyInt_CheckExact(b))) {</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">if</span> (<span class="code-snippet__keyword">sizeof</span>(Py_ssize_t) &gt;= <span class="code-snippet__keyword">sizeof</span>(<span class="code-snippet__keyword">long</span>))</span>
1
<span class="code-snippet_outer">        <span class="code-snippet__keyword">return</span> PyInt_AS_LONG(b);</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">else</span></span>
1
<span class="code-snippet_outer">        <span class="code-snippet__keyword">return</span> PyInt_AsSsize_t(b);</span>
1
<span class="code-snippet_outer">  }</span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">endif</span></span></span>
1
<span class="code-snippet_outer">  <span class="code-snippet__keyword">if</span> (likely(PyLong_CheckExact(b))) {</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">if</span> CYTHON_USE_PYLONG_INTERNALS</span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">const</span> digit* digits = ((PyLongObject*)b)-&gt;ob_digit;</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">const</span> Py_ssize_t size = Py_SIZE(b);</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">if</span> (likely(__Pyx_sst_abs(size) &lt;= <span class="code-snippet__number">1</span>)) {</span>
1
<span class="code-snippet_outer">        ival = likely(size) ? digits[<span class="code-snippet__number">0</span>] : <span class="code-snippet__number">0</span>;</span>
1
<span class="code-snippet_outer">        <span class="code-snippet__keyword">if</span> (size == <span class="code-snippet__number">-1</span>) ival = -ival;</span>
1
<span class="code-snippet_outer">        <span class="code-snippet__keyword">return</span> ival;</span>
1
<span class="code-snippet_outer">    } <span class="code-snippet__keyword">else</span> {</span>
1
<span class="code-snippet_outer">      <span class="code-snippet__keyword">switch</span> (size) {</span>
1
<span class="code-snippet_outer">         <span class="code-snippet__keyword">case</span> <span class="code-snippet__number">2</span>:</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">if</span> (<span class="code-snippet__number">8</span> * <span class="code-snippet__keyword">sizeof</span>(Py_ssize_t) &gt; <span class="code-snippet__number">2</span> * PyLong_SHIFT) {</span>
1
<span class="code-snippet_outer">             <span class="code-snippet__keyword">return</span> (Py_ssize_t) (((((<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">1</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">0</span>]));</span>
1
<span class="code-snippet_outer">           }</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">break</span>;</span>
1
<span class="code-snippet_outer">         <span class="code-snippet__keyword">case</span> <span class="code-snippet__number">-2</span>:</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">if</span> (<span class="code-snippet__number">8</span> * <span class="code-snippet__keyword">sizeof</span>(Py_ssize_t) &gt; <span class="code-snippet__number">2</span> * PyLong_SHIFT) {</span>
1
<span class="code-snippet_outer">             <span class="code-snippet__keyword">return</span> -(Py_ssize_t) (((((<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">1</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">0</span>]));</span>
1
<span class="code-snippet_outer">           }</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">break</span>;</span>
1
<span class="code-snippet_outer">         <span class="code-snippet__keyword">case</span> <span class="code-snippet__number">3</span>:</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">if</span> (<span class="code-snippet__number">8</span> * <span class="code-snippet__keyword">sizeof</span>(Py_ssize_t) &gt; <span class="code-snippet__number">3</span> * PyLong_SHIFT) {</span>
1
<span class="code-snippet_outer">             <span class="code-snippet__keyword">return</span> (Py_ssize_t) (((((((<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">2</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">1</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">0</span>]));</span>
1
<span class="code-snippet_outer">           }</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">break</span>;</span>
1
<span class="code-snippet_outer">         <span class="code-snippet__keyword">case</span> <span class="code-snippet__number">-3</span>:</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">if</span> (<span class="code-snippet__number">8</span> * <span class="code-snippet__keyword">sizeof</span>(Py_ssize_t) &gt; <span class="code-snippet__number">3</span> * PyLong_SHIFT) {</span>
1
<span class="code-snippet_outer">             <span class="code-snippet__keyword">return</span> -(Py_ssize_t) (((((((<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">2</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">1</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">0</span>]));</span>
1
<span class="code-snippet_outer">           }</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">break</span>;</span>
1
<span class="code-snippet_outer">         <span class="code-snippet__keyword">case</span> <span class="code-snippet__number">4</span>:</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">if</span> (<span class="code-snippet__number">8</span> * <span class="code-snippet__keyword">sizeof</span>(Py_ssize_t) &gt; <span class="code-snippet__number">4</span> * PyLong_SHIFT) {</span>
1
<span class="code-snippet_outer">             <span class="code-snippet__keyword">return</span> (Py_ssize_t) (((((((((<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">3</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">2</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">1</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">0</span>]));</span>
1
<span class="code-snippet_outer">           }</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">break</span>;</span>
1
<span class="code-snippet_outer">         <span class="code-snippet__keyword">case</span> <span class="code-snippet__number">-4</span>:</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">if</span> (<span class="code-snippet__number">8</span> * <span class="code-snippet__keyword">sizeof</span>(Py_ssize_t) &gt; <span class="code-snippet__number">4</span> * PyLong_SHIFT) {</span>
1
<span class="code-snippet_outer">             <span class="code-snippet__keyword">return</span> -(Py_ssize_t) (((((((((<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">3</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">2</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">1</span>]) &lt;&lt; PyLong_SHIFT) | (<span class="code-snippet__keyword">size_t</span>)digits[<span class="code-snippet__number">0</span>]));</span>
1
<span class="code-snippet_outer">           }</span>
1
<span class="code-snippet_outer">           <span class="code-snippet__keyword">break</span>;</span>
1
<span class="code-snippet_outer">      }</span>
1
<span class="code-snippet_outer">    }</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">endif</span></span></span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">return</span> PyLong_AsSsize_t(b);</span>
1
<span class="code-snippet_outer">  }</span>
1
<span class="code-snippet_outer">  x = PyNumber_Index(b);</span>
1
<span class="code-snippet_outer">  <span class="code-snippet__keyword">if</span> (!x) <span class="code-snippet__keyword">return</span> <span class="code-snippet__number">-1</span>;</span>
1
<span class="code-snippet_outer">  ival = PyInt_AsSsize_t(x);</span>
1
<span class="code-snippet_outer">  Py_DECREF(x);</span>
1
<span class="code-snippet_outer">  <span class="code-snippet__keyword">return</span> ival;</span>
1
<span class="code-snippet_outer">}</span>
1
<span class="code-snippet_outer"><span class="code-snippet__keyword">static</span> CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(<span class="code-snippet__keyword">long</span> b) {</span>
1
<span class="code-snippet_outer">  <span class="code-snippet__keyword">return</span> b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False);</span>
1
<span class="code-snippet_outer">}</span>
1
<span class="code-snippet_outer"><span class="code-snippet__keyword">static</span> CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(<span class="code-snippet__keyword">size_t</span> ival) {</span>
1
<span class="code-snippet_outer">    <span class="code-snippet__keyword">return</span> PyInt_FromSize_t(ival);</span>
1
<span class="code-snippet_outer">}</span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer"><span class="code-snippet__meta">#<span class="code-snippet__meta-keyword">endif</span> <span class="code-snippet__comment">/* Py_PYTHON_H</span></span></span>
现在我们可以测试我们全新的、速度超快的C代码了!看看下面的代码,它是比较Python代码和Cython代码速度的测试:


1
<span class="code-snippet_outer">import run_python</span>
1
<span class="code-snippet_outer">import run_cython</span>
1
<span class="code-snippet_outer">import time</span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer">number = 10</span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer">start = time.time()</span>
1
<span class="code-snippet_outer">run_python.test(number)</span>
1
<span class="code-snippet_outer">end =  time.time()</span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer">py_time = end - start</span>
1
<span class="code-snippet_outer">print(<span class="code-snippet__string">"Python time = {}"</span>.format(py_time))</span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer">start = time.time()</span>
1
<span class="code-snippet_outer">run_cython.test(number)</span>
1
<span class="code-snippet_outer">end =  time.time()</span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer">cy_time = end - start</span>
1
<span class="code-snippet_outer">print(<span class="code-snippet__string">"Cython time = {}"</span>.format(cy_time))</span>
1
<span class="code-snippet_outer"><br></span>
1
<span class="code-snippet_outer">print(<span class="code-snippet__string">"Speedup = {}"</span>.format(py_time /</span>
代码很容易理解,我们用Python的方式导入我们的文件,然后也像Python那样运行我们的函数!

只需稍作修改,Cython就可以帮你加速几乎所有的纯Python代码。值得注意的是,你使用的循环越多、需要筛选处理的数据越多,Cython就越能发挥加速的作用。

请看下面的表格,它记录了Cython在计算不同数阶乘的运行速度,number的值从10到10000000,使用Cython,我们的速度提高了36倍!

提速30倍!这个加速包让Python代码飞起来插图2

以上对Cython的介绍,希望可以给习惯使用Python进行编程的读者带来帮助。文摘菌也强势安利这款Cython加速器,带你在Python的道路上驰骋!

相关报道:

https://towardsdatascience.com/use-cython-to-get-more-than-30x-speedup-on-your-python-code-f6cb337919b6


实习/全职编辑记者招聘ing

加入我们,亲身体验一家专业科技媒体采写的每个细节,在最有前景的行业,和一群遍布全球最优秀的人一起成长。坐标北京·清华东门,在大数据文摘主页对话页回复“招聘”了解详情。简历请直接发送至zz@bigdatadigest.cn

志愿者介绍

后台回复志愿者”加入我们


提速30倍!这个加速包让Python代码飞起来插图3

提速30倍!这个加速包让Python代码飞起来插图4

提速30倍!这个加速包让Python代码飞起来插图5

点「在看」的人都变好看了哦

    已同步到看一看

    发送中

    点赞