数组遍历与指针,缓存效率方面

时间:2012-06-27 13:44:17

标签: c++ arrays caching pointers

void foo(Node* p[], int size){

    _uint64 arr_of_values[_MAX_THREADS];


    for (int i=0 ; i < size ; i++ ){
         arr_of_values[i] = p[i]->....;

         // much code here 
         // 
      }
 }

VS

void foo(Node* p[], int size){

    _uint64 arr_of_values[_MAX_THREADS];

    Node* p_end = p[size];
    for ( ; p != p_end ; ){            
         arr_of_values[i] = (*p)->.....;
         p++;


         // much code here 
         // 
     }

}

我创建了这个函数来演示我在问什么:

从缓存效率方面来看效率更高:采用p [i]或使用* p ++?

(我永远不会在代码的其余部分使用p [i-x],但我可以在下面的计算中使用p [i]或* p)

2 个答案:

答案 0 :(得分:2)

最重要的是避免arr_of_values中的false sharing。每个线程写入自己的插槽,但8或16个插槽共享一个高速缓存线(取决于CPU),导致大量的错误共享问题。在插槽之间添加填充以缓存对齐每个线程的插槽,或者在堆栈上累积并在结尾处只写一次:

void foo(Node* p[], int size){

    _uint64 arr_of_values[_MAX_THREADS];

    Node* p_end = p[size];
    for ( ; p != p_end ; ){            
         temp = .....;
         p++;
         // much code here 
         // 
     }  
     arr_of_values[i] = temp;
}

指针访问或索引访问的问题与今天的编译器无关。

您的下一步行动应该是:抓取the Software optimization Cookbook的副本。阅读。测量。修复测量的热点,而不是猜测。

答案 1 :(得分:1)

从缓存的角度来看,问题不在于您访问元素的方式。在这种情况下,使用指针或数组索引是等效的。

BTW Node * p []是一个指针数组。因此,您可能已将Node对象分配到远程内存区域。 (例如,使用几个ptr = new Node())。如果出现以下情况,可获得最佳缓存性能:

  1. 您的节点被连续存储到内存中
  2. 节点大小不超过缓存大小。