什么是冯·诺伊曼结构
冯·诺伊曼结构也称冯·诺伊曼模型(Von Neumann model)或普林斯顿结构(Princeton architecture),是一种将程序指令存储器和数据存储器合并在一起的电脑设计概念结构。本词描述的是一种实现通用图灵机的计算设备,以及一种相对于并行计算的序列式结构参考模型(referential model)。
本结构隐约指导了将存储设备与中央处理器分开的概念,因此依本结构设计出的计算机又称存储程序型电脑。
冯·诺伊曼结构的历史
最早的计算机器仅内涵固定用途的程序。现代的某些计算机依然维持这样的设计方式,通常是为了简化或教育目的。例如一个计算器仅有固定的数学计算程序,它不能拿来当作文字处理软件,更不能拿来玩游戏。若想要改变此机器的程序,你必须更改线路、更改结构甚至重新设计此机器。当然最早的计算机并没有设计的那么可编程化。当时所谓的“重写程序”很可能指的是纸笔设计程序步骤,接着制订工程细节,再施工将机器的电路配线或结构改变。
而存储程序型电脑的概念改变了这一切。借由创造一组指令集结构,并将所谓的运算转化成一串程序指令的运行细节,让此机器更有弹性。借着将指令当成一种特别类型的静态数据,一台存储程序型电脑可轻易改变其程序,并在程控下改变其运算内容。 冯·诺伊曼结构与存储程序型电脑是互相通用的名词,其用法将于下述。而哈佛结构则是一种将程序数据与普通数据分开存储的设计概念,但是它并未完全突破冯.诺伊曼架构。
存储程序型概念也可让程序运行时自我修改程序的运算内容。本概念的设计动机之一就是可让程序自行增加内容或改变程序指令的内存位置,因为早期的设计都要用户手动修改。但随着变址寄存器与间接位置访问变成硬件结构的必备机制后,本功能就不如以往重要了。而程序自我修改这项特色也被现代程序设计所弃扬,因为它会造成理解与除错的难度,且现代中央处理器的管线与缓存机制会让此功能效率降低。
从整体而言,将指令当成数据的概念使得汇编语言、编译器与其他自动编程工具得以实现;可以用这些“自动编程的程序”,以人类较易理解的方式编写程序;从局部来看,强调I/O的机器,例如Bitblt,想要修改画面上的图样,以往是认为若没有客制化硬件就办不到。但之后显示这些功能可以借由“运行中编译”技术而有效达到。
此结构当然有所缺陷,除了下列将述的冯·诺伊曼瓶颈之外,修改程序很可能是非常具伤害性的,无论无意或设计错误。在一个简单的存储程序型电脑上,一个设计不良的程序可能会伤害自己、其他程序甚或是操作系统,导致死机。缓存溢出就是一个典型例子。而创造或更改其他程序的能力也导致了恶意软件的出现。利用缓存溢出,一个恶意程序可以覆盖调用堆栈(Call stack)并改写代码,并且修改其他程序文件以造成连锁破坏。内存保护机制及其他形式的访问控制可以保护意外或恶意的代码更动。
冯·诺伊曼结构的提出
冯·诺伊曼结构这个词出自约翰·冯·诺伊曼的论文:First Draft of a Report on the EDVAC, 于1945年6月30日。冯·诺依曼由于在曼哈顿工程中需要大量的运算,从而使用了当时最先进的两台计算机Mark I和ENIAC,在使用Mark I和ENIAC的过程中,他意识到了存储程序的重要性,从而提出了存储程序逻辑架构。虽然冯·诺伊曼的概念非常新颖,但冯·诺伊曼结构这个词,对冯·诺伊曼的合作伙伴、时人甚至先辈都不公平。
一份康拉德·楚泽提出的专利应用就已在1936年点出这类概念。而存储程序型电脑的概念早在冯·诺伊曼知晓ENIAC的存在前就已在宾州大学的摩尔电机学院流传了。此构想的确实创立者永远是个谜。
赫曼·鲁寇夫(Herman Lukoff)相信是艾克特创建此概念。毛奇利(Mauchly)与艾克特(Eckert)在1943年于他们建造ENIAC时写下关于存储程序的概念,另外,ENIAC项目管理员布莱德(Grist Brainerd)在1943年12月为ENIAC做的进度回报,就已隐约提及存储程序的概念(虽然也同时否决了在ENIAC实现的项目),他说“为了拥有最简单的实现项目以及不复杂的事务,ENIAC建造时后将不需要任何自动整备”。
当设计ENIAC时,它很清楚说明从读卡器或纸带读取指令是不够快的,因为ENIAC设计用于高速运行运算。因此ENIAC直接以电路管线设计程序,并在需要新程序时重新配接线路。设计师也很清楚他们需要更好的系统结构,因此在ENIAC建造期间第一份EDVAC的报告就已撰写完毕,并包含了存储程序的概念,此概念叙述程序指令存储在高速内存(水银延迟内存)中,因此可以在运行时快速访问。
艾伦·图灵在1946年2月19日讲演了一份包含程序存储型电脑(Pilot ACE)完整设计的论文。
冯·诺伊曼结构瓶颈
将CPU与内存分开并非十全十美,反而会导致所谓的冯·诺伊曼瓶颈(von Neumann bottleneck):在CPU与内存之间的流量(数据传输率)与内存的容量相比起来相当小,在现代电脑中,流量与CPU的工作效率相比之下非常小,在某些情况下(当CPU需要在巨大的数据上运行一些简单指令时),数据流量就成了整体效率非常严重的限制。CPU将会在数据输入或输出内存时闲置。由于CPU速度远大于内存读写速率,因此瓶颈问题越来越严重。
而冯·诺伊曼瓶颈是约翰·巴科斯在1977年ACM图灵奖得奖致词时第一次出现,根据巴科斯所言:确实有一个变更存储设备的方法,比借由冯·诺伊曼瓶颈流通大量数据更为先进。瓶颈这词不仅是对于问题本身数据流量的叙述,更重要地,也是个使我们的思考方法局限在‘一次一字符’模式的智能瓶颈。它使我们怯于思考更广泛的概念。因此编程成为一种项目与详述通过冯·诺伊曼瓶颈的字符数据流,且大部分的问题不在于数据的特征,而是如何找出数据。
在CPU与内存间的缓存内存抒解了冯·诺伊曼瓶颈的性能问题。另外,分支预测(branch prediction)算法的创建也帮助缓和了此问题。巴科斯在1977年论述的“智能瓶颈”已改变甚多。且巴科斯对于此问题的解决方案并没有造成明显影响。现代的函数式编程以及面向对象编程已较少运行如早期Fortran一般会“将大量数值从内存搬入搬出的操作”,但平心而论,这些操作的确占用电脑大部分的运行时间。