我为矩阵乘法编写了一些C ++代码。我使用vector<double>
来保存矩阵条目,我使用了一系列3个嵌套for
循环来计算乘法逐项。事实证明这是超级慢(对于900 * 500和500 * 500矩阵乘法,我的macbook空气需要大约10秒)。是什么原因?我是否使用了矩阵的错误表示或代码中存在很大的缺陷?
for (int c_b=0;c_b<B.n_c;c_b++)
{
vector<double> vtmp(A.n_r);
for (int r_a=0;r_a<A.n_r;r_a++)
{
sum=0;
for (int i=0;i < A.n_c;i++)
{
sum=sum+A.mat[r_a+i*A.n_r]*B.mat[i+c_b*B.n_r];
}
vtmp[r_a]=sum;
}
Cvv[c_b]=vtmp;
}
更新:此问题已通过使用Lapack中的子例程解决。
答案 0 :(得分:1)
以下是一些性能改进建议。
将矢量移到循环外
矢量的创建需要时间。在任何for循环之前移动声明:
vector<double> vtmp(A.n_r);
for (int c_b=0;c_b<B.n_c;c_b++)
{
for (int r_a=0;r_a<A.n_r;r_a++)
{
//...
}
}
剖析作业计算。
在没有任何分析或基准测试的情况下,赋值语句看起来占用了大部分时间。将它拆分为单独的步骤以帮助编译器,这样您就可以看到计算是否可以更加优化地执行
原文:
sum=sum+A.mat[r_a+i*A.n_r]*B.mat[i+c_b*B.n_r];
解剖[1]:
const int A_Index = r_a + i * A.n_r;
const int B_Index = i + c_b*B.n_r;
sum = sum + A.mat[A_Index] * B.mat[B_Index];
解剖[2](使用更多变量):
const int temp1 = i * A.n_r;
const int temp2 = c_b * B.n_r;
const int A_Index = r_a + temp1;
const int B_Index = i + temp2;
sum = sum + A.mat[A_Index] * B.mat[B_Index];
以上可以帮助编译器选择最佳处理器指令。
使用本地变量
理想情况下,您希望处理器在重新加载之前从矩阵获取数据缓存中的多个连续位置。像这样:
int ATemp1 = A[w];
int ATemp2 = A[x];
int ATemp3 = A[y];
int ATemp4 = A[z];
int BTemp1 = B[e];
int BTemp2 = B[f];
int BTemp3 = B[g];
int BTemp4 = B[h];
sum = sum + ATemp1 * BTemp1;
sum = sum + ATemp2 * BTemp2;
sum = sum + ATemp3 * BTemp3;
sum = sum + ATemp4 * BTemp4;