CPU缓存对速度的影响

时间:2013-01-24 04:31:38

标签: c caching optimization pthreads cpu-architecture

我刚刚写了一个程序来测试CPU缓存对速度性能的影响。

void* foo(void* ptr)
{
    int* r = (int*) ptr;

    for (int i = (r - s); i < N; i += NUM_THREADS)
        *r += num[i];        
    return NULL;
}

void* bar(void* ptr)
{
    int* r = (int*) ptr;
    int idx = r - s;
    int block = N/NUM_THREADS;
    int start = idx * block, end = start + block;

    for (int i = start; i < end; ++i)
        *r += num[i];        
    return NULL;
}

基本上,foo()进行了隔行扫描,另一方面,bar()逐块扫描数组。

测试结果表明bar()要快得多:

gcc ping-pong.c -std=gnu99 -lpthread -O2  ; ./a.out
1.077037s
0.395525s

那么如何解释这个结果?

完整的源代码位于:https://gist.github.com/4617935

更新:删除所有if语句

2 个答案:

答案 0 :(得分:3)

事实证明这并不神秘。

我尝试了valgrind来分析缓存未命中,结果如下:

$ valgrind --tool=cachegrind --cachegrind-out-file=profile ./a.out
....
$ cg_annotate profile --auto=yes --show=D1mr --context=1
....
-- line 63 ----------------------------------------
    .  void* foo(void* ptr)
     0  {
     0      int* r = (int*) ptr;
     .  
     0      for (int i = (r - s); i < N; i += NUM_THREADS)
16,388          *r += num[i];
     0      return NULL;
     0  }
     .  
-- line 71 ----------------------------------------

-- line 72 ----------------------------------------
     .  void* bar(void* ptr)
     0  {
     0      int* r = (int*) ptr;
     0      int idx = r - s;
     0      int block = N/NUM_THREADS;
     0      int start = idx * block, end = start + block;
     .  
     0      for (int i = start; i < end; ++i)
 4,098          *r += num[i];
     0      return NULL;
     0  }

如您所见,foo()的L1缓存读取次数是bar的4倍,而4只是NUM_THREADS

正如@Mysticial回答的那样

  

顺序内存访问几乎总是超出非顺序访问。

由于更多非顺序内存访问意味着更多缓存未命中。

答案 1 :(得分:1)

顺序访问速度快得多的原因不是由于缓存结构,而是由于HW预取(这是相关的,但不相同)。有几个“流式”预取程序可以识别基于流或基于步幅的访问模式,并为您预先提取数据。

一些示例(英特尔CPU,但类似的主体也常用于其他CPU): http://software.intel.com/en-us/articles/optimizing-application-performance-on-intel-coret-microarchitecture-using-hardware-implemented-prefetchers

这里建议的valgrind分析表明了它,我建议再看一下L2 / L3 - 在大数据集上,有用的预取更有可能驻留在那里(经验法则 - 离你的核心越远,更多的时间和存储空间,您可以进行积极的预取。)