【问题标题】:Cython: for i from 1 <= i < NCython:对于 i 从 1 <= i < N
【发布时间】:2011-11-10 17:07:28
【问题描述】:

我正在学习 Cython 并遇到了这段代码:

import numpy as np
cimport numpy as np

def mean(np.ndarray[np.double_t] input):

    cdef np.double_t cur
    # Py_ssize_t is numpy's index type
    cdef Py_ssize_t i
    cdef Py_ssize_t N = len(input)

    for i from 0 <= i < N:
        cur += input[i]

    return cur / N

a=np.array([1,2,3,4], dtype=np.double)

显然,这会返回 a 的平均值,即 2.5。我的问题是这样的:

for 循环是 Python 循环、Cython 还是 C?

【问题讨论】:

    标签: python for-loop cython


    【解决方案1】:

    编译并查看:Cython 生成的 C 代码注释很好。

      /* "cyexample.pyx":11
     *     cdef Py_ssize_t N = len(input)
     * 
     *     for i from 0 <= i < N:             # <<<<<<<<<<<<<<
     *         cur += input[i]
     * 
     */
      __pyx_t_1 = __pyx_v_N;
      for (__pyx_v_i = 0; __pyx_v_i < __pyx_t_1; __pyx_v_i++) {
        /* "cyexample.pyx":12
     * 
     *     for i from 0 <= i < N:
     *         cur += input[i]             # <<<<<<<<<<<<<<
     * 
     *     return cur / N
     */
        __pyx_t_2 = __pyx_v_i;
        __pyx_t_3 = -1;
        if (__pyx_t_2 < 0) {
          __pyx_t_2 += __pyx_bshape_0_input;
          if (unlikely(__pyx_t_2 < 0)) __pyx_t_3 = 0;
        } else if (unlikely(__pyx_t_2 >= __pyx_bshape_0_input)) __pyx_t_3 = 0;
        if (unlikely(__pyx_t_3 != -1)) {
          __Pyx_RaiseBufferIndexError(__pyx_t_3);
          {__pyx_filename = __pyx_f[0]; __pyx_lineno = 12; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
        }
        __pyx_v_cur = (__pyx_v_cur + (*__Pyx_BufPtrStrided1d(__pyx_t_5numpy_double_t *, __pyx_bstruct_input.buf, __pyx_t_2, __pyx_bstride_0_input)));
      }
    

    因此循环本身已成功转换为 C。请注意,如今 Cython 可以自然地处理范围,因此不需要旧的“从 0

    【讨论】:

    • 我做了一些简单的 timeit 测试,两个循环结构的运行时间似乎都差不多,而且数组很大。谁能证实这一点?我只是好奇为什么这个特定片段的作者选择在现代代码中使用旧结构。
    • 过去,Cython 不会优化 for i in range(10),因此它实际上会创建一个长度为 10 的列表并使用 Python 回调对其进行迭代。由于这个原因,Pyrex/Cython 引入了 for ... from ... 语法,这可以归结为 C。我有时仍然使用旧语法,因为更清楚的是这段代码已经过优化。
    【解决方案2】:

    【讨论】:

    • 正确。它是一种 Pyrex 形式的 for 循环,Cython 保留它以实现向后兼容性
    猜你喜欢
    • 2022-01-13
    • 1970-01-01
    • 2019-02-12
    • 2021-02-10
    • 2019-04-30
    • 1970-01-01
    • 1970-01-01
    • 2012-01-13
    • 1970-01-01
    相关资源
    最近更新 更多