我有以下代码片段,可以将2×1024字段的矩阵相乘得到结果时间:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NUM 1024
float a[NUM][NUM],b[NUM][NUM],c[NUM][NUM];
void initialize_matrix(float m[][NUM]);
void load_matrix(float m[][NUM]);
int main() {
int i,j,k;
clock_t t_inicial,t_final;
load_matrix(a);
load_matrix(b);
initialize_matrix(c);
printf("Starting matrix multiplication 1024x1024...\n\n");
t_inicial=clock();
for(i=0;i<NUM;i++)
for(j=0;j<NUM;j++)
for(k=0;k<NUM;k++)
c[i][j] =c[i][j] + a[i][k] * b[k][j];
t_final=clock();
printf("Matrix multiplication finished in: %3.6f seconds",((float) t_final- (float)t_inicial)/CLOCKS_PER_SEC);
}
void initialize_matrix(float m[][NUM]) {
int i,j;
for(i=0;i<NUM;i++)
for(j=0;j<NUM;j++)
m[i][j]=0.0;
return;
}
void load_matrix(float m[][NUM]) {
int i,j;
#pragma omp parallel for
for(i=0;i<NUM;i++)
for(j=0;j<NUM;j++)
m[i][j]=(float) 10*rand()/(float) rand();
return;
}
此代码需要24秒才能解决,我已经被告知缓存内存有问题。如何改进此代码以缩短时间?它花了这么长时间并不是很好。
答案 0 :(得分:3)
刚刚交换
for(j=0;j<NUM;j++)
for(k=0;k<NUM;k++)
与
for(k=0;k<NUM;k++)
for(j=0;j<NUM;j++)
我有43倍的加速。就像你说的,改善缓存局部性。
甚至可以通过阻止(即交换
)来削减几毫秒for(j=0;j<NUM;j++)
for(j=0;j<NUM;j++)
for(k=0;k<NUM;k++)
通过
for(int i0=0; i0<NUM; i0+=BLK)
for(int k0=0; k0<NUM; k0+=BLK)
for(int j0=0; j0<NUM; j0+=BLK)
for(int i=i0, ix=i0+BLK; i<ix; ++i)
for(int k=k0, kx=k0+BLK; k<kx; ++k)
for(int j=j0, jx=j0+BLK; j<jx; ++j)
(我最好的选择是#define BLK 256
,但是YMMV)。
澄清:这是@Adriano引用的链接的答案,你真的应该在编辑问题之前查看它。
答案 1 :(得分:1)
这取决于您使用的编译器。使用GCC时,您可以使用__builtin_prefetch
,当然在请求优化(使用gcc -O3 -mtune=native
进行编译)之后。在基准测试后仔细使用它,请参阅this answer(例如在i
或j
循环中,以获取下一行)。
答案 2 :(得分:1)
矩阵乘法的直接实现不是非常缓存友好的。您被告知的评论可能是指阻塞,它将在块中进行乘法以改善局部性。 Here是一个参考。如果你谷歌用于&#34;缓存块矩阵乘法&#34;你会得到其他的点击。