创建 Numpy ufuncs¶
注意
此页面使用两种不同的语法变体
Cython 特定的
cdef
语法,旨在使类型声明简洁明了,并易于从 C/C++ 的角度阅读。纯 Python 语法,允许在 纯 Python 代码 中进行静态 Cython 类型声明,遵循 PEP-484 类型提示和 PEP 526 变量注释。
要在 Python 语法中使用 C 数据类型,您需要在要编译的 Python 模块中导入特殊的
cython
模块,例如import cython
如果您使用纯 Python 语法,我们强烈建议您使用最新的 Cython 3 版本,因为与 0.29.x 版本相比,这里已经进行了重大改进。
Numpy 支持一种 称为 ufunc 的特殊函数类型。这些支持数组广播(即处理具有任意数量维度的参数的能力),以及其他有用功能。
Cython 可以通过使用 @cython.ufunc
装饰器标记 Cython C 函数来生成 ufunc。输入和输出参数类型应该是标量变量(“通用 ufuncs”尚未支持),并且应该是 Python 对象或简单的数字类型。此类函数的主体被插入到一个高效的编译循环中。
import cython
@cython.ufunc
@cython.cfunc
def add_one(x: cython.double) -> cython.double:
# of course, this simple operation can already by done efficiently in Numpy!
return x+1
cimport cython
@cython.ufunc
cdef double add_one(double x):
# of course, this simple operation can already by done efficiently in Numpy!
return x+1
您的函数可以有任意数量的参数。如果您想拥有多个输出参数,则可以使用 ctuple 语法
import cython
@cython.ufunc
@cython.cfunc
def add_one_add_two(x: cython.int) -> tuple[cython.int, cython.int]:
return x+1, x+2
cimport cython
@cython.ufunc
cdef (int, int) add_one_add_two(int x):
return x+1, x+2
如果您想接受多个不同的参数类型,则可以使用 融合类型(模板)
import cython
@cython.ufunc
@cython.cfunc
def generic_add_one(x: cython.numeric) -> cython.numeric:
return x+1
cimport cython
@cython.ufunc
cdef cython.numeric generic_add_one(cython.numeric x):
return x+1
最后,如果您将 cdef
/@cfunc
函数声明为 nogil
,那么 Cython 将在生成的 ufunc 中释放 GIL。这与 nogil
函数的一般行为略有不同(它们通常不会自动释放 GIL,而是可以在没有 GIL 的情况下运行)。
此功能依赖于 Numpy。因此,如果您在 Cython 中创建 ufunc,则在构建生成的 C 代码时必须提供 Numpy 头文件,并且用户在运行模块时必须安装 Numpy。