Я относительно новичок в Python, и это моя первая попытка написать расширение C.
Фон В моем проекте Python 3.X мне нужно загрузить и проанализировать большой двоичный файлфайлы (10-100 МБ) для извлечения данных для дальнейшей обработки.Двоичный контент организован в кадры: заголовки, за которыми следует переменный объем данных.Из-за низкой производительности в Python я решил пойти на расширение C, чтобы ускорить загрузку.
Автономный код C превосходит Python в 20–500 раз, поэтому я вполне доволен им.
Проблема: память продолжает расти, когда я несколько раз вызываю функцию из моего C-расширения в одном и том же модуле Python.
my_c_ext.c
#include <Python.h>
#include <numpy/arrayobject.h>
#include "my_c_ext.h"
static unsigned short *X, *Y;
static PyObject* c_load(PyObject* self, PyObject* args)
{
char *filename;
if(!PyArg_ParseTuple(args, "s", &filename))
return NULL;
PyObject *PyX, *PyY;
__load(filename);
npy_intp dims[1] = {n_events};
PyX = PyArray_SimpleNewFromData(1, dims, NPY_UINT16, X);
PyArray_ENABLEFLAGS((PyArrayObject*)PyX, NPY_ARRAY_OWNDATA);
PyY = PyArray_SimpleNewFromData(1, dims, NPY_UINT16, Y);
PyArray_ENABLEFLAGS((PyArrayObject*)PyY, NPY_ARRAY_OWNDATA);
PyObject *xy = Py_BuildValue("NN", PyX, PyY);
return xy;
}
...
//More Python C-extension boilerplate (methods, etc..)
...
void __load(char *) {
// open file, extract frame header and compute new_size
X = realloc(X, new_size * sizeof(*X));
Y = realloc(Y, new_size * sizeof(*Y));
X[i] = ...
Y[i] = ...
return;
}
test.py
import my_c_ext as ce
binary_files = ['file1.bin',...,'fileN.bin']
for f in binary_files:
x,y = ce.c_load(f)
del x,y
Здесь я удаляю возвращенные объекты в надежде уменьшить использование памяти.
После прочтения нескольких сообщений (например, это , это и это ) я все еще застрял.
Я пыталсядобавить / удалить PyArray_ENABLEFLAGS
, установив флаг NPY_ARRAY_OWNDATA
, без разницы.Мне пока не ясно, подразумевает ли NPY_ARRAY_OWNDATA
free(X)
в C. Если я явно освобождаю массивы в C, я столкнулся с segfault
при попытке загрузить второй файл в цикле for в test.py
,
Есть идеи, что я делаю не так?