Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python C扩展中的内存泄漏 这是我第一次为Python写一个C扩展,你可以看到我的一个丑陋的和可能是非常低效的C++实现的卷积。我的内存管理有问题。每次我在python中调用这个函数时,它都会消耗大约500MB的内存(对于一批大小为100x112x112x3和一个大小为3x3x64的内核),之后不会释放它。即使这不是类方法,我也必须注意引用计数吗?还是我必须在代码中的某个地方手动释放内存?请注意,我排除了所有的错误检查,以获得更好的概述。谢谢 PyObject* conv2d(PyObject*, PyObject* args) { PyObject* data; PyObject* shape; PyObject* kernel; PyObject* k_shape; int stride; PyArg_ParseTuple(args, "OOOOi", &data, &shape, &kernel, &k_shape, &stride); Py_ssize_t dims = PyTuple_Size(shape); Py_ssize_t kernel_dims = PyTuple_Size(k_shape); int shape_c[3]; int k_shape_c[4]; for (int i = 0; i < kernel_dims; i++) { if (i < dims) { shape_c[i] = PyLong_AsLong(PyTuple_GetItem(shape, i)); } k_shape_c[i] = PyLong_AsLong(PyTuple_GetItem(k_shape, i)); } PyObject* data_item, kernel_item; PyObject* ret_array = PyList_New(0); double conv_val, channel_sum; for (int oc = 0; oc < k_shape_c[3]; oc++) { for (int row = 0; row < shape_c[0]; row += stride) { for (int col = 0; col < shape_c[1]; col += stride) { channel_sum = 0; for (int ic = 0; ic < shape_c[2]; ic++) { conv_val = 0; for (int k_row = 0; k_row < k_shape_c[0]; k_row++) { for (int k_col = 0; k_col < k_shape_c[1]; k_col++) { data_item = PyList_GetItem(data, row + k_row); if (!data_item) { PyErr_Format(PyExc_IndexError, "Index out of bounds"); return NULL; } data_item = PyList_GetItem(data_item, col + k_col); data_item = PyList_GetItem(data_item, ic); kernel_item = PyList_GetItem(kernel, k_row); kernel_item = PyList_GetItem(kernel_item, k_col); kernel_item = PyList_GetItem(kernel_item, ic); kernel_item = PyList_GetItem(kernel_item, oc); conv_val += PyFloat_AsDouble(data_item) * PyFloat_AsDouble(kernel_item); } } channel_sum += conv_val; } PyList_Append(ret_array, PyFloat_FromDouble(channel_sum)); } } } return ret_array; } PyObject*conv2d(PyObject*,PyObject*args) { PyObject*数据; PyObject*形状; PyObject*内核; PyObject*k_形状; 步幅; PyArg_语法元组(args,“OOOOi”,&data,&shape,&kernel,&k_shape,&stride); Py_ssize_t dims=PyTuple_大小(形状); Py_ssize_t kernel_dims=PyTuple_Size(k_形状); int shape_c[3]; int k_shape_c[4]; for(int i=0;i_Python_C_Python C Api - Fatal编程技术网

Python C扩展中的内存泄漏 这是我第一次为Python写一个C扩展,你可以看到我的一个丑陋的和可能是非常低效的C++实现的卷积。我的内存管理有问题。每次我在python中调用这个函数时,它都会消耗大约500MB的内存(对于一批大小为100x112x112x3和一个大小为3x3x64的内核),之后不会释放它。即使这不是类方法,我也必须注意引用计数吗?还是我必须在代码中的某个地方手动释放内存?请注意,我排除了所有的错误检查,以获得更好的概述。谢谢 PyObject* conv2d(PyObject*, PyObject* args) { PyObject* data; PyObject* shape; PyObject* kernel; PyObject* k_shape; int stride; PyArg_ParseTuple(args, "OOOOi", &data, &shape, &kernel, &k_shape, &stride); Py_ssize_t dims = PyTuple_Size(shape); Py_ssize_t kernel_dims = PyTuple_Size(k_shape); int shape_c[3]; int k_shape_c[4]; for (int i = 0; i < kernel_dims; i++) { if (i < dims) { shape_c[i] = PyLong_AsLong(PyTuple_GetItem(shape, i)); } k_shape_c[i] = PyLong_AsLong(PyTuple_GetItem(k_shape, i)); } PyObject* data_item, kernel_item; PyObject* ret_array = PyList_New(0); double conv_val, channel_sum; for (int oc = 0; oc < k_shape_c[3]; oc++) { for (int row = 0; row < shape_c[0]; row += stride) { for (int col = 0; col < shape_c[1]; col += stride) { channel_sum = 0; for (int ic = 0; ic < shape_c[2]; ic++) { conv_val = 0; for (int k_row = 0; k_row < k_shape_c[0]; k_row++) { for (int k_col = 0; k_col < k_shape_c[1]; k_col++) { data_item = PyList_GetItem(data, row + k_row); if (!data_item) { PyErr_Format(PyExc_IndexError, "Index out of bounds"); return NULL; } data_item = PyList_GetItem(data_item, col + k_col); data_item = PyList_GetItem(data_item, ic); kernel_item = PyList_GetItem(kernel, k_row); kernel_item = PyList_GetItem(kernel_item, k_col); kernel_item = PyList_GetItem(kernel_item, ic); kernel_item = PyList_GetItem(kernel_item, oc); conv_val += PyFloat_AsDouble(data_item) * PyFloat_AsDouble(kernel_item); } } channel_sum += conv_val; } PyList_Append(ret_array, PyFloat_FromDouble(channel_sum)); } } } return ret_array; } PyObject*conv2d(PyObject*,PyObject*args) { PyObject*数据; PyObject*形状; PyObject*内核; PyObject*k_形状; 步幅; PyArg_语法元组(args,“OOOOi”,&data,&shape,&kernel,&k_shape,&stride); Py_ssize_t dims=PyTuple_大小(形状); Py_ssize_t kernel_dims=PyTuple_Size(k_形状); int shape_c[3]; int k_shape_c[4]; for(int i=0;i

Python C扩展中的内存泄漏 这是我第一次为Python写一个C扩展,你可以看到我的一个丑陋的和可能是非常低效的C++实现的卷积。我的内存管理有问题。每次我在python中调用这个函数时,它都会消耗大约500MB的内存(对于一批大小为100x112x112x3和一个大小为3x3x64的内核),之后不会释放它。即使这不是类方法,我也必须注意引用计数吗?还是我必须在代码中的某个地方手动释放内存?请注意,我排除了所有的错误检查,以获得更好的概述。谢谢 PyObject* conv2d(PyObject*, PyObject* args) { PyObject* data; PyObject* shape; PyObject* kernel; PyObject* k_shape; int stride; PyArg_ParseTuple(args, "OOOOi", &data, &shape, &kernel, &k_shape, &stride); Py_ssize_t dims = PyTuple_Size(shape); Py_ssize_t kernel_dims = PyTuple_Size(k_shape); int shape_c[3]; int k_shape_c[4]; for (int i = 0; i < kernel_dims; i++) { if (i < dims) { shape_c[i] = PyLong_AsLong(PyTuple_GetItem(shape, i)); } k_shape_c[i] = PyLong_AsLong(PyTuple_GetItem(k_shape, i)); } PyObject* data_item, kernel_item; PyObject* ret_array = PyList_New(0); double conv_val, channel_sum; for (int oc = 0; oc < k_shape_c[3]; oc++) { for (int row = 0; row < shape_c[0]; row += stride) { for (int col = 0; col < shape_c[1]; col += stride) { channel_sum = 0; for (int ic = 0; ic < shape_c[2]; ic++) { conv_val = 0; for (int k_row = 0; k_row < k_shape_c[0]; k_row++) { for (int k_col = 0; k_col < k_shape_c[1]; k_col++) { data_item = PyList_GetItem(data, row + k_row); if (!data_item) { PyErr_Format(PyExc_IndexError, "Index out of bounds"); return NULL; } data_item = PyList_GetItem(data_item, col + k_col); data_item = PyList_GetItem(data_item, ic); kernel_item = PyList_GetItem(kernel, k_row); kernel_item = PyList_GetItem(kernel_item, k_col); kernel_item = PyList_GetItem(kernel_item, ic); kernel_item = PyList_GetItem(kernel_item, oc); conv_val += PyFloat_AsDouble(data_item) * PyFloat_AsDouble(kernel_item); } } channel_sum += conv_val; } PyList_Append(ret_array, PyFloat_FromDouble(channel_sum)); } } } return ret_array; } PyObject*conv2d(PyObject*,PyObject*args) { PyObject*数据; PyObject*形状; PyObject*内核; PyObject*k_形状; 步幅; PyArg_语法元组(args,“OOOOi”,&data,&shape,&kernel,&k_shape,&stride); Py_ssize_t dims=PyTuple_大小(形状); Py_ssize_t kernel_dims=PyTuple_Size(k_形状); int shape_c[3]; int k_shape_c[4]; for(int i=0;i,python,c,python-c-api,Python,C,Python C Api,泄漏源于: PyList_Append(ret_array, PyFloat_FromDouble(channel_sum)); PyFloat\u FromDouble创建一个新引用,PyList\u Append获取该引用的共享所有权(它不会窃取/使用该引用)。当使用PyList\u Append并希望列表拥有您自己的引用时,您必须在追加后明确释放引用,例如(省略错误检查): 另一种解决方案(如果合适,更快)是将列表预先分配到正确的大小,并用PyList\u SetItem/PyList\

泄漏源于:

PyList_Append(ret_array, PyFloat_FromDouble(channel_sum));
PyFloat\u FromDouble
创建一个新引用,
PyList\u Append
获取该引用的共享所有权(它不会窃取/使用该引用)。当使用
PyList\u Append
并希望
列表
拥有您自己的引用时,您必须在追加后明确释放引用,例如(省略错误检查):

另一种解决方案(如果合适,更快)是将
列表
预先分配到正确的大小,并用
PyList\u SetItem
/
PyList\u SET\u ITEM
填充条目,两者都会窃取引用,而不是增加引用计数。一般来说,没有明确提到引用窃取的API不会,并且您需要监控自己的引用计数

注意,在内存方面,单独的
PyFloat
s比C
double
s(它们包装)要贵很多;在64位系统上,
列表中的每个
PyFloat
消耗32个字节(8个字节用于
列表中的指针,24个字节用于
PyFloat
本身),而原始C
double
则消耗8个字节

您可能需要考虑使用(创建一个大小/类型正确的
数组
,使用缓冲协议对其进行C级查看,然后填充缓冲区);代码会稍微复杂一点,但内存使用率会下降4倍
numpy
类型将提供相同的优势(结果可能会更灵活地使用)。

泄漏源于:

PyList_Append(ret_array, PyFloat_FromDouble(channel_sum));
PyFloat\u FromDouble
创建一个新引用,
PyList\u Append
获取该引用的共享所有权(它不会窃取/使用该引用)。当使用
PyList\u Append
并希望
列表
拥有您自己的引用时,您必须在追加后明确释放引用,例如(省略错误检查):

另一种解决方案(如果合适,更快)是将
列表
预先分配到正确的大小,并用
PyList\u SetItem
/
PyList\u SET\u ITEM
填充条目,两者都会窃取引用,而不是增加引用计数。一般来说,没有明确提到引用窃取的API不会,并且您需要监控自己的引用计数

注意,在内存方面,单独的
PyFloat
s比C
double
s(它们包装)要贵很多;在64位系统上,
列表中的每个
PyFloat
消耗32个字节(8个字节用于
列表中的指针,24个字节用于
PyFloat
本身),而原始C
double
则消耗8个字节

您可能需要考虑使用(创建一个大小/类型正确的
数组
,使用缓冲协议对其进行C级查看,然后填充缓冲区);代码会稍微复杂一点,但内存使用率会下降4倍<代码>numpy