以编程方式测量关联方式

时间:2018-03-05 17:28:15

标签: c cpu-cache

我正在制作一个简单的C程序来了解我的CPU的关联方式。

我知道: 我的缓存大小为32Kb(L1),行大小为64字节。从那里我知道有500行。

我的方法是访问整数的第一个8192元素(32 kb),看看它需要更长的时间,如果每x次迭代需要更长的时间,那么x就是相关性的方式

但是,我得到的结果没有显示:

it should show a spike at every x iteration?

这是我的C代码:

void run_associativity_test() { 
  int j = 1;
  // 8192 * 4 bytes (int) is 32 kb
  while (j <= 8192 * 2) {
    get_element_access_time(j);
    j = j + 1;
  }
}

double get_element_access_time(int index) {
  struct timespec start_t, end_t;
  double start, end, delta;

  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_t);
  arr[index] += 1;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_t);

  start = 1000000000 * start_t.tv_sec + start_t.tv_nsec;
  end = 1000000000 * end_t.tv_sec + end_t.tv_nsec;
  delta = end - start;

  if (mode == 2 || mode == 3) {
    printf("%d, %lf\n", index, delta);
  }

  return delta;
}

我的方法有误吗?我该怎么办?

另外,我发现了一篇论文here,解释了如何衡量关联方式,尽管我无法理解它。如果有人向我简要解释一下测量相关性的论文中的方法,我将感激不尽。

谢谢!

1 个答案:

答案 0 :(得分:1)

这可能更像是一个评论而不是一个答案,但它太大了,不能将其作为评论发布。

  

我知道:我的缓存大小为32Kb(L1),行大小为64字节。从   我知道有500行。

缓存的大小为2 ^ 15个字节。所以有2 ^ 15/2 ^ 6 = 2 ^ 9 = 512个缓存行。

  while (j <= 8192 * 2) {

我认为数组的大小是8192 int s,而不是(8192 * 2)+ 1 int s。

get_element_access_time(j); 
j = j + 1;

缓存行可以容纳16 int秒。顺序访问阵列的元素将导致最多1/16的未命中率,这取决于L1D预取器。使用该访问模式估计L1D高速缓存中的路数是很困难的。我认为最好的方法是在相同的缓存集中进行抖动。

让我们忘记目前的L1D预取器。另外,我们只考虑使用内存地址的第6-11位或其子集作为高速缓存集索引的L1D高速缓存。例如,如果缓存是8路关联的,则会有2 ^ 9/2 ^ 3 = 64个集合,这意味着所有的位6-11都用于索引。

如何检查缓存是否为8向关联?通过访问相同的8个缓存行,这些缓存行将多次映射到同一缓存集(例如一百万次或更多次)。如果高速缓存的关联性至少为8,则执行时间应该比关联性小于8时更好。这是因为在前一种情况下,只有8次未命中(对于8个高速缓存行)但在后一种情况下由于并非所有高速缓存行都可以在L1D高速缓存中同时存在,因此会有许多未命中。为了使您的测量尽可能准确,我们希望最大化L1D未命中罚分。一种可能的方法是写入L1D而不是读取。这迫使L1D回写所有被驱逐的缓存行,这有望对性能产生可测量的影响。另一种方法是最大化L2D未命中数。

编写具有此类访问模式的程序相对容易。一旦您知道关联性是否小于8,您可以通过类似地测试其他较小范围的关联性来进一步关闭关联性。请注意,您只需要写入缓存行中的一个元素。同样重要的是确保刷新核心写缓冲区的每个写入。否则,许多写操作可能只是在写缓冲区而不是缓存上执行。基本上这可以通过使用volatile关键字(我认为?)或存储围栏来完成。

  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start_t);
  arr[index] += 1;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end_t);

这没有任何意义。定时器的分辨率并不高,无法精确测量单个存储器写操作的延迟。所以你应该测量所有访问的执行时间。

L1D预取器可能会干扰测量,可能会使缓存看起来具有比实际更高的关联性。如果可能,请将其关闭。

如果L1D缓存使用6-11之外的位来索引缓存,则虚拟内存会起作用,这会使准确估计关联性变得更加复杂。