Как передать огромный 2D массив numpy в функцию c

#python #arrays #c #numpy #ctypes

Вопрос:

Хороший день,

Я новичок в C и ctypes в Python.

Я пытаюсь передать функцию C в код Python.

Я продолжаю получать следующую ошибку: «чтение с нарушением доступа 0x0…» при чтении 2D-массивов («St» формы 10 000 x 521 и «dZ» формы 10 000 x 520) в следующей функции C:

 #include lt;math.hgt; #include lt;stdio.hgt;  double change (double * dZ, double * St, size_t lenTaus, size_t lenSims) {  size_t i, j;  double a, b;  for (i = 0; i lt; lenSims; i  ) /*Iterate through simulations.*/  {  for (j = 0; j lt; (lenTaus - 1); j  ) /*Iterate through taus.*/  {  a = St[lenTaus * i   j];  b = dZ[lenTaus * i   j];  }  }  return 0.0; }  

Переменные «lenSims» и «lenTaus» равны 10 000 и 521 соответственно.

Код Python для вызова функции C является:

 import ctypes impor t numpy as np cCode = ctypes.CDLL("cCode_e.so") ### Read the C code in a form of shared library. cCode.change.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_size_t, ctypes.c_size_t] ### Let know what kind of input we provide to the C function. cCode.change.restype = ctypes.c_double ### Let know what kind of output we expect from the C function. St_Python = np.zeros([10000,521]) dZ_Python = np.random.randn(10000,520) St = St_Python.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) ### Convert a numpy array into a pointer to an array of doubles. dZ = dZ_Python.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) ### Convert a numpy array into a pointer to an array of doubles. lenTaus = St_Python.shape[1] ### Find the number of columns in the original array. lenSims = St_Python.shape[0] ### Find the number of rows in the original array. out = cCode.change(dZ, St, lenTaus, lenSims) ### Call the C function  

Если я правильно понимаю проблему, я неправильно работаю с памятью при передаче целых массивов в качестве указателей на функцию C. Но я не знаю, как правильно их передать.

Могу я попросить вас о помощи?

С уважением,

Евгений

Комментарии:

1. как вы создаете St_Python и dZ_Python обрабатываете массивы? Может быть, в одном из них недостаточно данных?

2. Способ обработки массивов кажется неправильным. Если один из них равен 10000X521 (10000 строк и 521 столбец), 1-й индекс, который должен быть пройден, равен 10000 ( lenTaus ). Также 520 соответствует lenSims — 1 . Переключатель lenSims с (lenTaus - 1) 2 петлями. и индексация должна быть [lenSims * i j] .

3. Здравствуйте, я добавил определение массивов «St_Python» и «dZ_Python» в Python.

4. устраняет ли dZ_Python = np.random.randn(10000,520) -gt; gt; dZ_Python = np.random.randn(10000,521) проблему?

5. Кроме того, почему вы жестко закодировали значения в Python при создании массивов вместо использования St_Python.shape[] ? Может быть, они отличаются друг от друга.

Ответ №1:

Похоже, что проблема вызвана переполнением буфера.

Предполагая, что массивы определены как:

 St_Python = np.zeros([10000,521]) dZ_Python = np.random.randn(10000,520)  

В функции C параметры lenTaus и LenSims являются 521 и 10000 соответственно. В результате конечное смещение, при котором dZ осуществляется доступ, равно:

 lenTaus * i   j = lenTaus * (lenSims-1)   (lenTaus - 1 - 1)  = 521*9999   521-1-1  = 5209998  

Размер dz — это 10000 * 520 то 5200000 , что меньше конечного смещения, поэтому происходит переполнение буфера и вызывается неопределенное поведение.

Одним из решений является изменение расчетов смещения для dZ :

 b = dZ[(lenTaus - 1) * i   j];