cython 能将纯 python 数值或循环密集型代码提速 10–50 倍,但前提是显式声明类型(如 cdef int i、double[:, ::1] arr)、避免 python 对象操作、使用 cdef 函数、正确配置编译选项(-o3、-march=native、np.get_include()),否则仅改后缀为 .pyx 并 cythonize 不会加速。

直接说结论:Cython 能把纯 Python 数值计算或循环密集型代码提速 10–50 倍,但前提是——你得让 Cython 真正“看见类型”,而不是只给 .pyx 文件换个后缀。
为什么 cythonize 后速度几乎没变?
常见错觉是:把 slow.py 改名成 slow.pyx,再用 cythonize 编译,就自动变快。实际大概率没变化,甚至更慢。因为默认情况下 Cython 仍按 Python 对象方式解释执行,所有变量都是 PyObject*,没脱离解释器开销。
- 必须显式声明变量类型(
cdef int i、cdef double[:] arr) - 避免在 tight loop 中调用 Python 函数(如
print()、len()、list.append()) - 用
cdef定义函数(而非def),否则仍是 Python 可调用接口,带封装成本 - 编译时加
-O3和-march=native(通过extra_compile_args传给 setuptools)
cpdef 和 cdef 函数怎么选?
这是最常混淆的点。简单说:cdef 函数只能被同个 Cython 模块或其他 Cython 模块调用,不暴露给 Python;cpdef 是双接口:C 层直调 + Python 层可 import 调用,但后者有少量包装开销。
- 纯内部计算逻辑(比如循环体、数值更新)一律用
cdef - 你想从 Python 脚本里
import mymod; mymod.compute(...)调用的入口,用cpdef - 如果入口函数里只是简单转发给
cdef实现,cpdef开销可忽略;但别在每轮循环里调用cpdef函数 - 注意:
cdef函数不能接受 Python 的任意对象参数(如dict、str),只能是 C 类型或 memoryview / typed memoryview
如何安全地把 NumPy 数组传进 Cython 并获得最大性能?
直接传 np.array 给 Cython 函数,默认还是当 Python 对象处理。要零拷贝、高速访问,必须用 typed memoryview(double[:, ::1] 这种语法)或 np.ndarray 的 C API 接口。
- 首选 typed memoryview:声明形参为
double[:, ::1] arr,其中::1表示 C 连续(contiguous),能触发 Cython 的直接指针访问 - 调用前确保 NumPy 数组是 C-order:
arr = np.ascontiguousarray(arr),否则 Cython 会静默降级为通用索引(极慢) - 避免用
arr[i][j],改用arr[i, j]—— 前者触发两次 Python 索引,后者才是单次 C 指针偏移 - 如果数组维度固定(如总是 2D),可用
double *data+ 手动算偏移,但易出错,不推荐初学者
编译配置里最容易漏掉的三个关键项
setup.py 或 pyproject.toml 里只写 Extension(..., sources=['mymod.pyx']) 是不够的。缺以下任一,都可能让生成的 C 代码没优化、不向量化、甚至链接失败。
- 必须加
include_dirs=[np.get_include()],否则numpy/arrayobject.h找不到 - 必须设
extra_compile_args=['-O3', '-march=native'](Linux/macOS)或['/O2', '/QxHost'](Windows MSVC) - 若用了 OpenMP 并行(
cdef parallel for),还得加extra_link_args和对应编译器 flag(如-fopenmp),且确认系统装了 openmp runtime
真正卡住多数人的不是语法,而是“以为编译成功=加速成功”。跑完 python setup.py build_ext --inplace 后,务必用 line_profiler 或 cProfile 对比 hot loop 的 per-call 时间——有时候一个没声明类型的 float 变量,就能让整个函数退化回 Python 解释执行。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











