【发布时间】:2016-06-27 15:19:05
【问题描述】:
在 C 语言中,您被告知以行优先顺序遍历矩阵,因为这就是数组在底层存储的方式,并且行优先迭代利用了整个缓存行,从而减少了缓存未命中。事实上,我确实看到我的机器上的行优先和列优先迭代之间存在巨大的性能差异。测试代码:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/resource.h>
int getTime()
{
struct timespec tsi;
clock_gettime(CLOCK_MONOTONIC, &tsi);
double elaps_s = tsi.tv_sec;
long elaps_ns = tsi.tv_nsec;
return (int) ((elaps_s + ((double)elaps_ns) / 1.0e9) * 1.0e3);
}
#define N 1000000
#define M 100
void main()
{
int *src = malloc(sizeof(int) * N * M);
int **arr = malloc(sizeof(int*) * N);
for(int i = 0; i < N; ++i)
arr[i] = &src[i * M];
for(int i = 0; i < N; ++i)
for(int j = 0; j < M; ++j)
arr[i][j] = 1;
int total = 0;
int pre = getTime();
for(int j = 0; j < M; ++j)
for(int i = 0; i < N; ++i)
total += arr[i][j];
/*
for(int i = 0; i < N; ++i)
for(int j = 0; j < M; ++j)
total += arr[i][j];
*/
int post = getTime();
printf("Result: %d, took: %d ms\n", total, post - pre);
}
但是,现代内存系统具有可以预测跨步访问的预取器,并且当您遍历列时,您会遵循非常规则的模式。这不应该允许列优先迭代类似于行优先迭代吗?
【问题讨论】:
-
我认为这不是可用功能的问题,而是 C 支持它的问题。 Here's some GCC documentation about it.
-
如果您的循环遵循内存顺序,SIMD 优化也会容易得多。