Cython 入门

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)

推荐阅读更多精彩内容