2011-11-10 61 views
8

我学Cython和整个本SNIPPIT的代码传来:用Cython:对于i从1 <= I <N

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) 

显然,这将返回一个其为2.5的平均值。我的问题是这样的:

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

回答

5

编译并查看: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 < =我< N”的风格是没有必要的。引入(非Python)“for/from”语法的意义在于表示哪些循环应该被C化。

+0

我做了一些幼稚timeit测试和两个循环结构出现有关与数组大小大相同的时间内运行英寸任何人都可以确认吗?我只是好奇为什么这个特定snippit的作者选择在现代代码中使用旧的结构。 –

+1

当天,Cython不会优化'for i in range(10)',所以它实际上会创建一个长度为10的列表,并使用Python回调函数对其进行迭代。由于这个原因,Pyrex/Cython引入了for ... from ...语法,这可以归结为C语言。我有时仍然使用较老的语法,因为它更清晰地表明这个代码已经优化。 – carl

相关问题