CS巴别塔(1)

面试宝典3:计算机体系结构

Posted in Uncategorized by Kenny Yuan on 2010/10/31

(这段声明还是加上比较好:此《宝典》系列虽然名为“宝典”,但写的都是一些“不知道就别出来混”的基础知识。这一篇也仍然还是基础中的基础,而并非是什么高级货色——任何一个合格的在校本科生,学过计算机体系结构这门课的,都要懂得多得多——在我看来唯一可被理解的例外是那些在当年上学时,被劣质教材和老师害了的人。本文末尾有一本推荐的书籍,建议此类人士进补)

Human-Architecture

Human-Architecture

让我们来假设,有那么一天,作为软件工程师的你,面对这样一道Computer Architecture面试题:

程序在运行时,计算机内部到底会发生什么样的事情?

在继续阅读之前,请你先回想一下相关知识,并估算一下所涉及知识点的数量:

A. <10个;

B. 10-50个;

C. 50-100个;

D. >100个

请选择: ______。

……

以下,是我的回答(非标准答案,供参考):

首先是要搞清楚这台机器具有什么类型的ISA。ISA有四种:Stack,Accumulator,Register-Memory,Load-Store。现代的处理器都是Reg-Mem或者Load-Store的,或者说:有一些ISA,表面上是Reg-Mem这样的一只被汇编程序员所喜爱的喜羊羊,实际上它也是一头Load-Store的灰太狼(例如x86就是在CPU内部进行翻译的)。Stack类型的ISA似乎已经没有流行的硬件了,但是在许多Virtual ISA——也就是在各种高级语言虚拟机(HLL VM)中,却非常地流行。究其根本原因,应该是为了在各种不同的机器上移植的方便(因为这种结构对寄存器没有特别的要求)。

如果是Load-Store的ISA,那么可以肯定它是一个RISC处理器,那么它必有pipeline。例如经典的MIPS的5段流水线(ARM是3)。前面刚刚说过,不仅仅是RISC处理器,连x86也是把翻译出来的RISC操作码发射到超标量流水线中。这些辛辛苦苦翻译出来的操作码会用一个cache来缓存,名为trace cache。如果是RISC指令,因为其格式固定,还可以对其进行固定位置解码(fixed-field decoding)。在pipeline中,也有一些对软件透明,所以不太出名的部件,比如pipeline register,用来在各个stage之间传递数据。

pipeline不是随时都在满负荷工作的,时不时地会有一些停顿(stall),比如:因为结构冒险(structural hazard)引起的停顿。结构冒险是流水线冒险的一种,举例说明:如果register file的并行读写操作太多,port已经用光了,那么就会有一个停顿插入流水线;如果指令和数据都是存在同一个存储器中(冯·诺依曼结构),在同一时刻内又有WB(写回数据)和IF(取指令)的冲突,那么就需要插入一个停顿(也叫pipeline bubble)。哈佛结构不存在这种限制,而现代的冯·诺依曼处理器将Data Cache和Instruction Cache分开,也没有这种限制了(是的,不光是CISC和RISC,哈佛和诺依曼的界限也不是那么清晰了)。

(上面说到了存储器,我们先记下,一会接着再说它,否则就失去连续性了)

引起pipeline stall的原因,除了structural hazard,还有可能是control hazard控制冒险,比如各种转移(branch)。有了转移,就需要对转移进行预测,以便提高效率,否则流水线的损失太大太大。一般常用的转移预测(branch prediction)有这样几种:2-bit历史预测,多级相关预测(比如2级2bit 4KiB)。要进行这些预测,就需要额外的存储,一般CPU内建有BTB也就是branch target buffer。有些CPU中有多个这样的BTB,用于不同的预测,比如有的专门用来预测局部的转移(local branch prediction)。

有些转移是无条件的,比如call和jmp(goto),在现代处理器中对这种无条件的转移基本可做到不需耗费额外时钟周期。还有一种特殊类型的转移预测:return address prediction。我记得有个数据在C++或者JAVA这种高级语言中RET会占15%左右的转移总量,有了这个数据,这种类型的预测立即就有了意义:) 同理,对loop进行专门的loop prediction也是很有意义的。

除了前面说的两种,还有一种流水线冒险:数据冒险(data hazard)。数据冒险有三种,RAW(Read After Write),WAW(Write After Write)和WAR(Write After Read)。如果对R和W进行排列组合的话,其实还有RAR。但是我喜欢7z,不喜欢RAR,所以我说RAR不存在数据冒险(于是它就没有数据冒险)。

对于WAW和WAR,可以通过寄存器重命名(register renaming)来解决,也就是说,汇编大佬们注意了:CPU并不诚实,它欺骗了你,还一笑而过……嘿嘿……另一个可能会让汇编大佬伤心的事实是:处理器会乱序执行(out of order execution)多数指令(需要ROB — Re-Order Buffer的帮助),而且指令还是多发射(issue)的,这时候都没有先后关系了……前面讲的这些工作和一位几十年前在IBM工作,名叫Tomasulo的老爷爷有关(都已经过世两年了)。他用自己的姓来命名算法,所以大家虽然记不住他叫Robert,但还能知道他姓Tomasulo。

关于数据冒险,还有一种类型是RAW(Read After Write)。简单的解决方法是插入pipeline stall,等着数据写完再读,同时引来了pipeline的低效。更快的方法是在流水线内部的pipeline register直接传递数据,叫作直通或者短路。但即使加上了这种技术,有时候还是需要停顿,因为有时候从逻辑上来说,是必须要等的。

上面说的都是在ILP(Instruction Level Parallelism)级别的东西,其中也提到了内存,所以下面开始说一说内存相关的。

说到内存,就离不开Cache。Cache是一个伟大的发明,但一开始它却是为TLB(Translation Look-aside Buffer)服务的,因为“内存分页”的概念虽然好,但是多次间接地访问内存,搞得效率实再是太低下,于是有CPU设计者,在忍了再忍、忍无可忍的情况下,揭竿而起,给页表加上了cache——性能问题立即就得到了解决。

TLB和普通的cache一样,也会有hit和miss,现代CPU中的TLB在locality原则的保证下,甚至能够达到99%以上的TLB hit,但是那1%的TLB miss的penalty却非常地expensive(两个数量级以上),以至于无法忽略。据说TLB可以放在所有cache之前,或者在多级cache之间,或者在所有cache之后,分别对应:所有cache物理编址,L1 Cache虚拟编址+L2 Cache物理编址,以及所有Cache均为虚拟编码的三种情况,但实际上cache似乎都是物理编址的。理论上来讲,越大的Cache越需要用物理编址,否则一旦碰上进程切换……哼哼……

说到TLB就不得不说页表(本来它就是页表的cache)。页表有两种方式:多级页表和反向页表。32位地址模式下x86是三级每页4KiB,如果启用了PAE则是2MiB(这里多说一句,PAE不是Bank Switching,因为PAE扩展的那几位是参与VA->PA计算的)。AMD64位模式下为4级页表结构48Bit地址线。页表中对每个项(PTE)都至少有Present和Modified两个标志。P标志指示此页是否真在物理内存中,M标志指示此页是否在上次载入后被更改过。这两个标志是用来做虚拟内存的磁盘交换的,如果一个页被交换到磁盘上,它的P位就是False,访问它就会引发page fault中断,于是OS中断服务程序开始介入,假如不是非法访问的话,就要去从磁盘装载页面数据到物理内存,一般这时会硬盘狂响,界面冻结,用户开始捶打键盘……如果一个页由磁盘装入了内存,但一直还没有被更改过,那么M位就是False,也就是说如果在将来这个页要被换出的话,可以不必将它的内容写到磁盘。Linux内核中的pte_present()和pte_dirty()就是用来查询这两个标志的。除了这两个标志,还会有一些其它的,比如是否可更改等,用来做内存保护。

另外,Linux的程序装载,也是依靠page fault的,所谓的装载器其实并没有将程序内容从磁盘向内存复制(名不符实的东西遍地都有,是吧?),而是靠mmap机制映射之,随后在用到时,自然会有page fault出现,于是程序自然就被一点一点装载好了(这种感觉有点像刚刚写好了一个原语操作,然后就立即用它去发威了)。

TLB和Cache是紧密结合工作的,一个VA的VPO(Virtual Page Offset)会直接送到Cache中做匹配,VPN(Virtual Page Number)则送到TLB作查找,二者并行进行,如果都是hit,PN又对得上,那么这就是我们最想要的情形了。反之就要准备好至少两个数量级以上的penalty。在有些CPU中,TLB也有data TLB/instruction TLB,以及L1 TLB/L2 TLB之分。更多类型和更大的TLB cache力求减少miss,用以保证更好的VA->PA性能。

说完了TLB回过头来再说Cache。一般的Cache都是Set Associative的,因为Full Associative会慢,而且代价高,Direct Map又太不灵活(有一个经验定律是:2-way Set Associative,与双倍size的direct map cache相比,其cache miss rate持平)。因为Set Associativity的特性决定了有时候cache line必须被换出(此时称为victim,可以用LRU或FIFO来决定谁是victim),所以这里面就有一个优化:放置一个victim cache,专门用来保存上次被换出,但是马上又要被换入的那个line(我还看过有paper说用空闲的cache来做virtual victim cache)。OS中也有许多利用Cache的Set Associativity的特性,比如Page Coloring, Slab Coloring, Hot-n-Cold Allocator(另:设想Buddy System和非Full Associative的Cache一起使用,会有什么问题?)

从类型上来说,Cache分instruction cache和data cache两种,分别用来cache指令和数据。前面在说pipeline的时候曾经说过,如果在流水线中同时有“将运算结果写回”和“取指令”两个操作,存储器是无法接受这样的任务的。但区分了Instruction和Data两种类型后,就不存在此问题了,因为两个cache当然可以同时读+写。这种划分的另一个好处是,指令和数据的各自有自己的locality(包括时间和空间局部性),而且很少有交集(那个会写LISP的不要笑!严肃点!我们这儿侃大山呢!),所以区别对待它们,能带来性能上的提升。

一般CPU中cache至少有两级:L1和L2,现在开始流行三级cache了。越小的cache越快(基本和寄存器相当),越大的cache越慢,但无论如何也比内存快(最慢的也比内存快一个数量级左右)。分级的cache就带来一个问题:L2缓存中是不是有全部的L1缓存的内容?L3缓存中是不是有全部的L1&L2缓存的内容?这个决策不是一成不变的,有三种情况:如果大的cache一定含有小cache的内容,那么就算是strictly inclusive的;如果一定没有,就是exclusive的;如果基本上有(但有时候可能没有),就是inclusive的(注意和strictly inclusive的区别)。如果是inclusive cache,那么显而易见这里面就有一个更新的问题:更新L1 cache的时候,什么时候再去更新L2 cache中的对应内容?

层次当然是越多越好

层次当然是越多越好

另一个cache问题是在多核心/多CPU系统中出现的(SMP和NUMA均有),一般称为cache coherence问题。每个核心/CPU的L1 Cache一定是独享的,那么,如果相同Physical Address的内容被装到了不同的Core/CPU的L1 Data Cache中,然后这些Core/CPU又要去更新它们,就会出现问题。为了解决这个问题,在硬件中提供 了directory方式或者监听的方式,其中监听方式很简单:监听别的cache中的写入,如果是相同的PA,那么可以将其标为invalidated状态然后重装入,或者将监听到的写入动作同样执行一遍。

关于Cache,还有一个初看无关,但是细细考虑后,发现很相关的问题:DMA。经典的DMA讲解中,把“数据装入了内存、从而能够被直接使用”当成一个很终极的目标,但是现在我们还有更快的Cache,倘若每次用到DMA数据就需要从主存中取——这倒是没什么别的问题,就是太慢了——用惯了这么快的cache,早就把我们都惯坏了。所以又有一种办法被提了出来:对DMA的数据进行cache pre-fetching。当然这种pre-fetching不能太过份,否则cache会被这些东西给灌满,而真正需要用的热数据都被换出了——这就是所谓的cache polluting。cache polluting其实就是过量的cache warming-up以至于伤害了性能。

(曾经在某讨论组见过一个狂人,说整个组的人都不懂什么叫set associative cache,只有他自己一个人懂得……会不会我这篇blog侵犯到这位狂人独有的知识产权了呢?嘻嘻……)

说完了Cache这回终于能够说到内存了。内存的访问速度很慢,比CPU要慢两个数量级以上——这也正是Cache的意义所在。Cache也是内存,只不过是SRAM,特点是速度快;而内存是DRAM,特点是集成度高(其实计算机体系结构的许多问题都是由速度和容量的tradeoff产生的)。和双稳态的SRAM不同,DRAM每隔一段时间(典型数据:几十毫秒)就需要刷新数据以保证不丢失。过去的DRAM都是异步时钟的,直到SDRAM的时候才变成同步的(S就是synchronous)。DRAM颗粒是通过RAS和CAS信号来选取地址的(先用RAS锁出一行到行缓冲,然后靠CAS挑出需要的),每个内存颗粒可以一次选出8bit,然后这样8个8bit,并列起来构成了64位宽的数据(话说SDRAM和DDR都是64位宽的,更老的EDO和FPRAM什么的就让它们往事随风都随风吧——还不如关注一下双通道和三通道呢!)。有些内存模组上面有9片内存颗粒,这就是ECC内存了,一般是给服务器用的(Google的人曾发paper说,统计一下他们用ECC发现的内存错误,发现比想像中的可要频繁多了——对几万台服务器进行了长达两年半的跟踪记录,发现每年会发生22,696个可纠正的错误)。这里我不打算详细讲解校验原理,只做一个这样的计算:不带额外的颗粒时是8×8=64位,用它编码可以表达2^64种状态。现在是8×9=72位,也就是说可以用2^72种状态来表达2^64种编码,也就是说每256种编码中,就只有1种是对的,其它的255种排列方式都是错的……(嗯,Richard Hamming老先生要是看了我这样来解说,不知道会不会气得跳出来,然后再演讲一个Me and My Regret)

内存的访问有alignment一说,也就是说取32位数的时候,最好低5位地址为0,64位的则要求低6位地址为0。如果不是对齐的话,就需要两次存储器访问才能把完整的数给拼出来(注意这时候不考虑Cache的问题,完全是在说内存本身)。

在内存和Cache之间,同样有数据同步的问题, 为解决此问题,在Cache中也设计有dirty标志位:如果Cache要被淘汰掉了,并且dirty位为True,那么就需要把cache中的数据写回到memory中。当然,也有可能是用Write Through方式更新memory(不过,即使是Write Through,也是可以利用buffer来后台批量更新memory的,而不像传统教科书上讲的那样地naive)

关于内存访问,我想说的最后一件事是:程序中的内存访问操作,其顺序并不是按照程序规定的那样,而是经过了Memory Re-Ordering的。这种机制是乱序执行的一种,CPU中的MOB(Memory Ordering Buffer)就是来做这件事情的。

说完内存,就可以开始说外存了。如果不把穿孔纸带/卡算在内的话,外存是从磁芯磁鼓磁带一类的东西开始的,中间还有过8英寸、5英寸和3英寸软盘(后来又出现过LS-120/Zip/MO等软盘替代品,但它们都被U盘给干掉了)。现在的主流外存是硬盘,不久的未来可能会是SSD的天下。倒是磁带这东西还没有全死,因为容量实再是巨大(最新的大约是一卷500TiB);或者严格说来,软盘也没有全死:那些闻名世界的中国制造小工厂,常常使用老旧设备,那些设备上的计算机只能吃软盘:) 硬盘是从PIO方式发展过来的,后来才出现了DMA方式,后来又制定了DMA66/DMA100/DMA133等标准。有个经验规律是说,带宽的增长是延时的增长的两倍速度,但对于硬盘来说,这增长的带宽只是通讯线上的理论速度,硬盘本身的连续传输速率还是受机械机构的限制,不可能太快;延时方面则是基本没变。最新的硬盘外圈的连续速率可以有100+MB/Sec,但内圈速度至少减半。之所以有这样的速率差别,是因为硬盘是恒角速度旋转的(光盘倒是可以恒线速度),在相同时间内,外圈转过的距离当然比内圈要长,于是就可以多安排扇区。传统教科书上认为每个磁道上的扇区数都是固定的,但硬盘厂商早就打破了这一限制:他们在硬盘内部的固件里把逻辑扇区映射到物理扇区。这样的映射还带来另一个好处——试想,现在的硬盘是10年前的1000倍容量,如果工艺的改变没有1000倍(这种好事不用去想的!),那么坏扇区出现的故障率就大大增高了(比如100倍以上)。所以每个硬盘在正常的存储区之外,还有一些额外的保留区域备用,一旦出现了坏扇区,硬盘会把出错的逻辑扇区映射到保留区域内,这样就可以保证硬盘继续正常使用,只不过受到一点性能的损失(原来还有可能是连续的,现在是一定不连续了)。希捷硬盘的三黄问题,其中有一黄就是这个“重映射扇区”的计数。

1GB Hard Disk vs. 1GB Flash Card

1GB Hard Disk vs. 1GB Flash Card

如果硬盘中的碎片不特别严重,那么空间局部性原理也是起作用的(时间局部性原理多数会起作用,但考虑到OS有disk cache,可以稍微放松一下要求)。所以硬盘也安装有Cache,用来缓存读和写,在测试硬盘时候出现的最高的峰值速率都是Cache的功劳(硬盘用的Cache就是普通的DRAM颗粒)。

最早的硬盘是并行通讯。很多年前,并行通讯是比串行通讯快的,因为线多,可以同时传送一个字节或者更多。但后来发现,如果提高时钟频率,线多了会导致串扰变大(比如DMA33只要求40根的排线,而DMA66的线需要80根,其中就是添加了40根地线,每根地线和信号线并排),这就限制了时钟频率的提升,最终影响到通讯速率(还限制了通讯线的长度)。设想一下:如果串行通讯的时钟速率能有并行通讯的8倍以上(大约吧,因为还有其它开销),那么8位并行口就可以被打败了。实际上,用了低电压差分信号的串行线可以相当地快:比如PCI Express(过去叫3GIO),其时钟速率是2.5GHz,而PCI总线是33MHz或者66MHz(服务器上用的PCI-X最高有133MHz的)。当然,多组LVDS信号也是可以并列的(注意这仍不是并行通讯),这样就有了另一个优势:可以根据带宽需要来灵活安排。硬盘也在这几年完成了从并行到串行的进化,SATA中的S就是Serial的缩写。串行的最后一个优势是成本,如果提升速率带来的结果是价格翻倍,制造商们就不可能答应,因为一般来说消费者不会为这个买单。

Parallel->Serial->PS2->USB, And It Works

Parallel->Serial->PS2->USB, And It Works

硬盘的另一个进化,或者说革命,是SSD。SSD有两个巨大优势:一是访问延时(或相应的IOPS)。硬盘的典型寻道是10ms左右(硬盘直径小一些,就可以转得再快一些,寻道时间就可以再小一些,但至少也有几个ms;NCQ也可以优化寻道时间,原理是减少多余的空转),在这期间CPU能完成大约三千万条指令的运算。而优质的SSD(非中国山寨品)可以在1微秒内完成“寻道”(这是软件测试数据,实际有可能更小,因为本来SSD就没有“道”,就是做地址转换而已),至少提高了4个数量级。反过来用它折算IOPS,如果均为随机访问,大小为1Byte,那么这样的SSD至少应该有10k的IOPS;而10ms寻道的硬盘,一秒内至多能够有100个IO。SSD不仅仅是极限值估算中占优,在测试软件的IOPS实测中,也是以数量级领先于硬盘。SSD的第二个优势是速度,读取速率领先硬盘2-6倍。SSD的写入速率比SSD的读要慢百分之十几(SLC),但仍然大幅领先硬盘,而且SSD的速率在未来可能还会大幅提高,反过来看硬盘,在这10年间,盘片介质的传输速率也就是提高了两到三倍。

(往上翻了翻,发现打了一大堆字了,幸亏我有Cherry的机械键盘,打起字来一点也不累,嘿嘿……另外,如果是用嘴说的话,估计嗓子早就冒烟了……嗯,顺便在此BS一下弃blog而去录音频的tinyfool,然后咱们继续……)

说了这么半天,还有一件重要的东西一直还没提到:中断。同步/异步中断,可屏蔽/不可屏蔽中断,硬件/软件中断(软件中断由指令引发,常被用来实现系统调用),这里允许我虎头蛇尾一下吧,此处就先不展开了。

嗯,另外还有一个有趣的技术,SMT。这个技术的思路是,反正现代的CPU都是superscalar的了,程序经常无法用上这么多的运算部件,但如果把它们拆成两个传统的处理器核心的话,在可以充分ILP的时候却又吃亏了,而且需要的部件也变多了,再考虑到某些情况下流水线的长长等待停顿,设计者就盯上了近些年来开始流行的多线程技术,在CPU内实现了多线程并行——这也是SMT名字的由来:Simultaneous Multi-Threading。SMT属于线程级别的并行(TLP),它和ILP不同,它同时解决流水线垂直和水平浪费的问题,从充分利用运算部件的角度来说,SMT肯定是赚到了,但是从Cache和TLB等的角度来说,多个线程有可能互相warm up也有可能互相pollute,胜负难料。另外,从CPU设计的角度来说,支持SMT肯定会更复杂(register file需要再大一些,program counter需要两份等),坊间有传闻说Intel的Core2系列CPU就是因为没时间去做而放弃了SMT……嗯,传说而已,作为不明真相的雪亮群众,我们一定要保持情绪蛋定。

最后写点和知识无关的话:我上面写的这些体系结构方面的东西,全部都是因为组装电脑才学到的。有一本名叫CSAPP的教材(国内翻译版名为《深入理解计算机系统》),被某些人奉为神器,但在我这个装机十几年的人眼里,其中没有任何新鲜的知识,都是炒冷饭。

然后,请允许我吐一个槽:有些写程序的人,格外瞧不起会装电脑的,声称那些装机高手都是XXXX……在我看来,这有可能是他们自身知识层次的限制,外加一些很常见的biases(具体的我就不列举了,有兴趣的同学可以回家翻心理学教材),才导致他们会说出这样的话来(而且还有个逻辑错误)。

P.S. 说起基础的教材来,倒是《Computer Architecture – A Quantitative Approach》这一本,相当地不错。本着国内技术圈儿喜欢8褂教材的习惯,我在这里多介绍一些背景:作者共有两人,其中John Hennessy是RISC的大牛,斯坦福大学的校长,MIPS的发明人和公司创立者;另一位David Patterson是伯克利的教授,RISC的大牛,SPARC处理器原型的发明人……(嗯,看来我的8褂工夫不到家,说完这几句就没词儿了——这俩人获得冯诺依曼奖什么的不知道是不是应该8一下)……我个人建议:每个有志把程序写得更好的人,至少要把此书精读一遍(在上学时没有学到好教材的,该进补一下了)。其中的理由,我就不论证了——应该会有一小撮儿的software die-hard同意我的观点吧?最后,套用一句公司老大的话:

Software + Hardware = Complete!

An Architect

An Architect

感谢 @welfear 指出几处问题。

然后,自己留言给自己“辩解”一下:这个文章是在某一个周六的下午闲得无聊憋得难受就打一口气打出来的(前一个月左右曾复习了一下体系结构方面的东西,外加某些情况,不写写文章就有点憋得难受了:),最近我还没有仔细review,如果有错误肯定是在所难免,等回头对这些文字开始生疏的时候,我会再来修改订正。所以,大家千万看的时候要注意挑错,别轻信我说的,呵呵……

Advertisements
Tagged with:

21 Responses

Subscribe to comments with RSS.

  1. haohaolee said, on 2010/10/31 at 00:49

    很有营养~

  2. welfear said, on 2010/10/31 at 13:26

    有点意思。

  3. […] This post was mentioned on Twitter by haohaolee and Xuefeng Chang, Kenny Yuan. Kenny Yuan said: 《面试宝典3:计算机体系结构》http://wp.me/pw7f8-88 为DIYer正名;BS神器CSAPP;再BS @tinyfool 叛逃blog党改当cast党… […]

  4. Guancheng said, on 2010/10/31 at 18:01

    偶像!能把这些知识点行云流水般串讲一番没有十几年功力真弄不来!八卦一下,您是打算出一本面试宝典么?哈哈

    • Kenny Yuan said, on 2010/11/01 at 09:52

      你太客气了,我瞧了你的blog,挺不错,订之

      • mscorp said, on 2011/05/08 at 21:08

        没正面回答,估计有可能,呵呵。
        BTW,很用心经营的博客,相见恨晚。

        这样一篇巨型文章得花费您多少时间呢

        • Kenny Yuan said, on 2011/05/08 at 21:19

          多谢夸奖,呵呵。这个文章是我在某次面试前写的,当时大约花了两个晚上翻了翻书,然后赶上了周末,事情很多,看书看不下去,于是就花了一个下午码字,写了这一篇,当然在写的过程中也有翻书,于是就达到了我复习的目的,呵呵 🙂

          • Kenny Yuan said, on 2011/05/08 at 22:38

            补充说明:写完上面的回复后,发现自己文章的尾巴里也提到了这文章是如何写出来的,而且和上面回复中的不一样——看来“记忆重构”还真是无处不在啊,呵呵

  5. […] This post was mentioned on Twitter by Tinyfool, Reed Wang and Specter, Guancheng Chen | 陈冠诚. Guancheng Chen | 陈冠诚 said: http://goo.gl/GEJS 面试宝典3:计算机体系结构 from CS巴别塔 […]

  6. windstorm said, on 2010/11/01 at 02:06

    我反而觉得 深入理解计算机系统 对于普通程序员完全足够了。

    《Computer Architecture – A Quantitative Approach》也是在国外研究生阶段的高级计算机体系课才用这个教材(一般会有初级和高级两门课)

    • Kenny Yuan said, on 2010/11/01 at 09:54

      晕,原来不是本科,而是研究生课的教材啊,我SB了……

  7. hlessu said, on 2010/11/01 at 09:55

    Computer Organization and Design 这本也是这二位牛人写的,貌似这本更基础一些。都没读过的。。

    • Guancheng said, on 2010/11/01 at 16:40

      那一本Computer Organization and Design更偏向硬件实现 讲的都是VHDL的实现啊什么的 比较对应国内的计算机组成原理那门课

  8. myesis said, on 2010/11/08 at 21:35

    请问寄存器访问周期可能小于一个Cycle吗

  9. You Xu said, on 2011/02/13 at 03:34

    装机能学到 Pipeline stall ??? 哈哈

    • Kenny Yuan said, on 2011/02/15 at 12:34

      嗯,那些年的《电脑报》可NB了。再举几个例子:奇偶/海明/CRC/RAID/PIO/DMA/Superscala/Cache/Way/Coloring/TLB/ASID/FPRAM/CAS/RAS/EDO/DDR/RDRAM/VRAM……这些都是装机时学到的……

      • Kouga said, on 2012/10/09 at 16:09

        咱也只是初中的时候看《电脑版》那些年的确各种NB,但是……高中经历了长时间的资料匮乏,大学才真正开始有图书馆这样的资料来源了喵~

        现在的电脑版……呃……微笑一下带过吧喵……

  10. zym said, on 2011/05/09 at 14:34

    《深入理解计算机系统》本来定位就是给本科生的基础入门教材,说其炒冷饭未免冤枉了。

    ps,lz所谓的装机和大家一般想象的电脑城中的装机还是有很大区别的。

    • Kouga said, on 2012/10/09 at 16:12

      233~其实两边都偷换了一下概念喵~首先 “装机”和“学习电脑知识”这两个素相关性事件,但却是两个独立事件,很多人只是通过既有经验、直觉等关联了两方,尤其在电脑城大量烦死人的“促销员”存在的情况下顺带BS这类人也很正常。(往77z主板上插推土机CPU什么滴……

      • Kenny Yuan said, on 2012/11/20 at 21:08

        嘿嘿,我是故意那样说滴,理由很复杂,你就当我是卖萌吧,汪~~

  11. imeasoncxz said, on 2014/01/29 at 05:43

    本文简述: http://abstrusegoose.com/98


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: