简体   繁体   English

在cython中使用迭代器

[英]using iterator in cython

I am trying to learn cython and I modified the example found here . 我正在尝试学习cython,并修改了此处找到的示例。

#pyx file

import numpy as np
cimport numpy as np
import cython

np.import_array()

def test1(a):
    out = np.empty(a.shape, np.double)

    cdef np.flatiter ita = np.PyArray_IterNew(a)
    cdef np.flatiter ito = np.PyArray_IterNew(out)

    cdef double value

    cdef double i
    i = 0.0

    while np.PyArray_ITER_NOTDONE(ita):

        value = (<double*>np.PyArray_ITER_DATA(ita))[0]

        print(ita)  # for debugging
        print(value,i)  # for debugging

        value = value + i

        (<double*>np.PyArray_ITER_DATA(ito))[0] = value

        i += 1.0

        np.PyArray_ITER_NEXT(ita)
        np.PyArray_ITER_NEXT(ito)

    return out

So I expect the function to add each element of the input array by i , where the value of i increases by one each time the iterator passes to the next element. 因此,我期望函数将输入数组的每个元素加i ,其中,每当迭代器传递到下一个元素时, i的值就会增加一个。 When I run the function with a=np.arange(10) , the print statement shows something like: 当我使用a=np.arange(10)运行该函数时,print语句显示如下内容:

(2.121995791e-314, 0.0)
(<numpy.flatiter object at 0x0000024A2CE27B20>)

(4.2439915824e-314, 1.0)
(<numpy.flatiter object at 0x0000024A2CE27B20>)

(6.365987374e-314, 2.0)
(<numpy.flatiter object at 0x0000024A2CE27B20>)

(8.4879831653e-314, 3.0)
(<numpy.flatiter object at 0x0000024A2CE27B20>)
# rest not shown here

which isn't what I expect as it seems that the iterator is still pointing to the same element of the array, and the value returned by value is essentially zero, but not the values of a (number 0-9). 这不是我期望的,因为迭代器似乎仍指向数组的同一元素,并且value所返回的value本质上为零,而不是a (数字0-9)的值。 But the iterator does seem to stop at the end as the function terminates successfully and the returned array has the same shape as a . 但是,迭代器似乎停止在最后作为函数成功终止并返回的数组具有相同的形状作为a

So my question is: 所以我的问题是:

  1. What does the line value = (<double*>np.PyArray_ITER_DATA(ita))[0] actually mean? value = (<double*>np.PyArray_ITER_DATA(ita))[0]实际含义是什么? <double*> declares the pointer type? <double*>声明指针类型? np.PyArray_ITER_DATA is just what the API says. API所说的就是np.PyArray_ITER_DATA Then what about [0] ? [0]呢?

  2. What did I get wrong and how to modify the code? 我怎么了?怎么修改代码? If a=np.arange(2,8) , then test1(a) should give array([ 2, 4, 6, 8, 10, 12]) . 如果a=np.arange(2,8) ,则test1(a)应该给出array([ 2, 4, 6, 8, 10, 12]) a=np.arange(2,8) array([ 2, 4, 6, 8, 10, 12])

The problem was that arange gives you an int array by default, which you're then interpreting as if it was a double array (small integers misinterpreted as doubles are often around 1e-300 ish, so this is usually a good clue). 问题在于,默认情况下, arange会为您提供一个int数组,然后您将其解释为一个double精度数组(被误解为双精度的小整数通常在1e-300 ish左右,因此通常是个很好的线索)。 Ideally you should make sure you check the dtype in the function. 理想情况下,您应确保检查函数中的dtype

To answer your further questions: 要回答您的其他问题:

print(ita) is printing the address of the iterator object, not the data it's currently accessing. print(ita)正在打印迭代器对象的地址,而不是其当前正在访问的数据。 Therefore it always shows the same address. 因此,它始终显示相同的地址。

np.PyArray_ITER_DATA(ita) gets a pointer to the address of the current bit of data. np.PyArray_ITER_DATA(ita)获取一个指向当前数据位地址的指针。 Since it's designed as a generic interface for any numpy array we don't know the type so it's a void* . 由于它被设计为任何numpy数组的通用接口,我们不知道类型,所以它是void* <double*> is you telling Cython that this pointer actually points to a double . <double*>是要告诉Cython该指针实际上指向double [0] looks up the value stored at that pointer [0]查找该指针处存储的值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM