Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3882944
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8585
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类: C/C++

2011-09-09 20:44:44

     存储器是分层次的,离CPU越近的存储器,速度越快,每字节的成本越高,同时容量也因此越小。寄存器速度最快,离CPU最近,成本最高,所以个数容量有限,其次是高速缓存(缓存也是分级,有L1,L2等缓存),再次是主存(普通内存),再次是本地磁盘。

                       



     寄存器的速度最快,可以在一个时钟周期内访问,其次是高速缓存,可以在几个时钟周期内访问,普通内存可以在几十个或几百个时钟周期内访问。

    
          (注 本图来自Ulrich Drepper大牛的讲稿,如有侵权,通知即删)

    存储器分级,利用的是局部性原理。我们可以以经典的阅读书籍为例。我在读的书,捧在手里(寄存器),我最近频繁阅读的书,放在书桌上(缓存),随时取来读。当然书桌上只能放有限几本书。我更多的书在书架上(内存)。如果书架上没有的书,就去图书馆(磁盘)。我要读的书如果手里没有,那么去书桌上找,如果书桌上没有,去书架上找,如果书架上没有去图书馆去找。可以对应寄存器没有,则从缓存中取,缓存中没有,则从内存中取到缓存,如果内存中没有,则先从磁盘读入内存,再读入缓存,再读入寄存器。

    本系列的文章重点介绍缓存cache。了解如何获取cache的参数,了解缓存的组织结构,了解cache对程序的影响,了解如何利用cache提升性能。

    
     本文作为系列文章的第一篇,讲述的如何获取cache的组成结构和如何获取cache的参数。

    cache分成多个组,每个组分成多个行,linesize是cache的基本单位,从主存向cache迁移数据都是按照linesize为单位替换的。比如linesize为32Byte,那么迁移必须一次迁移32Byte到cache。 这个linesize比较容易理解,想想我们前面书的例子,我们从书架往书桌搬书必须以书为单位,肯定不能把书撕了以页为单位。书就是linesize。当然了现实生活中每本书页数不同,但是同个cache的linesize总是相同的。

    所谓8路组相连( 8-way set associative)的含义是指,每个组里面有8个行。
 
    我们知道,cache的容量要远远小于主存,主存和cache肯定不是一一对应的,那么主存中的地址和cache的映射关系是怎样的呢?

    拿到一个地址,首先是映射到一个组里面去。如何映射?取内存地址的中间几位来映射。

    举例来说,data cache: 32-KB, 8-way set associative, 64-byte line size

    Cache总大小为32KB,8路组相连(每组有8个line),每个line的大小linesize为64Byte,OK,我们可以很轻易的算出一共有32K/8/64=64 个组。

    对于32位的内存地址,每个line有2^6 = 64Byte,所以地址的【0,5】区分line中的那个字节。一共有64个组。我们取内存地址中间6为来hash查找地址属于那个组。即内存地址的【6,11】位来确定属于64组的哪一个组。组确定了之后,【12,31】的内存地址与组中8个line挨个比对,如果【12,31】为与某个line一致,并且这个line为有效,那么缓存命中。

    OK,cache分成三类,
    1 直接映射高速缓存,这个简单,即每个组只有一个line,选中组之后不需要和组中的每个line比对,       因为只有一个line。

    2 组相联高速缓存,这个就是我们前面介绍的cache。 S个组,每个组E个line。

   3 全相联高速缓存,这个简单,只有一个组,就是全相联。不用hash来确定组,直接挨个比对高位地址,来确定是否命中。可以想见这种方式不适合大的缓存。想想看,如果4M 的大缓存 linesize为32Byte,采用全相联的话,就意味着4*1024*1024/32 = 128K 个line挨个比较,来确定是否命中,这是多要命的事情。高速缓存立马成了低速缓存了。

   描述一个cache需要以下参数 :
    1 cache分级,L1 cache, L2 cache, L3 cache,级别越低,离cpu越近
    2  cache的容量
    3  cache的linesize
    4  cache 每组的行个数.
    组的个数完全可以根据上面的参数计算出来,所以没有列出来.
    Intel手册中用这样的句子来描述cache:
    8-MB L3 Cache, 16-way set associative, 64-byte line size 

    如何获取cache的参数呢,到了我们的老朋友cpuid指令,当eax为0x2的时候,cpuid指令获取到cache的参数. 下面给出代码:

   
  1. #include
  2. #include

  3. int d_eax;
  4. int d_ebx;
  5. int d_ecx;
  6. int d_edx;

  7. int parse_cache()
  8. {
  9. asm
  10.          (
  11.   "movl $2,%eax\n\t"
  12.   "cpuid\n\t"
  13.   "mov  %eax,d_eax\n\t"
  14.   "mov  %ebx,d_ebx\n\t"
  15.   "mov  %ecx,d_ecx\n\t"
  16.   "mov  %edx,d_edx\n\t"
  17.          );
  18. printf("d_eax : %x\nd_ebx : %x\nd_ecx : %x\nd_edx : %x\n",
  19.        d_eax,d_ebx,d_ecx,d_edx);
  20. return 0;
  21. }
  22. int main()
  23. {
  24. parse_cache();
  25. return 0;
  26. }

  1. root@libin:~/program/assembly/cache# ./test
  2. d_eax : 55035a01
  3. d_ebx : f0b2dd
  4. d_ecx : 0
  5. d_edx : 9ca212c
    我的电脑上运行结果如上图,查看intel的手册可知
  1. EAX
  2. (55h) Instruction TLB: 2-MB or 4-MB pages, fully associative, 7 entries
  3. (03h) Data TLB: 4-KB Pages, 4-way set associative, 64 entries
  4. (5Ah) Data TLB0: 2-MB or 4-MB pages, 4-way associative, 32 entries
  5. (01h) Instruction TLB: 4-KB Pages, 4-way set associative, 32 entries
  6. EBX:
  7. (F0h) 64-byte Prefetching
  8. (B2h) Instruction TLB: 4-KB pages, 4-way set associative, 64 entries
  9. (DDh) 3rd-level cache: 3-MB, 12-way set associative, 64-byte line size
  10. EDX:
  11. (09h) 1st-level Instruction Cache: 32-KB, 4-way set associative, 64-byte line size
  12. (CAh) Shared 2nd-level TLB: 4-KB pages, 4-way set associative, 512 entries
  13. (21h) 256KB L2 (MLC), 8-way set associative, 64-byte line size
  14. (2Ch) 1st-level data cache: 32-KB, 8-way set associative, 64-byte line size

参考文献:
1 Intel® Processor Identification andthe CPUID Instruction
2 Professional Assembly Language  Richard Blum著
3 深入理解计算机系统







阅读(24087) | 评论(4) | 转发(13) |
给主人留下些什么吧!~~

Bean_lee2011-10-30 09:29:18

Heartwork: 一点小问题:在组内查找对应哪一行命中的时候使用的是并行的搜索算法,如果使用顺序查找的话,组内的行数越多,效率也就越低。那样的话象全相联高速缓存就没有存.....
兄弟说的有道理,如果cache非常大,仍然选用并行搜索的算法,那么,硬件上会有很多比较器。比如4M  cache,linesize=64,那么就要有65536个tag需要比较,如果完全并行,那么硬件电路就太大了,如果如我所说的串行,那么又太慢。所以大容量的cache一般不采用全相联。

ulrich drepper也提到过这个问题,intel的TLB 采用的是全相联的cache。一般来讲,少于几十条的可以采用全相联。

Heartwork2011-10-26 16:32:37

GFree_Wind: 如果做到并行搜索呢?.....
硬件本身提供支持。

GFree_Wind2011-10-11 12:22:22

Heartwork: 一点小问题:在组内查找对应哪一行命中的时候使用的是并行的搜索算法,如果使用顺序查找的话,组内的行数越多,效率也就越低。那样的话象全相联高速缓存就没有存.....
如果做到并行搜索呢?

Heartwork2011-09-19 10:44:51

一点小问题:在组内查找对应哪一行命中的时候使用的是并行的搜索算法,如果使用顺序查找的话,组内的行数越多,效率也就越低。那样的话象全相联高速缓存就没有存在的意义了。