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)
答案 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())。如果出现以下情况,可获得最佳缓存性能: