馮・諾伊曼結構

馮・諾伊曼結構（Von Neumann architecture），全稱馮・諾依曼體系結構，也稱馮・紐曼模型（Von Neumann model）或普林斯頓結構（Princeton architecture），是一種將程式指令儲存器和資料儲存器合併在一起的電腦設計概念結構，由約翰・馮・諾伊曼等人提出。本詞描述的是一種實作通用圖靈機的計算裝置，以及一種相對於平行計算的序列式架構參考模型（referential model）。

本架構隱約指導了將儲存裝置與中央處理器分開的概念，因此依本架構設計出的計算機又稱儲存程式計算機。

理論

儲存程式計算機在體系結構上主要特點有：

以運算單元為中心
採用儲存程式原理
儲存器是按地址訪問、線性編址的空間
控制流由指令流產生
指令由操作碼和地址碼組成
資料以二進位制編碼

歷史

最早的計算機器僅內含固定用途的程式。現代的某些計算機依然維持這樣的設計方式，通常是為了簡化或教育目的。例如一個計算器僅有固定的數學計算程式，它不能拿來當作文書處理軟體，更不能拿來玩遊戲。若想要改變此機器的程式，你必須更改線路、更改結構甚至重新設計此機器。當然最早的計算機並沒有設計的那麼可程式化。當時所謂的「重寫程式」很可能指的是紙筆設計程式步驟，接著制訂工程細節，再施工將機器的電路配線或結構改變。

而儲存程式型電腦的概念改變了這一切。藉由創造一組指令集架構，並將所謂的運算轉化成一串程式指令的執行細節，讓此機器更有彈性。藉著將指令當成一種特別型態的靜態資料，一臺儲存程式型電腦可輕易改變其程式，並在程式控制下改變其運算內容。

馮・諾伊曼結構與儲存程式型電腦是互相通用的名詞，其用法將於下述。而哈佛結構則是一種將程式資料與普通資料分開儲存的設計概念，但是它並未完全突破馮。諾伊曼架構。

儲存程式型概念也可讓程式執行時自我修改程式的運算內容。本概念的設計動機之一就是可讓程式自行增加內容或改變程式指令的記憶體位置，因為早期的設計都要使用者手動修改。但隨著索引暫存器與間接位置存取變成硬體架構的必備機制後，本功能就不如以往重要了。而程式自我修改這項特色也被現代程式設計所揚棄，因為它會造成理解與除錯的難度，且現代中央處理器的管線與快取機制會讓此功能效率降低。

從整體而言，將指令當成資料的概念使得組合語言、編譯器與其他自動程式設計工具得以實現；可以用這些「自動程式設計的程式」，以人類較易理解的方式編寫程式；從區域性來看，強調 I/O 的機器，例如 Bitblt，想要修改畫面上的圖樣，以往是認為若沒有客製化硬體就辦不到。但之後顯示這些功能可以藉由「執行中編譯」技術而有效達到。

此架構當然有所缺陷，除了下列將述的馮・諾伊曼瓶頸之外，修改程式很可能是非常具傷害性的，無論無意或設計錯誤。在一個簡單的儲存程式型電腦上，一個設計不良的程式可能會傷害自己、其他程式甚或是作業系統，導致當機。緩衝區溢位就是一個典型例子。而創造或更改其他程式的能力也導致了惡意軟體的出現。利用緩衝區溢位，一個惡意程式可以覆蓋呼叫堆疊（Call stack）並覆寫程式碼，並且修改其他程式檔案以造成連鎖破壞。記憶體保護機制及其他形式的存取控制可以保護意外或惡意的程式碼更動。

第一次提出及實作

「馮・諾伊曼結構」這個詞出自美籍猶太數學家約翰・馮・諾伊曼（John von Neumann）的論文：《EDVAC 報告書的第一份草案》（First Draft of a Report on the EDVAC），

於 1945 年 6 月 30 日。馮・諾依曼由於在曼哈頓工程中需要大量的運算，從而使用了當時最先進的兩臺計算機 Mark I 和 ENIAC，在使用 Mark I 和 ENIAC 的過程中，他意識到了儲存程式的重要性，從而提出了儲存程式邏輯架構。雖然馮・諾伊曼的概念非常新穎，但馮・諾伊曼結構這個詞，對馮・諾伊曼的合作伙伴、時人甚至先輩都不公平。

一份由德國工程師康拉德・楚澤（Konrad Zuse）提出的專利應用就已在 1936 年點出這類概念。而儲存程式型電腦的概念早在馮・諾伊曼知曉 ENIAC 的存在前就已在賓州大學的摩爾電機學院流傳了。此構想的確實創立者永遠是個謎。

相信是艾克特建立此概念（見參考資料）。

莫奇利與艾克特在 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 圖靈獎得獎致詞時第一次出現，根據巴科斯所言：

原文如下：

Surely there must be a less primitive way of making big changes in the store than by pushing vast numbers of words back and forth through the von Neumann bottleneck. Not only is this tube a literal bottleneck for the data traffic of a problem, but, more importantly, it is an intellectual bottleneck that has kept us tied to word-at-a-time thinking instead of encouraging us to think in terms of the larger conceptual units of the task at hand. Thus programming is basically planning and detailing the enormous traffic of words through the von Neumann bottleneck, and much of that traffic concerns not significant data itself, but where to find it.

在 CPU 與記憶體間的快取記憶體抒解了馮・諾伊曼瓶頸的效能問題。另外，分支預測（branch prediction）演演算法的建立也幫助緩和了此問題。巴科斯在 1977 年論述的「智慧瓶頸」已改變甚多。且巴科斯對於此問題的解決方案並沒有造成明顯影響。現代的函數語言程式設計以及物件導向程式設計已較少執行如早期 Fortran 一般會「將大量數值從記憶體搬入搬出的操作」，但平心而論，這些操作的確佔用電腦大部分的執行時間。

早期的儲存程式型電腦

下列的日期資料很難給予一個適當的日期順序。一些是第一次執行測試程式的日期；一些是電腦第一次公開展示或完成建造的日期；還有一些是第一次散佈及安裝日期。