关于intel core 2 L1的cache测试

这两天在看intel的cache。因为core 2 架构和xeon属于一个套路,所以就拿自己的I5-2500开刀。根据资料,L1 CACHE是8way,估计128bytes一条,32kbytes,也就是相同32kbytes的偏移数据会相互打架。因此我做个测试。基本原理是,使 用同一个函数。只是调整步长,使得他们访问的基准点一样,只是顺序不一样,之所以说是基准点,是因为我还要用偏移点进行洗CACHE操作。由于是一个函 数,一样的访问量,所以剔除了代码运行的差异。采用O2编译,如下函数

01 volatile int data,count;
02 unsigned long long travel_matrix(int h,int w,int step1,long long  step2 ,char *p){
03     int i,j;
04     char *pp = p;
05     unsigned long long re;
06     count = data = 0;
07     CPU_CLK_START();
08     for (i = 0 ; i < h ; i++){
09         for (j = 0 ; j < w; j++,p+=step1){
10                    p[8*step1] =data;
11                     p[0] =data;
12  
13             //printf("%4x ",p - pp);
14         }
15         //printf("\n");
16         p+=step2;
17     }
18     CPU_CLK_END(re);
19     return re;
20 }
21  
22 unsigned long long travel_hor(int h,int w,int stride,char *p){
23     return travel_matrix(h,w,1,(long long)(stride - w),p);
24 }
25 unsigned long long travel_ver(int h,int w,int stride,char *p){
26     return travel_matrix(w,h,stride,(long long)(1-h*stride),p);
27 }

你可以通过打开上面的注释,确定循环次数相同,对于p[0]这个位置也是完全相同只是顺序不一样,一个是可以看作先从左到右,一个可以看作先从上到下。

在外侧调用上述两个函数如下

01 #define MAX_X 4*1024
02 #define MAX_Y 8
03 #define L1_BUF_SIZE MAX_X * MAX_Y  
04     for (step = 2; step <= MAX_Y *4 ; step*=2){
05         page_size = L1_BUF_SIZE / step;
06         hor = travell_hor(step,page_size,page_size,p);
07         ver = travell_ver(step,page_size,page_size,p);
08         hor += travell_hor(step,page_size,page_size,p);
09         ver += travell_ver(step,page_size,page_size,p);
10         hor += travell_hor(step,page_size,page_size,p);
11         ver += travell_ver(step,page_size,page_size,p);
12         fprintf(stderr,"step %d stride %d %8.3f \n",step,page_size,(double)ver/hor);   
13     }

当page_size等于 4*1024时就搞笑了如下。

1 step 2 stride 16384    3.444
2 step 4 stride 8192    3.582
3 step 8 stride 4096    9.101
4 step 16 stride 2048    8.375
5 step 32 stride 1024    4.807

时间差了9倍。真是可爱的CACHE。

这是因为,L1 CACHE是8way的。由于是 32Kbytes。所以每个way最多4Kbytes。而此时是强迫写,OS貌似对CACHE的写回机制设置的32Kbytes强制一个way。而在内侧 循环中,下次需要使用p[4*1024*X] 的内容,这个在不同的way里面。而p[8*4*1024]则始终要洗掉一个way。

可能有人说,我这个很过分,因为横向 扫描只有最后8个点不在L1内,而纵向扫描实际上是访问或操作了64kbytes的数据。

哈,这里得说下way。如果还不知道8way 什么意思,你可以把上面travel_matrix的代码修改如下:

1 for (i = 0 ; i < h ; i++){
2         for (j = 0 ; j < w; j++,p+=step1){
3             p[8*step1+128] = data;
4             p[0] =data;
5             //printf("%4x ",p - pp);
6         }
7         //printf("\n");
8         p+=step2;
9     }

你会发现时间如同彩票一样,就在赌 32K+128是否踩狗屎的进了p[0]的那个way。没有进,恭喜,时间差不多,如果进了,恭喜,你又慢了。

上面的例子虽然极端,但是如果你的代码特别是C代码,说实话,JAVA 我真不知道他如何操作的,如果尝试对32Kbytes偏移量的数据进行操作,你要小心了。同时,CACHE机制灵活使用,确实可以发挥机器性能。不过要求你尽可能保证你的指针的偏移量别跨的太多。

 

中山野鬼:一直没看到Sandy Bridge 架构下L3 cache的资料。不知道哪位朋友指引一下。哪可以找到。

你可能感兴趣的:(关于intel core 2 L1的cache测试)