C 为什么在矩阵乘法运算期间,用于存储累加和的变量比直接访问结果单元格更快?
我对算法和内存优化非常陌生,并试图提高我对它的总体理解。 我相信这是一个非常基本的问题,但是我自己没有找到答案,希望有人能帮我解释一下 在C中实现矩阵乘法时,假设矩阵存储为2D NxN数组,此任务的最基本方法可以写成: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当子例程被传递到
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;
}
}