我目前正在开发一个 C 程序,尝试计算矩阵乘法。我通过循环第二个矩阵的每一列来完成此任务,如下所示。
我已将大小设置为 1000。
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
for(k=0;k<size;k++)
{
matC[i][j]+=matA[i][k]*matB[k][j];
}
}
}
我想知道这个实现中存在哪些有问题的访问模式。是什么使行/列访问比其他访问更有效?我试图从使用缓存的逻辑角度来理解这一点。请帮助我理解这一点。非常感谢您的帮助 :)
如果您正在谈论缓存的使用,那么您可能想做一些称为循环平铺的操作。您将循环分解为图块,以便循环的内部部分存储在缓存中(现在缓存相当大)。所以你的循环将变成类似的东西(如果你使用指针将矩阵传递到函数中)
for(j=0;j<size;j+=t)
for(k=0;k<size;k+=t)
for(i=0;i<size;i+=t)
for(ii=i;ii<MIN(i+t,size);ii++)
for(jj=j;jj<MIN(j+t,size);jj++)
{
var=*(c+ii * size+jj); //Var is a scalar variable
for(kk=k;kk<MIN(k+t,size);kk++)
{
var = var + *(a+ii *size +kk) * *(bt +jj * size+ kk);
}
*(c+ii *size +jj) = var;
}
t 的值根据您获得的加速比而变化。它可以 t = 64,128,256 等等。您可以在此处使用许多其他技术。循环平铺只是有效利用缓存的一次技术。此外,您可以在发送到乘法函数之前转置 B 矩阵。这样你就可以线性访问矩阵 B 的元素。更多解释
考虑
A -------- and B | | | |
-------- | | | |
-------- | | | |
-------- | | | |
在这里,您总是会考虑将 A 的第一行与 B 的第一列相乘。并且因为您正在使用C
我相信,CPU需要额外的努力才能将矩阵B的所有列一一读入内存中。为了减轻这些工作,您可以转置矩阵并获取矩阵的行B'
(它们只不过是B
本质上)并使用循环平铺来缓存乘法的最大数量的元素。希望这会有所帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)