我有一个简单的Cython函数,它获取内存视图的长度:
cdef int get_length(int[:] a):
return len(a)我正在用annotate=True指令编译代码,让我看看Cython在哪里有一些Python交互。
生成的html包含以下文本,用于return len(a)行:
__pyx_t_1 = __Pyx_MemoryView_Len(__pyx_v_a);
__pyx_r = __pyx_t_1;
goto __pyx_L0;这种Python交互应该是缓慢的。有什么方法可以阻止Python的交互吗?我试过a.shape[0],但这没有帮助。
发布于 2018-12-09 23:06:04
您不应该担心这一点,__Pyx_MemoryView_Len的速度是最快的,因为它被定义为是:
typedef struct {
struct {{memview_struct_name}} *memview;
char *data;
Py_ssize_t shape[{{max_dims}}];
...
} {{memviewslice_name}};
// used for "len(memviewslice)"
#define __Pyx_MemoryView_Len(m) (m.shape[0])这一行的颜色不是黄色的,而是淡黄色的--这主要意味着这不是纯C代码的结果,而是使用了一些_Pyx_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;
}只有在使用RefNannyXXXX构建时,-defined。才是活动的。
annotate-tool还显示了另一段代码,它对应于cdef int get_length(int[:] a)::
/* … */
__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;但是,这段代码是__pyx_pymod_exec_XXXXX/PyInit_XXXXX的一部分,在加载模块时只调用一次。实际上,我不知道这与get_length有什么关系,也不知道为什么需要这样做,但是因为成本太小,所以我从来不关心这个问题。
https://stackoverflow.com/questions/53697021
复制相似问题