首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何防止Cython中的__Pyx_MemoryView_Len(__pyx_v_a) Python交互

如何防止Cython中的__Pyx_MemoryView_Len(__pyx_v_a) Python交互
EN

Stack Overflow用户
提问于 2018-12-09 21:49:00
回答 1查看 248关注 0票数 3

我有一个简单的Cython函数,它获取内存视图的长度:

代码语言:javascript
运行
复制
cdef int get_length(int[:] a):
    return len(a)

我正在用annotate=True指令编译代码,让我看看Cython在哪里有一些Python交互。

生成的html包含以下文本,用于return len(a)行:

代码语言:javascript
运行
复制
  __pyx_t_1 = __Pyx_MemoryView_Len(__pyx_v_a); 
  __pyx_r = __pyx_t_1;
  goto __pyx_L0;

这种Python交互应该是缓慢的。有什么方法可以阻止Python的交互吗?我试过a.shape[0],但这没有帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-09 23:06:04

您不应该担心这一点,__Pyx_MemoryView_Len的速度是最快的,因为它被定义为是:

代码语言:javascript
运行
复制
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编译器将看到它,就好像您已经编写了:

代码语言:javascript
运行
复制
return a.shape[0]

顺便说一句,这是条白线。

如果您也对多维memview的大小感兴趣,那么这个问题可能值得一读。

注释将函数的定义显示为黄色行。但是,只有加载模块时的成本(并且每次调用该函数时都支付一次,而不是每次调用该函数)才负责“黄色”颜色。

看看生成的C代码:

代码语言:javascript
运行
复制
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):

代码语言:javascript
运行
复制
/* … */
  __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有什么关系,也不知道为什么需要这样做,但是因为成本太小,所以我从来不关心这个问题。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53697021

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档