在矩阵乘基准测试(来自matrix_mult套件的Metis中)中,我遇到了一个奇怪的性能问题。对基准测试进行了优化,使数据平铺,使活动工作集为12 L1 (3块32x32个into ),并适合于L1缓存。长话短说,在某些数组输入大小(4096,8192)上,交换内两大循环的性能差异几乎为4倍,而在其他数组输入大小上的性能差异约为30%。问题本质上归结为按顺序访问元素,而不是按步调模式访问元素。我认为,某些数组大小造成了错误的跨步访问,产生了大量的缓存行冲突。当从双向结合L1转变为8路结合L1时,性能差异明显减小.
我的问题是为什么gcc不优化循环顺序来最大化顺序内存访问?
下面是问题的简化版本(请注意,性能时间高度依赖于L1配置。下面显示的数字来自2.3GHzAMD系统与64K L1双向结合编译与-O3)。
N = ARRAY_SIZE // 1024
int* mat_A = (int*)malloc(N*N*sizeof(int));
int* mat_B = (int*)malloc(N*N*sizeof(int));
int* mat_C = (int*)malloc(N*N*sizeof(int));
// Elements of mat_B are accessed in a stride pattern of length N
// This takes 800 msec
for (int t = 0; t < 1000; t++)
for (int a = 0; a < 32; a++)
for (int b = 0; b < 32; b++)
for (int c = 0; c < 32; c++)
mat_C[N*a+b] += mat_A[N*a+c] * mat_B[N*c+b];
// Inner two loops are swapped
// Elements are now accessed sequentially in inner loop
// This takes 172 msec
for (int t = 0; t < 1000; t++)
for (int a = 0; a < 32; a++)
for (int c = 0; c < 32; c++)
for (int b = 0; b < 32; b++)
mat_C[N*a+b] += mat_A[N*a+c] * mat_B[N*c+b];https://stackoverflow.com/questions/9476939
复制相似问题