Cython:纯C循环优化

2024-09-30 12:15:13 发布

您现在位置:Python中文网/ 问答频道 /正文

引用Cython documentation

Cython recognises the usual Python for-in-range integer loop pattern:
    for i in range(n):
        ...
If i is declared as a cdef integer type, it will optimise this into a pure C loop

我编写了一个简单Cython函数的两个版本,一个使用Pythonrange,另一个使用for-fromPyrex符号(应该不推荐使用):

^{pr2}$

通过查看.c文件,我注意到这两个循环的处理方式截然不同:

第一种方法实际上是使用Python对象创建Python范围。它还附带了50行不必要的Python-to-C-C-to-Python内容。在

纯C循环已优化为一秒:

__pyx_t_1 = __pyx_v_stop;
__pyx_t_2 = __pyx_v_step;
for (__pyx_v_x = __pyx_v_start; __pyx_v_x < __pyx_t_1; __pyx_v_x+=__pyx_t_2) {

是我遗漏了什么,还是我应该报告的bug?在


Tags: thetoinloopforifisdocumentation
2条回答

实际上,假设start、stop和step是C变量,就可以将一个范围内的任何for循环转换为完全优化的C循环。你只要写得再巧妙一点就行了。在

loop1()开头:

def loop1(int start, int stop, int step):
    cdef int x, t = 0
    for x in range(start, stop, step):
        t += x
    return t

Cython(目前)不知道如何优化它,因为它不知道step的符号。事实证明,这个问题最简单的解决方案就是解决一个稍微更一般的问题。也就是说:

^{pr2}$

count变量看起来没用,但问题的另一个版本可能会在循环体中使用它。在

现在,用手计算指数:

def loop1(int start, int stop, int step):
    cdef:
        int x
        int count
        int length
        int t = 0
    length = len(range(start, stop, step))  # could optimize this further
    for count in range(length):
        x = start + count*step
        t += x
    return t

我已经尝试过了,我知道它生成纯C代码(除了length =行)。事实上,我已经成功地在nogil块中使用了它。cython -a显示循环本身的所有白色输出。在

这将创建两个额外的变量,以及一些死存储等,但是我假设任何一个半途而废的编译器都应该能够消除-O2上的那些变量。因此,它适用于高性能环路。在

The docs请注意:

Automatic range conversion

This will convert statements of the form for i in range(...) to for i from ... when i is any cdef’d integer type, and the direction (i.e. sign of step) can be determined.

我想Cython想知道编译时step的符号,以便在C循环的结束条件中生成<或{}。在

另请参见Ticket #546 on Cython Trac

相关问题 更多 >

    热门问题