如何使用NpyIter(新API)进行直接数据访问?我该如何处理char *类型?

时间:2011-10-18 01:47:38

标签: c numpy scipy

我在这里举手表示希望有人能够在Numpy的C API中了解新的NpyIter API,以便快速告诉我我做错了什么。

我有一个形状的阵列(非常大,有点大)。元素是双倍> = 0.对于每一行,我需要找到总和为最大值的连续非零值的总和。我不知道有什么方法可以在Python中快速完成这项工作(有时候真的很大~1e5),所以我一直在使用Weave。

在我的旧代码中,我有以下内容:

            double *p1,*res;
            double g,d,q;
            PyArrayIterObject *itr;
            int axis = 1;
            g = 0;
            d = 0;
            itr = (PyArrayIterObject *) PyArray_IterAllButAxis(py_x,&axis);
            while(PyArray_ITER_NOTDONE(itr)) {
                const int go = x_array->strides[axis]/sizeof(double);
                p1 = (double *) PyArray_ITER_DATA(itr);
                res = (double *) PyArray_GETPTR1(py_r,itr->index);
                g = 0;
                d = 0;
                for (int i = 0; i < x_array->dimensions[axis]; i++) {
                    d+=*p1;
                    if (d>g) g=d;
                    if ((*p1)==0) d=0;
                    p1+=go;
                }
                *res = g;
                PyArray_ITER_NEXT(itr);
            }
            PyArray_free(itr);

这很有效,但它的内存非常泄漏。我不知道如何阻止它泄漏,旧的PyArrayIter的文档在内存管理方面相当缺乏。

我尝试使用NpyIter API编写新代码,但缺少内存管理其他的文档。具体来说,我完全不确定我应该如何访问实际的数组值。我尝试了以下内容:

            char *p1; 
            double *res;
            char **p1p;
            double g,d,q;
            int go;
            NpyIter* iter;
            NpyIter_IterNextFunc *iternext;
            g = 0;
            d = 0;
            iter = NpyIter_New(x_array, NPY_ITER_READONLY|NPY_ITER_EXTERNAL_LOOP, NPY_KEEPORDER, NPY_NO_CASTING, NULL);
            iternext = NpyIter_GetIterNext(iter, NULL);
            p1p = NpyIter_GetDataPtrArray(iter);

            do {
                p1 = *p1p;
                const int go = x_array->strides[1]/sizeof(double);
                res = (double *) PyArray_GETPTR1(py_r,NpyIter_GetIterIndex(iter));
                g = 0;
                d = 0;
                for (int i = 0; i < x_array->dimensions[1]; i++) {
                    d+= p1;
                    if (d>g) g=d;
                    if ((*p1)==0) d=0;
                    p1+=go;
                }
                *res = g;
            } while(iternext(iter));

            NpyIter_Deallocate(iter);   

然而,由于char * vs. double *,这显然不起作用。但是,我不确定如何从NpyIter_GetDataPtrArray返回(char **)并将其转换为实际的数组值:文档非常无用,而是使用未给出的函数并使用char *。

如何以有效且不泄漏内存的方式执行此操作?

1 个答案:

答案 0 :(得分:2)

在第一种情况下,您需要遵循常用的PyObject内存管理规则:Py_DECREF使用后PyArrayIterObject以避免内存泄漏。 (PyArray_free做了一些截然不同的事情。)

NpyIter

要访问数据,请抓取(double*)(*dataptr)

如果您不确切知道自己在做什么,请不要使用NPY_ITER_EXTERNAL_LOOP。要复制IterAllButAxis的行为,您需要调用NpyIter_RemoveAxis来删除您不想从迭代中迭代的轴。