如何将巨大的2D numpy数组传递给c函数



你好,

我是Python中C和ctypes的新手。

我正试图将一个C函数传递到Python代码中。

我一直收到以下错误:;读取0x0…"的访问违规;当在以下C函数中读取2D阵列(形状为10000x521的"St"和形状为10000*520的"dZ"(时:

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

变量";lenSims";以及";lenTaus";分别为10000和521。

调用C函数的Python代码是:

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函数时,我会错误地处理内存。但我不知道如何以正确的方式通过它们。

我可以请你帮忙吗?

致问候,

叶甫根尼

看起来问题是由缓冲区溢出引起的。

假设数组定义为:

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

在C函数中,参数lenTausLenSims分别为52110000。因此,访问dZ的最终偏移量为:

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

dz的大小是10000 * 5205200000的大小小于最终偏移量,因此存在缓冲区溢出,并调用未定义行为

解决方案之一是将dZ的偏移计算更改为:

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

最新更新