Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么在矩阵乘法运算期间,用于存储累加和的变量比直接访问结果单元格更快?_C_Memory_Matrix Multiplication - Fatal编程技术网

C 为什么在矩阵乘法运算期间,用于存储累加和的变量比直接访问结果单元格更快?

C 为什么在矩阵乘法运算期间,用于存储累加和的变量比直接访问结果单元格更快?,c,memory,matrix-multiplication,C,Memory,Matrix Multiplication,我对算法和内存优化非常陌生,并试图提高我对它的总体理解。 我相信这是一个非常基本的问题,但是我自己没有找到答案,希望有人能帮我解释一下 在C中实现矩阵乘法时,假设矩阵存储为2D NxN数组,此任务的最基本方法可以写成: for (i=0; i<N; i++) for (j=0; j<N; j++) for (k=0; k<N; k++) c[i][j] += a[i][k] * b[k][i]; 对于(i=0;i当子例程被传递到

我对算法和内存优化非常陌生,并试图提高我对它的总体理解。 我相信这是一个非常基本的问题,但是我自己没有找到答案,希望有人能帮我解释一下

在C中实现矩阵乘法时,假设矩阵存储为2D NxN数组,此任务的最基本方法可以写成:

for (i=0; i<N; i++)
    for (j=0; j<N; j++)
        for (k=0; k<N; k++)
            c[i][j] += a[i][k] * b[k][i];

对于(i=0;i当子例程被传递到指针
a
b
c
,编译器通常不知道它们指向哪里。因此,在
c[i][j]+=a[i][k]*b[k][i]
中,编译器必须考虑到更新到
c[i][j]的可能性
可能会更改
a
b
的元素,这些元素将在循环的未来迭代中使用。通常的做法是将每次更新写入
c[i][j]
的内存中


使用
sum+=a[i][k]*b[k][i]
,编译器知道
sum
不能与
a
b
重叠,因为
sum
是本地创建的。因此,它可以通过将和保存在寄存器中并在
c[i][j]时只向内存写入一次来优化此代码=sum;
已执行。

不确定它是否相关(需要检查程序集),但
c[i][j]
涉及一系列乘法和加法(
c[i][j]
=>类似,大约==>
*(c+i*sizeof c[i]+j*sizeof c[i][j])
)第二个版本的内存写入更少。在第一个版本中,
c
的每个元素都被写入
N+1
次(
+1
是因为必须事先将其归零,而您没有显示)。第二个版本将
c
的每个元素写入一次,而无需事先将其归零。这就是区别。优化后,
sum
将保存在寄存器中。感谢快速帮助。第二个方法写入的次数是否相同(N+1)对于变量sum,就像第一个对c一样?或者,当sum保存在寄存器中时,是否避免了这种情况@TomKarzes@nirt如果登记在登记簿中,则不需要对其进行写入。@ TomKarzes,如果我们认为该金额不在寄存器中,这仍然成立吗?与此相比,我们仍然做较少的内存写入操作吗?第一版也是吗?
for (i=0; i<N; i++) {
    for (j=0; j<N; j++) {
        int sum = 0;
        for (k=0; k<N; k++) {
            sum += a[i][k]*b[k][j];
        }
        c[i][j] = sum;
    }
}