据说对于普通 x86 cpu(i7 mac),cpu 缓存行大小为 64 字节,因此如果使用数组大小<64,它将仅存在于一个缓存行中并且速度很快,当缓存行大小为越大,程序会变慢。
下面是我的程序:
#include<sys/time.h>
#include<stdlib.h>
#include<stdio.h>
size_t cacheline=16;
int main(int argc,char*argv[]){
size_t loopCount=2000000000;
if(argc==2){loopCount=atol(argv[1]);}
printf("loop=%ld\n",loopCount);
int array[cacheline];
for(size_t a=0;a<cacheline;++a){
array[a]=a;
}
size_t c=0;
long sum=1;
for(size_t i=0;i<loopCount;++i){
if(c==cacheline)c=0;
sum+=array[c++];//
}
printf("sum=%ld\n",sum);
return 0;
}
clang++ test07_cacheline.cpp -O2 -o test07_cacheline && time ./test07_cacheline 2000000000
loop=2000000000
sum=63354543092609
real 0m2.810s
user 0m2.794s
sys 0m0.009s
但在我的测试程序中我发现,无论我将“数组”的大小设置为16、64、256或65536,时间执行时间基本相同。理论或我的程序设计有什么问题?我也尝试了一些来自互联网的其他程序,结果相同,如下所示:
#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
long timediff(clock_t t1,clock_t t2){
return (t2-t1)*1000/CLOCKS_PER_SEC;
}
int main(int argc,char*argv[]){
int array_size=65536;
if(argc>=2)array_size=atoi(argv[1]);
int repeat_times=2000000000;
long array[array_size];
for(int i=0;i<array_size;++i){
array[i]=i;
}
int j=0;
int k=0;
int c=0;
clock_t start=clock();
while(j++<repeat_times){
if(k==array_size){k=0;}
c+=array[k++];
}
clock_t end=clock();
printf("c=%d,%lu\n",c,timediff(start,end));
return 0;
}
g++ test08_cacheline.cpp -O2 -o test08_cacheline && ./test08_cacheline
c=1865233920,2800
无论array_size如何位。那么关于高速缓存行如何影响我的程序性能的任何解释?
最佳答案
您缺少的是这两个执行都在利用数据局部性。
您正在读取连续数组。您的缓存将读取数组的连续 block 。唯一的区别在于您加载 block 的次数。
这个数字并没有那么大,此外,编译器能够预测何时加载新 block ,尤其是当您标记了一些优化规则(例如矢量化)时。
更多信息请阅读here
如果您想了解性能如何变化,请尝试以这种方式修改您的代码:
while(j++<repeat_times){
if(k==array_size){k=0;}
int position = ((c+k)*j)%array_size;
c+=array[position];
k++;
}
这样您将失去数据本地性。
更新
性能更多地取决于内存访问模式而不是缓存大小。更准确地说,如果程序主要是顺序的,缓存大小就不是什么大问题。如果有相当多的随机访问,缓存大小真的很重要。
如果您想尝试查看缓存大小如何导致不同的性能,您可以尝试:
- 删除随机访问的数据局部性
- 然后改变数组的大小。
通过这种方式,如果每次随机访问数组的大小都适合您的缓存,则该 block 将已经进入缓存。
注意您不是唯一在您的 PC 上使用缓存的人!
关于c - Linux C++ : test of the cacheline size performance effect not as expected,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43559277/