如何防止Cython中的Python交互
我有一个简单的Cython函数,它获取memoryview的长度:如何防止Cython中的Python交互,python,cython,Python,Cython,我有一个简单的Cython函数,它获取memoryview的长度: cdef int get_length(int[:] a): return len(a) 我使用annotate=True指令编译代码,让我看看Cython在哪里有一些Python交互 生成的html包含以下文本,用于返回len(a)行: __pyx_t_1 = __Pyx_MemoryView_Len(__pyx_v_a); __pyx_r = __pyx_t_1; goto __pyx_L0; 这种
cdef int get_length(int[:] a):
return len(a)
我使用annotate=True
指令编译代码,让我看看Cython在哪里有一些Python交互
生成的html包含以下文本,用于返回len(a)
行:
__pyx_t_1 = __Pyx_MemoryView_Len(__pyx_v_a);
__pyx_r = __pyx_t_1;
goto __pyx_L0;
这种Python交互应该很慢。我有没有办法阻止Python交互?我试过
a.shape[0]
,但没有效果。你不必担心,\u Pyx\u MemoryView\u Len
速度很快,因为:
这一行的颜色不是黄色而是淡黄色-这主要意味着它不会产生纯C代码,而是使用了一些\u Pyx\u XXX
功能,这通常对性能一点也不坏
没有Python交互-在C预处理器传递之后,C编译器将看到它,就好像您编写了:
return a.shape[0]
顺便说一下,这会引出一条白线
如果您还对多维memview的大小感兴趣,那么可能值得一读
注释将函数的定义显示为黄线。然而,只有模块加载时的成本(并且只支付一次,而不是每次调用函数时)才是“黄色”的原因 看一下由此产生的C代码:
static int __pyx_f_9my_module_get_length(__Pyx_memviewslice __pyx_v_a) {
int __pyx_r;
__Pyx_RefNannyDeclarations
__Pyx_RefNannySetupContext("get_length", 0);
/* "my_module.pyx":5
*
* cdef int get_length(int[:] a):
* return a.shape[0] # <<<<<<<<<<<<<<
*/
__pyx_r = (__pyx_v_a.shape[0]);
goto __pyx_L0;
/* "my_module.pyx":4
* return 3. * a
*
* cdef int get_length(int[:] a): # <<<<<<<<<<<<<<
* return a.shape[0]
*/
/* function exit code */
__pyx_L0:;
__Pyx_RefNannyFinishContext();
return __pyx_r;
}
但是,此代码是
\uuupyx\upymod\uexec\uuxxxxx
/PyInit\uuxxxxx
的一部分,在加载模块时只调用一次。事实上,我不确定这与get_length
有什么关系,也不知道为什么需要这样做,但因为成本太低,我一直都不想知道。谢谢您的详细解释。为什么只有在加载模块时才有成本?“我不是一个C语言程序员。”我补充了一些解释
static int __pyx_f_9my_module_get_length(__Pyx_memviewslice __pyx_v_a) {
int __pyx_r;
__Pyx_RefNannyDeclarations
__Pyx_RefNannySetupContext("get_length", 0);
/* "my_module.pyx":5
*
* cdef int get_length(int[:] a):
* return a.shape[0] # <<<<<<<<<<<<<<
*/
__pyx_r = (__pyx_v_a.shape[0]);
goto __pyx_L0;
/* "my_module.pyx":4
* return 3. * a
*
* cdef int get_length(int[:] a): # <<<<<<<<<<<<<<
* return a.shape[0]
*/
/* function exit code */
__pyx_L0:;
__Pyx_RefNannyFinishContext();
return __pyx_r;
}
/* … */
__pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(1, 1, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_1);
if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(1, 1, __pyx_L1_error)
__Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;