Встраивание массива python / cython numpy: передача массива numpy в указатель c - PullRequest
0 голосов
/ 14 января 2019

Я пытаюсь передать массив cthon-numpy в структуру c. Который иногда работает, но падает, если массив становится слишком большим. Хотя это не очень много (например, <100 000 записей двойного типа), и я не могу понять, откуда этот предел. Несколько фрагментов кода (полный код прилагается). </p>

Сборка на Win7, Cython 0.28.4, Python 3.6, mingw64

Я пробовал это с разными длинами массива. Последнее, что я обнаружил, это всегда происходит сбой, если длина массива превышает 2 ** 16-512 записей. Но я понятия не имею, почему.

Файл Cython:

//cy_file.pyx
//...
cdef public struct Container:
    double* np_array
// ...
cdef public void create_np_array(Container *container):
  cdef numpy.ndarray[numpy.float_t, ndim=1, mode = 'c'] np_array
  # just create a numpy array 
  longarray = np.linspace(1.0, 5.0, 100000)
  np_array = numpy.ascontiguousarray(numpy.array(longarray), dtype=float)
  container.np_array = <double*> np_array.data

А для c-файла:

//c_file.c
#include "Python.h"
#include "cy_file.h"

struct Container container;
//...
Py_Initialize();
PyInit_cy_file();
// and call the cython function that fills up the numpy array
create_np_array(&container, start, stop, n_elements, n);
// shutdown of python interpreter
Py_Finalize();

// *** here comes the crash if the array longarray is 'too long' ***
container.np_array[0]

Может кто-нибудь дать мне подсказку, что здесь не так или как отлаживать?

Спасибо и ура, Тим

Ответы [ 2 ]

0 голосов
/ 06 марта 2019

Хорошо, наконец-то нашел ответ с полезными подсказками:

Идея лучше всего описана в сообщении в блоге , включая полный пример кода на github. Так что я просто ссылаюсь на этот пост здесь, который отвечает на вопрос очень подробно.

Спасибо!

0 голосов
/ 14 января 2019

Память принадлежит массиву Numpy и освобождается, когда счетчик ссылок массива Numpy падает до нуля, что наиболее вероятно в конце create_np_array. В противном случае Py_Finalize() пытается освободить всех оставшихся объектов Python.

Ваша попытка получить доступ к этой памяти всегда недействительна - тот факт, что она работает только для массивов определенных размеров, является просто "удачей".

Нет одного хорошего решения, но вот несколько советов:

  1. Используйте Py_INCREF, чтобы вручную увеличить счетчик ссылок массива-владельца (и затем снова уменьшить его вручную, когда вы закончите с памятью, в которой он хранится), чтобы он не уничтожался в конце функции , Убедитесь, что у вас есть доступ к памяти до Py_Finalize.

  2. Обработайте выделение памяти в вашем коде C и присвойте его массиву Numpy, чтобы массиву numpy не принадлежало его, используя PyArray_SimpleNewFromData. Вы должны быть осторожны, чтобы массив Numpy не переживал память.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...