Act enthusiastic and you will be enthusiastic.
1.Cython 的由来
Python 是一门开源免费、语法简单的语言,然而解释性语言的通病就是“运行速度慢”,它远慢于 C/C++。为了解决该问题,Python 官网提供了「Python/C API」,可以实现用 C 语言编写 Python 库,即通过 C 语言来编写部分核心逻辑来提高整体性能。然而,「Python/C API」门槛太高,于是诞生了 Cython。
只需编写简单的 Cython(语法与 Python 基本一致)代码,就可以实现 C 扩展,如下图所示:
2.什么是 Cython ?
「Cython」 是一个针对 Python 语言和扩展的 Cython 语言(基于 Pyrex)的优化的静态编译器,即可将 Python/Cython 编译成 C。它使得为 Python 编写 C 扩展就像 Python 本身一样简单,优点包括:
- 1)既具备了 Python 快速开发的特点,
- 2)又可以让代码运行起来像 C 一样快,
- 3)同时还可以方便地调用 C library。
在计算科学中,常用 Cython 来加速 Python 代码。
3.安装 Cython
3.1)配置 gcc
Cython 需要一个 C 编译器,不同平台的安装配置:
- windows
首先,安装 MingW-w64 编译器,命令:conda install libpython m2w64-toolchain -c msys2
然后,在 Python 安装路径下的 /Lib/distutils 下创建 distutils.cfg,并写入如下内容:
[build] compiler=mingw32
- macOS
安装 XCode 即可。 - linux:
gcc 一般都是配置好的,如果没有可执行命令:sudo apt-get install build-essential
3.2)安装 Cython 库
命令:pip install cython
Anaconda 环境下安装命令:conda install cython
查看版本:cython --version
4.简单示例
1)定义要加速的模块。
原始 Python 文件 multiply_python.py
:
from time import time
# 自定义"计时"装饰器
def cal_time(func):
def cal_time_wrapper(*args):
start_time = time()
result = func(*args)
end_time = time()
print("Python 耗时(秒):", end_time - start_time)
return result
return cal_time_wrapper
# 添加"计时"装饰器
@cal_time
def my_multiply(a, b):
return a * b
需要加速的 Cython/Python 模块 multiply_cython.pyx
:
from time import time
# 自定义"计时"装饰器
def cal_time(func):
def cal_time_wrapper(*args):
start_time = time()
result = func(*args)
end_time = time()
print("Cython 耗时(秒):", end_time - start_time)
return result
return cal_time_wrapper
# 添加"计时"装饰器
@cal_time
def my_multiply(a, b):
return a * b
2)编写 setup.py
(名字不限) 文件——指定扩展模块,内容如下:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [Extension("multiply_cython", ["multiply_cython.pyx"])]
setup(
name='multiply_demo',
cmdclass={'build_ext': build_ext},
ext_modules=ext_modules
)
3)执行命令生成 C 扩展:python setup.py build_ext --inplace
。
执行成功,生成一个 .c
和一个 .so
文件:
4)编写 test.py
进行测试,内容如下:
import numpy as np
import multiply_python
import multiply_cython
x = np.arange(1, 25).reshape(2, 3, 4)
y = np.arange(10, 34).reshape(2, 3, 4)
multiply_python.my_multiply(x, y)
multiply_cython.my_multiply(x, y)
本例中,Cython 加速后的速度是原来的4.75倍,运行结果如下:
Python 耗时(秒): 9.059906005859375e-06
('Cython 耗时(秒):', 1.9073486328125e-06)