使用Cython重载Python数学函数

时间:2012-04-27 12:39:14

标签: python cython

这是我的基本问题:

我有一个导入

的Python文件
from math import sin,cos,sqrt

我需要这个文件仍然是100%CPython兼容,以允许我的开发人员编写100%的CPython代码并使用为Python开发的优秀工具。

现在进入Cython。在我的Python文件中,trig函数被调用数百万次(代码的基础,不能改变它)。有没有办法通过主python文件中的一些Python-fu,或Cython魔术,否则我可以使用C / C ++数学函数使用Cython代码上的一些变体

cdef extern from "math.h":
    double sin(double)

这会给我近乎C的表现,这将是非常棒的。

Stefan's talk具体说不能这样做,但谈话已经两年了,那里有很多有创意的人

4 个答案:

答案 0 :(得分:2)

我不是Cython专家,但是AFAIK,你所能做的就是在sin周围写一个Cython包装并调用它。我无法想象这会比math.sin更快,因为它仍然使用Python调用语义 - 所有Python内容的开销都是调用函数,而不是实际的trig计算,在使用CPython时也在C中完成。

您是否考虑使用Cython pure mode,这使源CPython兼容?

答案 1 :(得分:2)

在Cython文档的example中,他们使用C库中的cimport来实现这一点:

from libc.math cimport sin

答案 2 :(得分:1)

八年后回答了这个问题,这对我来说是有效的,它使用来自Ubuntu repostory的系统CPython vesion 3.7.5和Cython3版本0.29.10在Ubuntu 19.10上工作。

Pure Python Mode上的Cython文档给出了一个有效的示例。它看起来与此处的旧答案中的示例有所不同,因此我认为此文档自此以来已进行了更新。

Python文件需要有条件导入,使用常规CPython可以正常工作:

#!/usr/bin/env python3
# from: https://cython.readthedocs.io/en/latest/src/tutorial/pure.html
# mymodule.py

import cython

# override with Python import if not in compiled code
if not cython.compiled:
    from math import sin

# calls sin() from math.h when compiled with Cython and math.sin() in Python
print(sin(0.5))

Cython语言构造必须放在具有相同名称但后缀为“ .pxd”的文件中:

#cython: language_level=3
# from: https://cython.readthedocs.io/en/latest/src/tutorial/pure.html
# mymodule.pxd

# declare a C function as "cpdef" to export it to the module
cdef extern from "math.h":
    cpdef double sin(double x)

我使用“ --embed”选项为独立的Linux ELF可执行文件创建了C代码,以对此进行测试。 GCC编译器行需要使用“ -lm”来导入包含sin的maths模块。

cython3 --embed mymodule.py

gcc -o mymodule mymodule.c -I/usr/include/python3.7 -lpython3.7m -lm

答案 3 :(得分:0)

我可能误解了您的问题,但Cython documentation on interfacing with external C code似乎建议使用以下语法:

cdef extern from "math.h":
    double c_sin "sin" (double)

在C代码中赋予函数名称sin(以便它正确链接到math.h中的函数),并在Python模块中赋予c_sin。我不确定我是否理解在这种情况下实现了什么,但是为什么你想在Cython代码中使用math.sin?你有一些静态类型的变量,还有一些动态类型的变量?