C语言中的矩阵表示

3

我希望找到在C编程语言中表示m x n实数矩阵的最佳方法。

使用单个指针表示矩阵有什么优点:

double* A;

使用这种表示法,您可以分配内存:

A = (double* )malloc(m * n * sizeof(double));

在这种表示中,矩阵访问需要进行额外的乘法操作:
aij = A[i * m + j];

矩阵表示法作为双指针的缺点有哪些:

double** B;

内存分配需要进行循环:

double** B = (double **) malloc(m * sizeof(double*));
for (i = 0; i < m; i++)
    A[i] = (double *) malloc(n * sizeof(double))

在这种表示法中,您可以使用直观的双索引 `bij = B[i][j]`,但是否存在会影响性能的缺点。我想知道在性能方面什么是最好的表示方法。
这些矩阵应该用于数值算法,例如奇异值分解。我需要定义一个函数:
void svd(Matrix A, Matrix U, Matrix Sigma, Matrix V);

我希望您能帮忙翻译一下关于IT技术的内容,这段话需要讲述如何更好地表述矩阵。如果C语言中有其他更有效的方法来表示矩阵,请告诉我。

我发现大多数人使用单指针表示法。我想知道相对于双数组表示法是否有性能上的优势?


你缺少访问矩阵中特定数字并分配矩阵本身的示例代码,因此无法确定你所指的矩阵表示。 (虽然不是我投的反对票。) - ZyX
你能告诉我这个问题是否有所改善,还是应该删除它吗? - Slaven Glumac
1
在第二种情况下,您可以将malloc的数量减少到2个甚至1个。也就是说,您可以malloc一个大的double *块(与第一种变体相同长度),并分配A [0] = malloc_resultA [1] = malloc_result + nA [2] = malloc_result + 2 * n等(假设malloc_result的类型为double *)。通过一次malloc,您可以分配sizeof(double *)* m + sizeof(double)* n * m,并分配A = malloc_resultA [0] =(double *)(malloc_result + m)A [1] = A [0] + nA [2] = A [1] + n等(假设malloc_result的类型为(double **))。没有必要进行m + 1次分配。 - ZyX
1
尽管这些变量有一个缺点,即valgrind无法检测到越界数组访问:因为A[0][n]只是A[1][0],所以试图对其进行赋值不会报错。 - ZyX
2个回答

5
看看所需的内存访问。
对于单指针情况,您需要:
1. 读取指针(基地址),可能来自寄存器 2. 读取四个整数,可能来自寄存器或硬编码到指令集中。对于array[i*m+j],4个值分别为imjsizeof(array[0])。 3. 进行乘法和加法 4. 访问内存地址
对于双指针情况,您需要:
1. 读取指针(基地址),可能来自寄存器 2. 读取索引,可能来自寄存器 3. 将索引乘以指针大小并添加。 4. 从内存中获取基地址(不太可能是寄存器,可能会有一些缓存运气)。 5. 再次读取索引,可能来自寄存器 6. 将其乘以对象大小并添加 7. 访问内存地址
双指针解决方案需要访问两个内存位置,这使得其比单指针解决方案慢得多。显然,缓存将是关键;这就是为什么重要的原因是访问数组使访问具有良好的缓存性能(因此尽可能经常访问相邻的内存位置)。
您可以在我的概述中挑剔细节,有些“乘法”操作可能是移位操作等,但一般概念仍然存在:双指针解决方案需要两个内存访问,而单指针解决方案只需要一个,这将会更慢。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接