天天看點

《計算機組成原理》----1.4 存儲程式計算機

本節書摘來自華章出版社《計算機組成原理》一書中的第1章,第1.4節, 作 者 computer organization and architecture: themes and variations[英]艾倫·克萊門茨(alan clements) 著,沈 立 王蘇峰 肖曉強 譯, 更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

本書将相當詳細地介紹兩種高性能計算機:arm系列計算機和intel ia-64體系結構的計算機。但本節并不會将計算機視作一種既定事實,直接描述它的結構,而是會從概念上介紹計算機是如何設計的。是以本節将通過提出一個問題并分析解決這個問題需要哪些東西,來介紹一個非常簡單的計算機的結構。盡管這個問題非常簡單,但它卻展示了一個真正的程式所要完成的操作以及指令序列的概念。本節将要設計的用來解決問題的計算機就是真正的存儲程式計算機的一個初始版本。

請考慮圖1-7中的十進制數串23277366664792221。正如讀者所看到的那樣,其中有一些值相同的數字連續出現(例如連續的2個7、4個6和3個2)。我們的問題十分簡單:找出最大遊程,即同一個數字連續出現的最大次數。為了簡化問題,假設數串的長度大于3。

《計算機組成原理》----1.4 存儲程式計算機

從圖1-7中可以很快看出結果應為4,因為這一串數字中有4個連續的6,而連續的7隻有2個,連續的2則隻有3個。我們将設計一台計算機來處理圖1-7中的數串,它每次讀一個數,并告訴我們最大遊程是多少。

如果我們從數串的左邊開始逐個檢查數字,在任何一個位置,我們都會得到以下兩個結果之一:要麼這個數與前一個相同,序列還在增長;要麼這個數與上一個不同,前一個序列結束,一個新的序列開始。為了強調這一點,圖1-7中用帶陰影的圓角矩形标出了所有至少含有兩個數的序列。

圖1-8中的狀态圖可以幫我們解決這個問題。在任一時刻,某個系統都會處于幾種可能的狀态之一。例如,人要麼睡着了,要麼醒着;飛機則可能處于以下3種狀态之一:爬升、降落或水準飛行。對于一個數字系統,當一個特定的事件(如時鐘脈沖)發生時,它将從一個狀态轉換為另外一個狀态。圖1-8中,每當從數串中讀出一個新的元素,都會發生狀态轉換。

《計算機組成原理》----1.4 存儲程式計算機

圖1-8中有兩個狀态,分别是“在同一序列中”和“不在同一序列中”。處于狀态“在同一序列中”的條件是當發現連續的兩個或更多的數字都具有相同的值時。如果處于狀态“不在同一序列中”,且新的數與前一個數不同,則會依然維持目前狀态“不在同一序列中”不變。如果新讀出的數與上一個數相同,則狀态将轉換為“在同一序列中”,因為此時已經處于一個序列的第二個位置。隻要每個新讀出的數都與前一個相同,每次狀态轉換後都會維持“在同一序列中”的狀态不變。隻有當新讀出的數與前一個不同時,狀态才會被轉換為“不在同一序列中”。

圖1-9列出了一個接一個地讀入圖1-7中數串的數字後系統狀态的轉換情況。正如讀者所看到的那樣,狀态的改變會發生在序列的第二個數字或結束序列的那個數字上。

《計算機組成原理》----1.4 存儲程式計算機

表1-1則将這些數字組織成一種更容易了解的形式。最上面一行是每個數字在數串s中的位置或位址,下一行是串s中這個數字的值。例如,第11個元素的值是4。第三行則是目前序列中數的值;這一行的第一個元素是?,因為此時上一個元素的值是未知的。顯然,第三行每個元素的值與第二行前一個元素的值相同。

《計算機組成原理》----1.4 存儲程式計算機

讓我們從數串的左邊開始,逐個檢查每個數字。我們每次讀入一個新的數字,并問自己,“我們是否找到了一個新的序列?”如果此時正好處于一個序列的開始,那麼這個序列的長度被置為1。如果這個數字是目前序列的一部分,則目前序列的長度增加1。現在我們周遊數串中的每個數字,并将每個數字對應的序列長度記錄在表1-2中。序列長度在1~4之間變化。請注意,表1-2中“目前序列數值”這一行記錄的是檢查新元素之前的數值。

《計算機組成原理》----1.4 存儲程式計算機

每當一個新的序列開始時,我們都會判斷上一個序列是否比目前為止最長的序列還長。表1-3通過增加新的一行記錄目前最大序列的長度來說明這是如何實作的。可以看到,當處理完數串最右邊的第17個元素後,所記錄的最大序列長度為4。注意,這個問題假定串的長度是已知的,處理過程何時停止也是已知的。如果不知道這些,那麼就必須知道最後一個數是什麼,顯然它必須是唯一的。

《計算機組成原理》----1.4 存儲程式計算機

下一步是設計一個算法,告訴我們如何清楚明确地解決這個問題。周遊數串的時候,必須跟蹤一些資訊。當然,這些資訊分别對應于表1-3中的各行。為友善起見,我們通過下面的符号名引用這些資訊。

《計算機組成原理》----1.4 存儲程式計算機

下面的僞碼描述了解決這個問題所必需的操作。僞碼的開始部分是初始化操作,它們僅被執行一次,而repeat…until所定義的重複操作加陰影表示。為簡便起見,此處省去了索引變量i,用“第一個數”或“下一個數”表示各個數字,而沒有用digit(i)或digit(i+1)。

《計算機組成原理》----1.4 存儲程式計算機

上面的僞碼使用了兩個在很多進階語言中都能見到的結構:5~13行的repeat…until結構和if…then…else結構。repeat…until用于将一個動作執行一次或重複多次,if…then…else則從兩個可能的動作中選擇一個來執行。if…then…else是數字計算機的關鍵操作,本書會以多種方式多次用到這個結構。讀者還會看到它是如何在硬體層實作的,它在幾種不同的計算機上是如何表示的,它怎樣給現代計算機的性能帶來負面影響,一些計算機如何試圖在它實際完成之前猜測其結果,以及一些計算機如何試圖使用謂詞操作完全避免它的出現。

《計算機組成原理》----1.4 存儲程式計算機
《計算機組成原理》----1.4 存儲程式計算機

我們首先來看看解決這個問題時應進行哪些操作。由于1~13行的動作是順序進行的,我們的計算機也必須能順序地完成這些操作。細心的讀者可能會發現我們選擇順序解決問題(每次一步)。這種方法既反映了人類的通常行為,也反映出計算機的實際發展。我們也可以采用另一種不同的方法,同時進行多個操作。我們設計出一種通用的問題求解機制,它能夠很容易地被修改以便用于解決其他問題。我們也能設計一種隻能解決這個問題的機制,但我們的目标是設計一台能夠通過程式設計解決一系列問題的計算機。算法的前兩行如下:

《計算機組成原理》----1.4 存儲程式計算機

第1行從串中讀出一個數,此時這個串必須儲存在計算機存儲器中的某處。符号名new_digit指明了這個數在存儲器中的位置。計算機必須確定它在任何需要使用目前序列的目前值的時候,都能通路到存儲器的這個位置。

第2行是一個指派操作,因為它将一個值賦給一個變量。同樣,第3行和第4行也是指派操作,它們分别将變量current_run_length和max_run的值置為1。計算機必須能夠完成從存儲器中讀出一個數,修改這個數并且将修改後的數寫回存儲器等操作。

第5行包含關鍵字repeat,它告訴我們這裡是一組将被執行1次或多次的操作的起始位置。這組操作以第13行的關鍵字until結尾。

第7、8和10行說明了條件執行,即要執行的操作類型取決于測試結果。

《計算機組成原理》----1.4 存儲程式計算機

第7行比較從串中讀出的數值與目前序列的數值是否相同(即比較new_digit與current_run_value是否相同)。然後根據比較結果執行下面兩個操作中的一個。一個操作由第8行關鍵字then後面的文字指定,另一個則由第9、10兩行else後的文字指定。第9和10兩行包含在一對花括号{}中,說明執行時它們将被視作else路徑上的一個整體。

圖1-10以流程圖的方式描述了這一結構。

盡管這個問題相對簡單,它卻含有解決任一問題所需的全部元素:有将資訊從一個位置傳遞到另一個的指派操作;有加、減等算術運算;最後,還有根據計算結果(如比較)從兩個候選動作中選擇一個的操作。

《計算機組成原理》----1.4 存儲程式計算機
《計算機組成原理》----1.4 存儲程式計算機

計算機解決問題所需元素并不比上面介紹的内容多。可以說計算機體系結構就是更加快速、高效地實作我們所描述的各種操作類型。

在繼續介紹計算機的設計之前,我們必須簡要浏覽一下儲存程式和程式所用資料的存儲系統。

人類的記憶是一種奇怪的、不精确的東西。一個事件會觸發一次對某個被我們稱為記憶的資料元素的回憶或檢索。這裡的事件也許是某人問你的一個問題,也許是讓你回想起發生在過去的某段插曲的東西。通常我們隻記得其中的一部分,甚至它還是錯誤的。人類是通過将某個事件與所儲存的資訊相比對而查找或通路記憶的。也就是說,我們的記憶是聯想的,因為我們總是将一段記憶與另一段聯系在一起。計算機的存儲器則完全不同,最好将它視作一個存放資訊的表格或目錄。

圖1-11描述了程式怎樣找出儲存在一個假想存儲器中的數串的最大序列長度。必須強調的是,這個程式是概念上的而不是實際的,因為真正的計算機指令比其更加基礎。這幅圖叫作存儲器映射,它展示了資訊在存儲器中的存放位置。它是存儲器的一幅快照,因為它表示存儲器在某個特定時刻的狀态。存儲器映射也包含程式使用的變量和數字串。前面談到過,存儲程式計算機會将指令、變量和常量全部儲存在同一個存儲器内。

圖1-11說明存儲器中的每個位置要麼儲存了指令要麼儲存了資料元素。第一列中的數字0~37為位址,代表了資料元素和指令在存儲器内的存放位置(位址從0而不是1開始,因為0是一個合法的辨別符)。程式位于位址0~16的位置,變量位于位址17~20的位置,而資料(串)位于位址21~37的位置。可以将計算機的存儲器視作一個資料元素的表格——每個元素的位置就是它的位址。例如,位址為3的存儲單元儲存了指令“将max_run置為1”而位址為20的存儲單元儲存了元素max_run的值。17行及其後面的各行使用了粗體字,表明它們儲存了變量以及要處理的數串。

千萬不要以為圖1-11中的程式是真實的。為了簡便起見,我們不得不省略了一些細節。例如,我們在位址10處放置了一條跳轉指令,它告訴計算機忽略位址11和12處的指令,直接執行位址13的指令。這是必需的,因為如果執行了分支的then部分,那麼必須忽略掉它的else部分。此處還說明了怎樣用符号memory(i)來通路每個數字,它表示存儲器的第i個單元。i的值被初始化為21,并且循環在i等于37時結束。

圖1-12描述了存儲系統的組成。處理器将一個放在位址總線上的位址以及一個用于選擇讀操作或寫操作(它們有時也被稱作讀或寫周期)的控制信号發送給存儲器。在讀周期中,存儲器将資料放在資料總線上供cpu讀取。在寫周期中,放在資料總線上的資料被寫入存儲器。資訊進入或離開存儲器的位置(或計算機系統的其他功能部分)叫作端口。

盡管圖1-12中的存儲器是簡化後的版本,它卻準确地描述了将資料和指令連續存放的計算機存儲器。一台真正的計算機會使用存儲系統層次(每個層次都有可能采用不同的技術來實作)。這些層次包括儲存頻繁被通路資料的速度非常快的cache、主存,以及速度非常慢的輔存,在這一層次中大量資料會一直儲存在磁盤、CD光牒或dvd中,直到使用時才會被調入主存。

《計算機組成原理》----1.4 存儲程式計算機

由于使用文字描述計算機的操作很不友善,下面介紹一個概念寄存器傳輸語言(register transfer language, rtl),使用rtl可以更加容易地定義計算機内發生的操作。

《計算機組成原理》----1.4 存儲程式計算機
《計算機組成原理》----1.4 存儲程式計算機

繼續閱讀