内存视图中扩展类型的Cython开销

时间:2015-12-05 23:26:46

标签: cython

我正在编译Cython模块,并使用cython -a命令检查了这段代码。

cdef INT_t print_info(Charge[:] electrons):
    cdef INT_t i, index
    for i in range(electrons.shape[0]):
        index = electrons[i].particleindex
    return index

事实证明

 + index = electrons[i].particleindex
    __pyx_t_4 = __pyx_v_i;
    __pyx_t_3 = (PyObject *) *((struct __pyx_obj_14particle_class_Charge * *) ( /* dim=0 */ (__pyx_v_electrons.data + __pyx_t_4 * __pyx_v_electrons.strides[0]) ));
    __Pyx_INCREF((PyObject*)__pyx_t_3);
    __pyx_t_5 = ((struct __pyx_obj_14particle_class_Charge *)__pyx_t_3)->particleindex;
    __Pyx_DECREF(((PyObject *)__pyx_t_3)); __pyx_t_3 = 0;
    __pyx_v_index = __pyx_t_5;

Charge是一个cdef扩展类型,我试图在这里使用memoryview缓冲区Charge[:]。在这种情况下,Cython似乎调用了一些Python API,特别是生成了__Pyx_INCREF((PyObject*)__Pyx_DECREF(((PyObject *)

我想知道是什么导致这种情况,会导致很多放缓吗?这是我在论坛上的第一篇文章,非常感谢任何意见或建议!

PS:Charge对象定义为

charge.pyx

cdef class Charge:
    def __cinit__(Charge self):
        self.particleindex = 0     
        self.charge = 0
        self.mass = 0
        self.energy = 0
        self.on_electrode = False 

charge.pxd

cdef class Charge:
    cdef INT_t particleindex
    cdef FLOAT_t charge
    cdef FLOAT_t mass
    cdef FLOAT_t energy
    cdef bint on_electrode 

2 个答案:

答案 0 :(得分:0)

Cython可能会对pythonic代码感到满意。重写你的功能:

cdef INT_t print_info(Charge[:] electrons):
    cdef INT_t i, index
    for electron in electrons:
        index = electron.particleindex
    return index

再试一次。

答案 1 :(得分:0)

这不是内存视图,而是扩展类型。 Cython扩展类型使用与Python对象相同的引用计数语义进行处理。

可以获取并使用指向它们的指针,这些指针不会更改重新计算,包括<void*><PyObject*>(您可以cimport来自{ {1}}),但指针显然没有任何方法或属性。在您尝试强制转换为扩展类型类型的那一刻,cpython.ref代码重新出现。这些说明非常快。

在邮件列表上有一些关于如何将非引用的引用(即访问对象数据)扩展到扩展类型可能是未来的新功能的讨论,但似乎没有热情添加一个功能实际上,可能会导致很多可疑的“访问违规”变种代码。