我正在编译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
答案 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
代码重新出现。这些说明非常快。
在邮件列表上有一些关于如何将非引用的引用(即访问对象数据)扩展到扩展类型可能是未来的新功能的讨论,但似乎没有热情添加一个功能实际上,可能会导致很多可疑的“访问违规”变种代码。