python定义变量能加速_使用Cython可以让Python代码的速度提高30倍以上

毫无疑问,Python是社区最喜爱的编程语言!到目前为止,它是最容易使用的语言之一,因为python代码是用一种直观的、人类可读的方式编写的。

然而,你经常会反复听到一些对Python的抱怨,尤其是来自C语言爱好者的抱怨,这些抱怨无非就是Python很慢。

是的,他们并没有说错。

与许多其他编程语言相比,Python确实很慢。Benchmark game有一些比较不同编程语言在不同任务上的速度的可靠基准。

对于Python,我们有几种不同的方法可以加快速度:

使用多进程库来使用所有的CPU核心

如果你使用Numpy、panda或Scikit-Learn,使用Rapids来加速GPU上的处理。

如果你所做的实际上可以并行化,比如数据预处理或矩阵运算,这些都是很好的方法。

但是如果你的代码是纯Python的呢?如果你不得不使用一个很大的for循环,且不能将数据放入矩阵中,因为数据必须按顺序处理,那会怎样?有没有办法加快Python本身的速度呢?

答案是肯定的,这就是Cython来加速原生Python代码的地方。

什么是Cython?

Cython是Python和C/C++之间的一个中间步骤。它允许你编写纯Python代码,并且只需要做一些小修改,然后将其直接翻译成C代码。

你对Python代码所做的惟一调整就是向每个变量添加类型信息。通常,我们可以像这样在Python中声明一个变量:

x = 0.5

使用Cython,我们将向该变量添加一个类型:

cdef float x = 0.5

这告诉Cython,我们的变量是浮点类型,就像我们在C中所做的一样。对于纯Python,变量的类型是动态确定的。Cython中类型的显式声明使转换为C成为可能,因为显式类型声明是必须的。

安装Cython只需要一行简单的pip命令:

pip install cython

Cython中的类型

使用Cython时,变量和函数分别有不同的类型。

对于变量我们有以下类型:

cdef int a, b, c

cdef char *s

cdef float x = 0.5 (单精度)

cdef double x = 63.4 (双精度)

cdef list names

cdef dict goals_for_each_play

cdef object card_deck

注意所有这些类型都来自C/C++ ! 而对于方法我们有以下类型:

def — 常规python函数,仅从python调用。

cdef — 不能从python的代码中访问Cython的函数。即必须在Cython内调用

cpdef — C 和 Python. 可以从C和Python中访问

了解了Cython类型之后,我们就可以直接实现加速了!

如何使用Cython加速你的代码

我们要做的第一件事是设置Python代码基准:用于计算数值阶乘的for循环。原生Python代码如下:

def test(x):

y = 1

for i in range(x+1):

y *= i

return y

相同功能的Cython方法看起来非常相似。首先,我们将确保Cython代码文件具有.pyx扩展名。对代码本身的惟一更改是,我们已经声明了每个变量和函数的类型。

cpdef int test(int x):

cdef int y = 1

cdef int i

for i in range(x+1):

y *= i

return y

注意到该函数具有cpdef,以确保我们可以从Python中调用它。并且注意到到循环变量i是具有类型的。你需要为函数中的所有变量设置类型,以便C编译器知道使用哪种类型!

接下来,创建setup.py文件,该文件将Cython代码编译为C代码:

from distutils.core import setup

from Cython.Build import cythonize

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

并执行编译:

python setup.py build_ext --inplace

Boom ! 可以看到我们的C代码已经编译好了,可以使用了!

你将看到,在Cython代码所在的文件夹中,你拥有运行C代码所需的所有文件,包括run_cython.c文件。如果你感兴趣,可以查看一下Cython生成的C代码!

现在我们准备测试我们新的并且超级快的C代码!查看下面的代码,它实现了一个速度测试,将原生Python代码与Cython代码进行比较。

import run_python

import run_cython

import time

number = 10

start = time.time()

run_python.test(number)

end = time.time()

py_time = end - start

print("Python time = {}".format(py_time))

start = time.time()

run_cython.test(number)

end = time.time()

cy_time = end - start

print("Cython time = {}".format(cy_time))

print("Speedup = {}".format(py_time / cy_time))

代码非常直观,我们以与普通Python相同的方式导入文件,并以与普通Python相同的方式运行函数!

Cython几乎可以让你在所有原生Python代码上获得良好的加速,而不需要太多额外的工作。需要注意的关键是,循环次数越多,处理的数据越多,Cython可以提供的帮助就越多。

下表显示了Cython为不同的数值阶乘带来的加速性能。当数值为10000000的时候,可以看到,我们的Cython加速超过了36倍。

Number

Python Time

Cython Time

Speedup

10

1.6689300537109375e-06

4.76837158203125e-07

3.5

100

3.337860107421875e-06

4.76837158203125e-07

7.0

1000

2.193450927734375e-05

9.5367431640625e-07

23.0

10000

0.0002090930938720703

6.4373016357421875e-06

32.481

100000

0.0021562576293945312

6.008148193359375e-05

35.89

1000000

0.02128767967224121

0.0005953311920166016

35.75

10000000

0.2148280143737793

0.00594782829284668

36.1187317112278

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值