python生成数组内存爆_使用PyArray_SimpleNewFromData()创建数组并返回时,Python扩展中出现内存泄漏...

我编写了一个简单的Python扩展模块来模拟3位模数转换器。它应该接受一个浮点数组作为它的输入,以返回相同大小的输出数组。输出实际上由量化的输入数字组成。以下是我的(简化)模块:static PyObject *adc3(PyObject *self, PyObject *args) {

PyArrayObject *inArray = NULL, *outArray = NULL;

double *pinp = NULL, *pout = NULL;

npy_intp nelem;

int dims[1], i, j;

/* Get arguments: */

if (!PyArg_ParseTuple(args, "O:adc3", &inArray))

return NULL;

nelem = PyArray_DIM(inArray,0); /* size of the input array */

pout = (double *) malloc(nelem*sizeof(double));

pinp = (double *) PyArray_DATA(inArray);

/* ADC action */

for (i = 0; i < nelem; i++) {

if (pinp[i] >= -0.5) {

if (pinp[i] < 0.5) pout[i] = 0;

else if (pinp[i] < 1.5) pout[i] = 1;

else if (pinp[i] < 2.5) pout[i] = 2;

else if (pinp[i] < 3.5) pout[i] = 3;

else pout[i] = 4;

}

else {

if (pinp[i] >= -1.5) pout[i] = -1;

else if (pinp[i] >= -2.5) pout[i] = -2;

else if (pinp[i] >= -3.5) pout[i] = -3;

else pout[i] = -4;

}

}

dims[0] = nelem;

outArray = (PyArrayObject *)

PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, pout);

//Py_INCREF(outArray);

return PyArray_Return(outArray);

}

/* ==== methods table ====================== */

static PyMethodDef mwa_methods[] = {

{"adc", adc, METH_VARARGS, "n-bit Analog-to-Digital Converter (ADC)"},

{NULL, NULL, 0, NULL}

};

/* ==== Initialize ====================== */

PyMODINIT_FUNC initmwa() {

Py_InitModule("mwa", mwa_methods);

import_array(); // for NumPy

}

我预计,如果引用计数处理正确,Python垃圾回收将(频繁地)释放输出数组使用的内存,如果它具有相同的名称并被重复使用。所以我用这个代码在一些虚拟的(但大量的)数据上进行了测试:

^{pr2}$

在这里,名为“b”的数组被多次重用,它的内存(由adc3()从堆中借用)将被返回给系统。我用gnome系统监视器来检查。与我的预期相反,python拥有的内存增长迅速,只能通过退出程序来释放(我使用IPython)。

为了比较,我用标准NumPy函数zeros()和copy()尝试了相同的过程:for i in xrange(1000):

a = np.zeros(10000000)

b = np.copy(a)

print i

如您所见,后一个代码不会产生任何内存累积。

我在标准文档和网络上读了很多文本,试图使用Py_incrif(outArray),但没有使用它。一切都是徒劳的:问题依然存在。在

但是,我在http://wiki.scipy.org/Cookbook/C_Extensions/NumPy_arrays中找到了解决方案。

作者提供了一个扩展程序matsq(),它创建一个数组并返回它。当我试图使用作者建议的电话时:outArray = (PyArrayObject *) PyArray_FromDims(nd,dims,NPY_DOUBLE);

pout = (double *) outArray->data;

而不是我的pout = (double *) malloc(nelem*sizeof(double));

outArray = (PyArrayObject *)

PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, pout);

/* no matter with or without Py_INCREF(outArray)) */

内存泄漏消失了!程序现在正常工作了。在

一个问题:有人能解释一下为什么PyArray_SimpleNewFromData()没有提供正确的引用计数,而PyArray_FromDims()却提供了正确的引用计数?在

非常感谢。在

添加。我可能在评论中超过了房间/时间,所以我把我的评论添加到Alex这里。

我试图这样设置OWNDATA标志:outArray->flags |= OWNDATA;

但我得到了“错误:'OWNDATA'未声明”。

剩下的在评论里。提前谢谢你。在

已解决:标志的正确设置是outArray->flags |= NPY_ARRAY_OWNDATA;

现在它起作用了。在

亚历克斯,对不起。在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值