栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Cython模块中的加载与链接

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Cython模块中的加载与链接

调用

cdef
-function或多或少地相当于跳转到内存中的一个地址-应该从中读取/执行命令。问题是如何提供此地址。在某些情况下,我们需要考虑:

A.内联函数

这些函数的代码是内联的,或者函数的定义在同一个转换单元中,因此链接器在链接时(甚至在编译时甚至是编译器)都知道地址,而无需其他库。

一个示例是仅标头库。

后果:中仅应提供包含路径

setup.py

B.静态链接

我们需要的定义/功能在另一个翻译单元/库中-跳转的目标地址是在链接时计算的,此后不能再更改。

一个示例是添加到扩展定义中的其他c / cpp文件或静态库。

结果:静态库应添加到setup.py,即库路径和库名称以及包含路径。

C.动态链接

共享库/共享库中提供了必要的功能。要跳转到的地址是在运行时从加载程序中计算得出的,可以在程序启动时通过交换已加载的共享对象来替换。

例如stdlibc (通常由g 自动添加)或libm,它们不会由gcc自动添加到链接器命令中。

结果:动态库应添加到setup.py,即库路径和库名称,可能是r-path + include路径。必须在运行时提供共享的对象/ dll。可以在此SO-post中找到更多(使用动态库)有关Cython / Python的信息。

D.通过指针调用

仅当我们通过函数名称调用函数时,才需要链接器。如果通过函数指针调用它,则不需要链接器/加载器,因为函数的地址是已知的-函数指针中的值。

示例:Cython生成的模块使用此机制来启用对通过pxd-file导出的cdef函数的访问。它创建一个__pyx_capi__功能指针的数据结构(将其存储为模块本身的变量),一旦通过ldopen(或Windows的任何等效方法)加载了so / dll,该指针便由加载器填充。字典中的查找仅在模块加载且函数地址被缓存时才发生一次,因此在运行时的调用几乎没有开销。

我们可以检查它,例如通过

#foo.pyx:cdef void doit():    print("doit")#foo.pxdcdef void doit()>>> cythonize -3 -i foo.pyx>>> python -c "import foo; print(foo.__pyx_capi__)" {'doit': <capsule object "void (void)" at 0x7f7b10bb16c0>}

现在,cdef从另一个模块调用函数只是跳转到相应的地址。

结果:我们需要导入所需的功能。

Numpy有点复杂,因为它使用A和D的复杂组合以便将符号的解析推迟到运行时,因此在链接时(但在运行时!)不需要共享对象/ dll。

可以直接使用numpy -pxd文件中的某些功能,因为它们是内联的(甚至只是定义了),例如PyArray_NDIM,基本上所有来自的功能ndarraytypes.h。这就是为什么可以毫不费力地使用cython的ndarray的原因。

例如,ndarrayobject.h如果没有np.import_array()在初始化步骤中调用,则无法访问其他功能(基本上是from的所有功能)PyArray_FromAny。为什么?

答案是在报头__multiarray_api.h被包括在ndarrayobject.h,但不能在找到的git存储库,因为它是生成的安装信息,其中的定义期间PyArray_FromAny可以查找:

...static void **PyArray_API=NULL; //usually......#define PyArray_CheckFromAny         (*(PyObject * (*)(PyObject *, PyArray_Descr *, int, int, int, PyObject *))          PyArray_API[108])...

PyArray_CheckFromAny不是函数的名称,而是保存在中的函数指针的定义PyArray_API,该指针在NULL首次加载模块时未初始化(即)。顺便说一句,还有一个(私有)函数称为PyArray_CheckFromAny,它实际上是函数指针指向的内容-并且由于公共版本是一个定义,因此链接时不会发生名称冲突…

难题的最后一部分-函数_import_array(或多或少地是后面的工作马np.import_array)是内联函数(情况A),因此仅需要include路径即可使用它。

_import_array使用与Cython类似的方法来__pyx_capi__获取函数指针:调用了该字段_ARRAY_API,可以通过以下方法检查该字段:

>>> import numpy.core._multiarray_umath as macore>>> macore._ARRAY_API<capsule object NULL at 0x7f17d85f3810>

有关如何PyArray_API初始化的更多信息,可以在我的SO解答中找到。

但是,当使用from中的功能时numpy/math.pxd,必须静态链接numpy的数学库(例如,参见此SO问题)。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/660983.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号