此代码以四种方式转置矩阵。第一个进行顺序写入,非顺序读取。第二种则相反。接下来的两个是相同的,但缓存跳过写入。似乎发生的是顺序写入更快,跳过缓存更快。我不明白的是,如果跳过缓存,为什么顺序写入仍然更快?
QueryPerformanceCounter(&before);
for (i = 0; i < N; ++i)
for (j = 0; j < N; ++j)
tmp[i][j] = mul2[j][i];
QueryPerformanceCounter(&after);
printf("Transpose 1:\t%ld\n", after.QuadPart - before.QuadPart);
QueryPerformanceCounter(&before);
for (j = 0; j < N; ++j)
for (i = 0; i < N; ++i)
tmp[i][j] = mul2[j][i];
QueryPerformanceCounter(&after);
printf("Transpose 2:\t%ld\n", after.QuadPart - before.QuadPart);
QueryPerformanceCounter(&before);
for (i = 0; i < N; ++i)
for (j = 0; j < N; ++j)
_mm_stream_si32(&tmp[i][j], mul2[j][i]);
QueryPerformanceCounter(&after);
printf("Transpose 3:\t%ld\n", after.QuadPart - before.QuadPart);
QueryPerformanceCounter(&before);
for (j = 0; j < N; ++j)
for (i = 0; i < N; ++i)
_mm_stream_si32(&tmp[i][j], mul2[j][i]);
QueryPerformanceCounter(&after);
printf("Transpose 4:\t%ld\n", after.QuadPart - before.QuadPart);
编辑:输出是
Transpose 1: 47603
Transpose 2: 92449
Transpose 3: 38340
Transpose 4: 69597
最佳答案
CPU 有一个写入组合缓冲区,用于组合高速缓存行上的写入以在一次突发中发生。在这种情况下(顺序写入跳过缓存),此写入组合缓冲区充当作为单行缓存,这使得结果与未跳过缓存非常相似。
确切地说,在缓存被跳过的情况下,写入仍然以突发方式发生在内存中。
参见 write-combining logic这里的行为。
关于c中矩阵转置的缓存利用率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8549907/