C 当存在';大步预取?

C 当存在';大步预取?,c,caching,prefetch,C,Caching,Prefetch,在C语言中,你被告知按行主顺序遍历矩阵,因为这是数组存储在引擎盖下的方式,行主迭代利用整个缓存线,从而减少缓存未命中。事实上,在我的机器上,我确实看到了行主迭代和列主迭代之间的巨大性能差异。测试代码: #include <stdio.h> #include <stdlib.h> #include <time.h> #include <sys/resource.h> int getTime() { struct timespec tsi;

在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);
}
#包括
#包括
#包括
#包括
int getTime()
{
结构timespec tsi;
时钟获取时间(时钟单调,&tsi);
双elaps=tsi.tv秒;
long elaps\u ns=tsi.tv\u nsec;
返回值(int)((elaps_s+((double)elaps_ns)/1.0e9)*1.0e3);
}
#定义N 1000000
#定义M 100
void main()
{
int*src=malloc(sizeof(int)*N*M);
int**arr=malloc(sizeof(int*)*N);
对于(int i=0;i

然而,现代内存系统有预取器,它可以预测跨步访问,当你遍历一列时,你会遵循一个非常规则的模式。这不应该允许列主迭代执行与行主迭代类似的操作吗?

缓存线具有一定的大小(例如64字节),处理器读取和写入完整的缓存线。比较处理的字节数和读写的字节数

我认为这不是功能可用性的问题,而是C支持它的问题。此外,如果循环遵循内存顺序,SIMD优化会容易得多。正确。此外,一些步幅预取器对步幅范围有限制。