找回密码
 欢迎注册
查看: 12936|回复: 2

[讨论] 通过一个程序说明cache命中率对内存访问速度的影响

[复制链接]
发表于 2011-11-8 19:47:09 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
我们知道,现代的CPU包含cache部件,cache亦称高速缓冲,其中存储了CPU最近访问过的或者将要访问的数据。和通常的RAM相比,cache也是一种存储器,其特点存储速度非常快,但同样容量的cache比同样的RAM成本高了很多,因此不能做的太大。 cache亦采用多级存储结构,通常的CPU有8-64K的一级cache,256K-12M的2级cache,有的CPU还有3级cache.许多现代的CPU的2级cache与CPU同频,因此速度非常快。 按照intel的说法,在通常情况下,对RAM的访问实际上近似等同于对cache的访问,因为在90%以上的情况下,RAM中的数据已经被缓冲到cache. 因为程序对RAM的访问具有局部性,也就是说,下次访问的数据的地址和这次访问的数据的地址相邻,所有当访问d[ i ]时,CPU的后台"程序"自动把和d[ i ]相邻的数据载入cache. 下次访问d[ i+1 ]时,可直接从cache中读写数据. 只用当访问的数据不在cache中,CPU才直接从RAM读取数据,由于RAM的很高的延时,故直接从RAM中读写数据比从cache中读写数据要慢得多。 显然,对数据的顺序访问具有极高的cache命中率,因此对数据的顺序访问的性能几乎可达到内存带宽这个上限。内存带宽指内存和cache间批量数据传递的速率,注意内存带宽和内存延时无必然的联系,因为通常情况下,CPU在后台做内存和cache间数据交换,所有内存的高延时被隐藏了。 反之,对数据的随机访问则使得cache命中率大大降低,一旦cache未命中,CPU不得不与内存之间交换数据,此时,内存的高延时就成为瓶颈。 楼下的代码分别测试 对1M*4,4M*4,16M*4,64M*4的内存块进行顺序读取和随机读取所耗费的时间。其速度比如下(测试机的L2 cache is 6M) 块大小 速度比 4M 3.0 16M 7.1 64M 11.2 256M 12.5

cache_test.zip

3.38 KB, 下载次数: 7, 下载积分: 金币 -1 枚, 经验 1 点, 下载 1 次

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2011-11-8 19:50:55 | 显示全部楼层
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <memory.h>
  4. #include "currTime.h"
  5. typedef unsigned long DWORD;
  6. void initAccessTable(int accessTab[], int len, int isRand )
  7. {
  8. int i,idx;
  9. if (isRand==0) //sequential access
  10. {
  11. for (i=0;i<len;i++)
  12. {
  13. accessTab[i]=i;
  14. }
  15. }
  16. else
  17. {
  18. char *tmpBuff=(char *)malloc(len);
  19. memset(tmpBuff,0,len);
  20. for (i=0;i<len;)
  21. {
  22. idx= ((rand() << 15)+ rand()) % len;
  23. if ( tmpBuff[idx]==0)
  24. {
  25. accessTab[i++]=idx;
  26. tmpBuff[idx]=1;
  27. }
  28. }
  29. free(tmpBuff);
  30. }
  31. }
  32. int sum(DWORD pBuff[], int accessTab[], int len)
  33. {
  34. DWORD s=0;
  35. int i,idx;
  36. for (i=0;i<len;i++)
  37. {
  38. idx=accessTab[i];
  39. s += pBuff[idx];
  40. }
  41. return s;
  42. }
  43. //mode=0, sequential access
  44. //mode=1, random access
  45. void test_access_RAM(int blk_len, int mode)
  46. {
  47. DWORD *pBuff=malloc(sizeof(DWORD)*blk_len);
  48. int *accessTab=malloc(sizeof(int)*blk_len);
  49. DWORD i,s;
  50. double t;
  51. for (i=0;i<blk_len;i++)
  52. {
  53. pBuff[i]=rand() & 15;
  54. }
  55. initAccessTable(accessTab, blk_len, mode);
  56. t=currTime();
  57. s=sum(pBuff,accessTab,blk_len);
  58. t=currTime()-t;
  59. printf("s=%d\n",s);
  60. if ( mode ==0)
  61. printf("sequential access %d number, it take %.6f ms\n",blk_len,t*1000 );
  62. else
  63. printf("random access %d number, it take %.6f ms\n",blk_len,t*1000 );
  64. free(pBuff);
  65. free(accessTab);
  66. }
  67. void test()
  68. {
  69. int blk_len;
  70. int i,loop;
  71. loop=3;
  72. blk_len=1024*1024;
  73. for (i=0;i<loop;i++)
  74. { test_access_RAM(blk_len,0); }
  75. for (i=0;i<loop;i++)
  76. { test_access_RAM(blk_len,1); }
  77. //----------------------------
  78. blk_len=4*1024*1024;
  79. for (i=0;i<loop;i++)
  80. { test_access_RAM(blk_len,0); }
  81. for (i=0;i<loop;i++)
  82. { test_access_RAM(blk_len,1); }
  83. //----------------------------
  84. blk_len=16*1024*1024;
  85. for (i=0;i<loop;i++)
  86. { test_access_RAM(blk_len,0); }
  87. for (i=0;i<loop;i++)
  88. { test_access_RAM(blk_len,1); }
  89. //----------------------------
  90. blk_len=64*1024*1024;
  91. for (i=0;i<loop;i++)
  92. { test_access_RAM(blk_len,0); }
  93. for (i=0;i<loop;i++)
  94. { test_access_RAM(blk_len,1); }
  95. }
  96. int main(int argc, char* argv[])
  97. {
  98. test();
  99. return 0;
  100. }
复制代码
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2011-11-9 01:53:05 | 显示全部楼层
的确,random access 现在已经不能简单认为是O(1)了,但是细化的研究还是比较欠缺,做cache的还是做编译器的比较多,系统里面大家对cache的认识都比较简化。 最近在思索如果提供给programmer在cache-aware 的programming model,但又不至于增加复杂度
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-22 04:21 , Processed in 0.023506 second(s), 20 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表