Cython优化简介

使用Cython进行优化简介 - Cython教程


在Python中,当你声明一个变量时,如:

x  =  5.0

你永远不必告诉语言变量’x’是一个整数。事实上,以后,你可以将’Gary’分配给x并且很好。这是因为Python会每隔一段时间检查一次以确定类型。这被称为“动态打字”。

这很好,并且使得学习最初非常简单,Python实际上只是一种教学语言,但是这会严重降低速度。

相反,如果我们愿意,我们可以使用静态打字和Cython来获得一些严重的加速。许多语言更像是:

float  x  =  5.0

Cython需要这样的东西:

cdef  float  x  =  5.0

一旦你有了Cython和一个编译器,让我们通过Cython工作流程并制作我们自己的C-Exension!我们从一个简单的python文件开始:

# example_original.py
def test(x):
    y = 0
    for i in range(x):
        y += i
    return y

我们如何准备这个文件通过Cython传递?简单而不是.py,我们做.pyx

#example_cython.pyx
def test(x):
    y = 0
    for i in range(x):
        y += i
    return y

我们显然还没有任何输入信息。稍后我们会补充说,但现在,我们将坚持这一点。

一旦你有.pyx,你就可以开始构建。为此,我们将制作一个setup.py文件:

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize('example_cython.pyx'))

接下来,在您的终端中,执行:

python3 setup.py build_ext --inplace

这应该创建一个构建目录,一个C文件(.c)和一个共享对象文件(.so)。有了这个,我们可以导入我们的C-extension。为了说明这一点,您现在可以删除或以其他方式移动您的example.pyexample.pyx文件,以便保留build,.c和.so文件。现在创建一个名为testing.py的新文件,我们可以导入新的c扩展名:

#testing.py
import example_cython

example_cython.test(5)

所以我们还没有真正做过任何Cython输入…等等,所以这段代码没有更好的优化,但是这实际上很有趣,因为它很简单,它表明你可以尽可能多地做,或者尽可能少地使用Cython实现。

现在,我们将开始添加输入信息。让我们回顾一下键入声明:

cdef声明

cdef int x,y,z
cdef char *s
cdef float x = 5.2 (single precision)
cdef double x = 40.5 (double precision)
cdef list languages
cdef dict abc_dict
cdef object thing

def, cdef, and cpdef

  • def - 常规的python函数,仅来自Python的调用。
  • cdef - cython只有函数,不能从python-only代码访问这些函数,必须在Cython中进行访问,因为对于这些函数将不会有C语言转换。
  • cpdef - C和Python。 将为Python创建一个C函数和一个包装器。 为什么不总是使用cpdef? 在某些情况下,你可能只有C指针,就像C数组一样。 但是,我们将主要使用cpdef

现在,我们将从之前的相同代码开始:

#example_cython.pyx
def test(int x):
    cdef int y = 0
    cdef int i
    for i in range(x):
        y += i
    return y
#setup.py
from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize('example_cy.pyx'))
#testing_things.py
import timeit

cy = timeit.timeit('''example_cy.test(5)''',setup='import example_cy',number=100)
py = timeit.timeit('''example.test(5)''',setup='import example', number=100)

print(cy, py)
print('Cython is {}x faster'.format(py/cy))

不错! 还有一些其他的细微变化,比如:

cpdef int test(int x):
    cdef int y = 0
    cdef int i
    for i in range(x):
        y += i
    return y
#testing_things.py
import timeit

cy = timeit.timeit('''example_cy.test(5000)''',setup='import example_cy',number=100)
py = timeit.timeit('''example.test(5000)''',setup='import example', number=100)

print(cy, py)
print('Cython is {}x faster'.format(py/cy))

我们必须分析我们可以尝试使用cython的领域的一个选项是通过cythonize的html输出。 例如,让我们将我们原始的Python脚本转换为.pyx:

#furthertesting.pyx
def test(x):
    y = 0
    for i in range(x):
        y += i
        return y
$ cython -a furthertesting.pyx

现在我们可以看到,与Python的唯一关系是我们的cpdef,因为我们希望能够在Python中使用这个函数。

好的,这就是现在所有的Cython。我可能会在未来引入更多高级主题,但是,不管你信不信,你的大部分收获将纯粹来自使用静态类型。您还可以查看各种命令,如“与nogil”。如果你愿意,Cython可能会变得更加复杂。如果您熟悉C / C ++,我强烈建议您更多地参与。否则,请考虑Python代码中哪些地方需要继续验证某些变量的类型。这可以是循环的,也可以是扩展的程序。例如,如果您的网站流量很大,或者您有某种爬网机器,或者您正在分析股票的价格价格,那么无论您何时扩大使用变量,都应该考虑添加类型一些严重的性能改进信息。

正如你所见,这样做是非常快速和无痛的。希望它有帮助!

发布了96 篇原创文章 · 获赞 179 · 访问量 64万+

猜你喜欢

转载自blog.csdn.net/wc781708249/article/details/80247892