当我使用不同的方法进行矩阵乘法和测量执行时间时,我对这些结果提出了一些疑问。
矩阵:float A[N][N], B[N][N], C[N][N];
IJK :
for (i=0; i<N; i++)
for (j=0; j<N; j++)
for (k=0; k<N; k++)
C[i][j] = C[i][j] + A[i][k] * B[k][j];
JKI :
for (j=0; j<N; j++)
for (k=0; k<N; k++)
for (i=0; i<N; i++)
C[i][j] = C[i][j] + A[i][k] * B[k][j];
KIJ :
for (k=0; k<N; k++)
for (i=0; i<N; i++)
for (j=0; j<N; j++)
C[i][j] = C[i][j] + A[i][k] * B[k][j];
IJK :
for (i=0; i<N; i++) {
for (j=0; j<N; j++) {
aux = C[i][j];
for (k=0; k<N; k++) {
aux = aux + A[i][k] * B[k][j];
}
C[i][j] = aux;
}
}
JKI :
for (j=0; j<N; j++) {
for (k=0; k<N; k++) {
aux = B[k][j];
for (i=0; i<N; i++) {
C[i][j] = C[i][j] + A[i][k] * aux;
}
}
}
KIJ :
for (k=0; k<N; k++) {
for (i=0; i<N; i++) {
aux = A[i][k];
for (j=0; j<N; j++) {
C[i][j] = C[i][j] + aux * B[k][j];
}
}
}
更突出的是“ JKI”超过大小512所花费的时间增加。我猜这是因为矩阵无法容纳超过该大小的缓存,而“ JKI”的问题在于所有访问都是从上到下bot并从左到右,而不是从左到右,从上到下是bot,就像“ IJK”中的C和A以及“ KIJ”中的C和B一样。如果每当在高速缓存中加载一个块时发生另一种情况,那么下次访问就会被命中,这就是为什么'IJK'和'KIJ'更快的原因。如果我错了请纠正我。
我无法克服的是为什么“ KIJ”比“ IJK”更快。应该不一样吗? [q1]
为什么在'JKI'中使用辅助字符,据说减少对内存的访问与普通的'JKI'具有相同的执行时间? [q2]
最后,为什么用'-O2'标志在'KIJ'中大大减少了执行时间,而在'JKI'中却几乎没有改变? [q3] 我也想知道真正的做-O2来优化。
最终结论:从这6个示例中可以得出带有辅助词的“ KIJ”。我想知道是否有更快的算法。 [q4]