【问题标题】:How to pass huge 2D numpy array to c function如何将巨大的 2D numpy 数组传递给 c 函数
【发布时间】:2022-01-03 13:29:19
【问题描述】:

早安,

我是 C 和 Python 中的 ctypes 的新手。

我正在尝试将 C 函数传递给 Python 代码。

在以下 C 函数中读取二维数组(形状为 10,000 x 521 的“St”和形状为 10,000 x 520 的“dZ”)时,我一直收到以下错误:“访问冲突读取 0x0...”:

#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”分别为 10,000 和 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_PythondZ_Python 数组?也许其中一个没有足够的数据?
  • 处理数组的方式似乎是错误的。如果一个是 10000X521(10000 行和 521 列),则应该遍历的第一个索引是 10000 (lenTaus)。 520 也对应于 lenSims - 1。在 2 个循环中将 lenSims(lenTaus - 1) 切换。和索引应该是[lenSims * i + j]
  • 您好,我在 Python 中添加了“St_Python”和“dZ_Python”数组的定义。
  • dZ_Python = np.random.randn(10000,520) -> dZ_Python = np.random.randn(10000,521) 解决问题了吗?
  • 另外,为什么您在创建数组时硬编码 Python 中的值,而不是使用 St_Python.shape[]?也许他们不同。

标签: python arrays c numpy ctypes


【解决方案1】:

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

假设数组定义为:

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 * 520 什么是5200000,小于最终偏移量,因此存在缓冲区溢出并调用 未定义行为

其中一种解决方案是将dZ 的偏移量计算更改为:

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

【讨论】:

    猜你喜欢
    • 2022-01-14
    • 1970-01-01
    • 2014-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    相关资源
    最近更新 更多