Cython基础:cdef/cpdef/def三种函数类型详解
请解释Cython中cdef、cpdef和def三种函数类型的区别和各自的使用场景。cdef函数为什么不能被Python调用?cpdef如何在Python和C之间提供混合调度?给出一个Cython加速数值计算的完整示例(编译前和编译后性能对比)。说明Cython类型声明的语法和性能影响。
回答
我还是少年
三种函数类型对比:
| 函数类型 | Python可调用 | C可调用 | 调用开销 | 适用场景 |
|---------|------------|---------|---------|---------|
| def | ✅ | ❌ | Python完整调用 | API接口、需灵活处理 |
| cdef | ❌ | ✅ | 零开销 | 内部函数、循环热路径 |
| cpdef | ✅ | ✅ | 小开销(双入口) | 需要Python可见的内部函数 |
性能对比示例:
# calc.pyx
def py_sum(int n): # 纯Python级
def py_sum(n): # Python级
cdef int i
cdef long total = 0
for i in range(n):
total += i
return total
cdef long c_sum(int n) nogil: # C级,可释放GIL
cdef int i
cdef long total = 0
for i in range(n):
total += i
return total
cpdef long cp_sum(int n): # 双入口
with nogil:
return _c_sum(n)
编译(setup.py):
from setuptools import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize('calc.pyx', language_level='3'))
性能数据(求和10^8):
- 纯Python:~8秒
def+ C类型声明:~0.5秒cdef+ nogil:~0.15秒- 优化后接近C性能
类型声明语法:
cdef:
int i
double x = 3.14
list py_list = [] # Python对象
Py_ssize_t idx # 索引类型(平台无关)
最佳实践:
- 内层循环变量加类型声明
- 计算密集型函数用
cdef+nogil - 外部API用
cpdef提供Python接口 - 使用
-a选项生成HTML注释查看优化情况 - 复杂项目可用
Cython.Build.cythonize(compiler_directives={'boundscheck': False, 'wraparound': False})