python - 如何在大小为 `n` 次 `m` (n≠m) 的非方阵的 numpy 数组上使用 c 函数进行计算

标签 python arrays c numpy malloc

编辑

我创建了一个类似的问题,我发现它在那里更容易理解和实用:How to copy a 2D array (matrix) from python with a C function (and do some computer heavy computation) which return a 2D array (matrix) in python?

原始问题

我想在 python 中使用 C 来计算一个大小为 nm 的大型非方阵的所有条目。我从那里的优秀教程中复制了代码:https://medium.com/spikelab/calling-c-functions-from-python-104e609f2804 .方阵的代码

我先编译了c_sum.c脚本

$ cc -fPIC -shared -o c_sum.so c_sum.c

然后运行 ​​python 脚本:

$ python main.py

而且运行良好。但是,如果我将 main.py 中的 nm 的值设置为不同的值,则会出现段错误。我想必须分别为 nm 分配内存,但我对 C 的了解还很初级,不知道如何去做。比方说,可以使用 m=3000n=2000 的代码是什么?

这是脚本c_sum.c:

#include <stdlib.h>

double * c_sum(const double * matrix, int n, int m){
    double * results = (double *)malloc(sizeof(double) * n);
    int index = 0;
    for(int i=0; i< n*m; i+=n){
        results[index] = 0;
        for(int j=0; j<m; j++){
            results[index] += matrix[i+j];
        }
        index += 1;
    }
    return results;
}

这是 main.c 脚本:

# https://medium.com/spikelab/calling-c-functions-from-python-104e609f2804
from ctypes import c_void_p, c_double, c_int, cdll
from numpy.ctypeslib import ndpointer
import numpy as np
import time
import pdb

def py_sum(matrix: np.array, n: int, m: int) -> np.array:
    result = np.zeros(n)
    for i in range(0, n):
        for j in range(0, m):
            result[i] += matrix[i][j]
    return result

n = 3000
m = 3000
matrix = np.random.randn(n, m)

time1 = time.time()
py_result = py_sum(matrix, n, m)
time2 = time.time() - time1
print("py running time in seconds:", time2)
py_time = time2

lib = cdll.LoadLibrary("c_sum.so")
c_sum = lib.c_sum
c_sum.restype = ndpointer(dtype=c_double,
                          shape=(n,))

time1 = time.time()
result = c_sum(c_void_p(matrix.ctypes.data),
            c_int(n),
            c_int(m))
time2 = time.time() - time1
print("c  running time in seconds:", time2)

c_time = time2
print("speedup:", py_time/c_time)

最佳答案

我假设您想计算 (n,m) 矩阵沿最后一个轴的总和。当您访问您无权访问的内存时,会发生段错误。问题在于错误的外循环。您需要对两个维度进行迭代,但您对同一维度进行了两次迭代。

double * results = (double *)malloc(sizeof(double) * n); /* you allocate n doubles. 
         Do you free this Outside function? If not, you are having a memory leak. 
        An alternative way is to pass the output array to function, so that you can avoid creating memory in the function*/

for(int i=0; i< n*m; i+=n){ /* i+=n => you are iterating for m times. also you are iterating over last dimension */

        results[index] = 0; /* when index > n ; you are accessing data which 
                           you don't have access leading to segmentation fault */
        for(int j=0; j<m; j++) /* you are iterating again over last axis*/
        {
            results[index] += matrix[i+j];
        }

        index += 1; /* this leads to index > n as you iterate for m times and m>n in this case.
                   For a square matrix, m=n, so you don't have any issue */
    }

TLDR:要修复段错误,您需要替换 for(int i=0; i< n*m; i+=n)for(int i=0; i< n*m; i+=m)这样您就可以只在两个维度上迭代 n 次。

关于python - 如何在大小为 `n` 次 `m` (n≠m) 的非方阵的 numpy 数组上使用 c 函数进行计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73715140/

相关文章:

python - 如何在 Python Django 中传递多个键值对作为查询参数?

c# - 将 stdout/stderr 从 .NET 应用程序中嵌入的 Python 重定向到文本框

python - 无法将小部件放置在框架 tkinter 上

c - scanf AFTER fgets 破坏了 fgets 语句

python - 如何加载带有自定义损失的keras "history"对象?

javascript - 如何使用 jQuery 获取 HTML 文本而不是下拉列表中的值

c - C中将数组和数组指针传递给函数的区别

java - 字符串数组计算

c - 使用网站 www.codepad.org 您可以链接数学库吗?

c - 如何从 XML 文件中读取多个值并将它们与一个值进行有效比较的示例