題:
為什麼我們的微處理器中沒有更多的寄存器?
Darshan Chaudhary
2016-09-09 11:16:25 UTC
view on stackexchange narkive permalink

理論上不需要註冊;所有微處理器在沒有寄存器的情況下仍然可以工作。但是,這種看似微不足道的添加幫助使微處理器更加高效。

為什麼我們沒有更多的寄存器來進一步從中受益?它們只是片上存儲器,可以想像添加起來不是很困難嗎?是什麼因素影響了寄存器的數量而不是原來的數量,比如說多了十倍?

遺產。很多。
我沒有明白你的意思。要完成uP工作,完全需要寄存器。實際上,首先是#1條件。
@Alper91許多假設的和實際的體系結構都沒有寄存器,也完全沒有必要。這只是一個有用的優化。
在8位PIC中,所有RAM均為寄存器。例如,PIC16F18877具有4K RAM,可通過64個存儲區訪問,每個存儲區都有80個文件寄存器。
嗯沒有人提到Sparc。最大的實現可能有520個寄存器(32個窗口乘以16個寄存器,再加上8個全局變量。)我肯定記得它們。
我認為指令中需要指定寄存器的位數是個大問題。如果您有1024個寄存器,那麼每條算術指令至少需要30位-除非添加其他約束,例如“所有3個寄存器必須來自同一組32(在這種情況下,您需要20位)。
“更多的片上存儲器”被實現為L1高速緩存。
@pjc50:是的。但是L1曾經比P2時代的CPU慢3倍,但現在由於CPU的運行速度更快而變得更慢。只是不能接近cpu的速度。即使是L1,大多數情況下還是要“快等”。L1不是寄存器。
@pipe-實際上,幾乎任何實際設計在原理上都需要“寄存器”,即使即使您構建了堆棧機或類似的東西,也必須有一個地方保存ALU的參數,否則輸出-大多數記憶沒有三個訪問端口。堆棧計算機需要一個*堆棧指針*,它是一個寄存器!而且,更不用說管道寄存器了。您可以向程序員隱藏對此類“寄存器”的使用,但是您仍然需要一些寄存器,並且可能與原始寄存器機器所需要的數目差不多。
@ChrisStratton當然可以,但是只要不通過ISA公開它們,它只是一個實現細節。不過有些爭論,因為我們不知道_register_表示OP的含義。
請注意,處理器可以擁有比其架構要求更多的寄存器。參見https://en.wikipedia.org/wiki/Register_renaming
一些較舊的微處理器使用多個寄存器來保存每個內存地址-例如,我讀取了具有1 MB內存的8位處理器。
八 答案:
AProgrammer
2016-09-09 16:32:02 UTC
view on stackexchange narkive permalink

有幾個因素:

  • 高性能微體系結構使用寄存器重命名。也就是說,物理寄存器的數量大於體系結構可見的寄存器的數量,並且它們能夠跟踪它們的獨立用途。

  • 將寄存器數量加倍不會使性能提高一倍。 ISTR(來自計算機體系結構,一種量化方法)從16個寄存器增加到32個寄存器帶來了大約10%的改善,前提是假定增加不會帶來不利影響(這是非常樂觀的假設)。

  • 體系結構可見的寄存器具有成本。例如:

    • 增加它們的數量會增加指令格式中採用的位數,以指示正在作用於哪個寄存器(將寄存器數量加倍意味著該格式中每個寄存器都有一個位數,從而防止將這些位數用於其他寄存器用法或強制使用更長的指令)。
    • 增加體系結構寄存器的數量會增加上下文切換成本(因為必須在上下文切換中對其進行保存和恢復)。
我敢保證16到32個寄存器的性能提高完全取決於所考慮的編譯器的優化潛力。在彙編程序中,訪問兩倍數量的寄存器(在x64體系結構中)可以極大地提高性能-但僅適用於特殊角色,並且僅在實際使用它們的情況下。
從8到16個體系結構寄存器的@rdtsc:大大提高了典型代碼的溢出/重載數量,[根據此答案鏈接的論文中的模擬數據](http://stackoverflow.com/questions/8466981/為什麼-does-arm-have-16-registers)。它會影響代碼大小,指令數量以及低延遲存儲轉發的重要性。16-> 32的效果要小得多。AFAICT的16個體系結構寄存器是通過重命名寄存器來消除WAR和WAW危害的硬件的理想選擇。
但是,英特爾的AVX512增加了16個矢量寄存器,總共32個。(以及將它們的寬度加倍到64字節,即一個完整的高速緩存行)。隱藏來自高吞吐量高延遲FP操作的延遲可能會佔用大量寄存器。例如英特爾Haswell具有5c lat,每0.5c吞吐量FMA一個,因此您需要10個矢量累加器以使FMA執行單元飽和以進行縮減(例如,點積或求和數組,其中FMA是循環依賴的一部分)。x86-64僅具有16個矢量寄存器。但是請記住,整數運算,尤其是。在GP reg上,很少有超過1c的延遲。
整數,FP和向量寄存器的權衡是不同的。例如,整數寄存器的懶惰保存/恢復沒有任何意義,對向量1進行更好的選擇。向量ISA的寄存器通常比整數1多(AltiVec至少具有128個寄存器,ISTR為Sparc讀取了大約256個寄存器,但現在找不到引用)。
https://zh.wikipedia.org/wiki/AltiVec具有32個128b矢量reg。我對SPARC感到好奇,並查看了其寄存器窗口的內容如何用於上下文切換。它一次具有32個寄存器,但使用滑動窗口到較大的寄存器文件中。聽起來[從此簡化版本開始](http://www.cim.mcgill.ca/~jer/courses/os/lecnotes/lec11.html)就像操作系統需要知道整個滑動窗口寄存器文件的大小一樣保存/恢復註冊表,因為即使窗口幻燈片指令提供了用於保存/恢復註冊表的內存(如果需要),也可以通過捕獲到OS來完成。
但是,是的,折衷是不同種類的寄存器,這很正常。您提到了懶惰的保存/恢復;英特爾已經超越了通常的含義,並添加了[XSAVEOPT指令](http://www.felixcloutier.com/x86/XSAVEOPT.html),以優化方式保存了整個寄存器集(例如,所有向量寄存器)。格式*。允許跳過未修改的保存寄存器(並將其記錄在保存區域中不透明的元數據中,該保存區域根據微體系結構而有所不同)。操作系統查詢(在啟動時一次)它需要為XSAVEOPT保留的內存大小。
+1表示上下文切換成本,這是一個通常被忽略/忽略的巨大成本(尤其是Intel不斷增長的AVX寄存器文件破壞了上下文切換時間)。
我想提出一點格式化方面的改進。我認為關於指令大小和上下文切換成本的最後一個要點實際上是兩個不同點,因此最好將其格式化為兩個項目符號。同樣,也許值得考慮有關指令大小的第一部分可以具體化。問題是,多出10倍的寄存器將需要在指令中增加約3.3位(多出16倍的寄存器將需要增加4位),因此,對於3地址的機器,將需要12位大的指令,而需要將32位的指令變為44位指令。只是一個想法
Neil_UK
2016-09-09 11:43:25 UTC
view on stackexchange narkive permalink

雖然寄存器和RAM都是內存,但是它們以不同的方式訪問,以反映訪問它們的成本(在芯片面積或隱藏時鐘週期內)。

寄存器與ALU緊密綁定,可以擔當數據源,接收器,修飾符等的許多角色。因此,它們需要大量的寬復用連接。在某些架構中,我們可以寫成R1 < = R2 + R3,而這恰好是在單個時鐘週期內發生的。每個寄存器都用操作碼直接尋址,這種尋址是非常有限的資源。

由於寄存器的實現成本很高,因此在大多數體系結構中,寄存器的數量通常限制在10/20的數量級。

RAM鬆散地綁定到CPU,通常通過單個共享連接進行引導。這使得實現大量RAM的成本大大降低。 RAM地址通常來自寄存器存儲的地址,因此不會佔用大量指令寬度。

SPARC是一種有趣的體系結構,具有72到640個64位寄存器,具有32個寄存器上下文,可以通過重疊進行移位,以通過參數傳遞進行快速子例程調用。您往往不會在需要成本的PC和服務器中找到它們,例如在99.999%的應用程序中。

另一方面是您必須在上下文切換期間保存/恢復寄存器。更多的寄存器,更多的時間。
我會注意到,舊的TMS9900將其所有工作寄存器都保存在外部存儲器中https://en.wikipedia.org/wiki/Texas_Instruments_TMS9900
我已經“總是”使用了(除了一些調整),但是將其簡化了。也許我只是將其更改為“一般”。基本上,如果您可以找到並理解例外,則不需要我指出這些例外。如果您有足夠的勇氣被誤導,那就沒關係,因為它不會給您帶來麻煩。TMS9900,那真是太奇怪了,我早年的罪孽是99/4,是奇怪的野獸!
Itanium還具有註冊窗口。
@MichelBillaud-您不必“保存” /“恢復”所有*寄存器進行上下文切換,某些當前流行的ABI則不需要。
好吧,我目前在Linux計算機上有243個任務,大多數任務閒置。其中有多少個從未進行過上下文切換,從而導致操作系統保存寄存器的內容?
@ChrisStratton:您在考慮“函數調用”還是“上下文切換”?將所有寄存器保存在函數調用上不會產生任何效果,但是上下文切換必須保存發生上下文切換時可能正在使用的任何寄存器。擁有帶有擴展寄存器文件(可通過操作碼前綴訪問)的系統可能會有一些好處,其中每個寄存器都有一個額外的“使用中”位,可以在此處讀取32或64個寄存器的“使用中”狀態一次,並且寄存器保存/恢復只需要處理“使用中”的寄存器,但是我不確定這是否值得。
@supercat-如果您不打算以上下文本地方式使用某些寄存器,則沒有理由保存它們。因此,保存它們的需要由所選的ABI決定,而不是在硬件中具有不必要的寄存器的強製成本。例如,如果您不打算使用集成FPU,則即使它們存在於芯片中,也沒有理由保存唯一的寄存器。ISR無需保存不會碰到的寄存器。而且,可能不了解細節的操作系統調度程序類型的任務開關在計算方面往往很少。
@ChrisStratton:我認為異步上下文切換必須保留正在運行的代碼可能正在使用的所有寄存器。當使用直接返回到先前代碼的中斷時,這是否意味著將它們複製到內存中或只是使其不受干擾就不會改變語義。但是,任何未在堆棧開關之間保留的寄存器實際上將是無用的(單個任務“擁有”但其他任何東西都未使用的寄存器將在上下文開關中往返該任務保留)。
ABI的工作是(而不是硬件)指示“正在運行的代碼可能正在使用的所有寄存器”。ABI是模塊之間的*合同*,它可以精確地控制這些事情!將寄存器放入硬件中並不強制ABI要求保存它;而據稱違反了ABI的程序員或編譯器已經有許多其他方式可以引起問題。
@MichelBillaud大約為零。
@supercat:實際上,許多體系結構都提供了一種上下文切換代碼的方法,以檢查自上次保存以來已觸摸了哪些擴展寄存器集,從理論上講,這消除了許多應用程序的成本。但是後來有人認為它們很聰明,讓`memcpy`使用所有向量寄存器...。
@ChrisStratton:雖然“不能使用寄存器X和Y”被認為是“ ABI”的一部分(例如,在mips上的k0和k1寄存器)有一些先例,但這是不尋常的用法。如果在上下文切換時未保存/恢復這些“禁止ABI的寄存器”,則肯定會在進程之間存在不需要的/不安全的隱式消息通道。即,不應該進行通信的進程可以通過將信息存儲在禁止的寄存器中並等待上下文切換來進行通信。
*“寄存器與ALU緊密綁定,可以擔當數據源,接收器,修飾符等的許多角色。因此,它們需要大量的寬復用連接” *不一定如此,並非所有寄存器都是通用且可互換的。完全可以使用FP寄存器,索引寄存器,算術寄存器等。SPARC,x86,Z80和其他工具可以做到這一點。
Uwe
2016-09-09 11:54:59 UTC
view on stackexchange narkive permalink

必須在說明內找到寄存器。如果寄存器很多,指令會更長。如果寄存器很多,則為中斷服務保存和恢復寄存器內容需要更多時間。

Arsenal
2016-09-09 11:52:49 UTC
view on stackexchange narkive permalink

大多數情況下,寄存器的數量是成本,複雜性和實用性之間的折衷。

寄存器被實現為多端口靜態RAM,這使其比其他存儲選項成本更高(芯片面積)。

然後它們與處理器的指令集耦合,增加寄存器的數量會增加指令集的複雜性。因此,如果您想與指令集保持兼容,就不能僅僅增加下一代處理器中可用寄存器的數量來提高效率,這些程序就不會使用它們。

接下來,您真正需要多少寄存器?它們的用途是有限的。考慮您編寫了一種算法,該算法在1024字節上執行一些數學運算,比方說乘以5。使用當前的寄存器計數,最終會得到類似:

  load操作數1 = 5
加載地址
循環:加載操作數2 = byte1 @ address
將Register1乘以Register2
儲存結果
遞增地址
如果地址=結束goto endLoop
跳躍循環
endLoop:
 

現在,如果您將擁有1024個寄存器並將所有數據存儲在其中,則程序將如下所示:

 將Register1與Register2相乘
將Register1乘以Register3
將Register1乘以Register4
將Register1乘以Register5
將Register1與Register6相乘
...
 

由於每個指令都是不同的指令,因此每個指令都必須寫出。因此,您所需的程序存儲器正在爆炸。在意識到這一點之後,您可能想要引入一些指令,例如將register1與register(2到256)乘以。但是什麼時候停止,您會提供所有組合的說明嗎?

所以也許我們目前可用的數字是成本,複雜性和實用性之間的一個很好的權衡。

我認為程序`將Register1與Register2相乘 將Register1與Register3`相乘是非常不現實的,因為數據必須直接或間接來自計算機外部,因此需要加載寄存器,並且需要在某個地方直接或間接使用結果,因此需要存儲寄存器。實際上,針對高級語言的體面的優化編譯器將“展開”第一個程序的循環以創建類似於第二個程序的內容,從而優化寄存器使用,內存延遲,可能的緩存佔用率和執行速度。
不需要許多特殊用途的“將register1與register(2到256)相乘”指令。流水線顯著提高了CPU吞吐量,特別是對於更易於解碼和執行指令而言。因此,可以通過使用幾個具有較高執行率的較簡單的指令來實現複雜的大量指令的效果。擁有更多的寄存器有助於編譯器生成許多獨立的指令(不共享寄存器的指令),這些指令可以獨立完成,從而提高了吞吐量。您的示例=更多的寄存器更好。
gnasher729
2016-09-10 01:18:18 UTC
view on stackexchange narkive permalink

寄存器非常昂貴。非常貴。與其說寄存器本身,不如說是寄存器之間的所有連接。假設您有一條指令reg1 = reg2 + reg3。要實現這種 fast ,您需要在一個週期內從兩個寄存器讀取數據,並在第二個週期內寫入另一個寄存器。現在,如果您有一個處理器每個週期可以執行多個指令(例如3條指令),則您需要能夠每個週期從6個寄存器讀取數據,並將數據寫入3個寄存器。那是非常可怕的,非常快的連接。

當然,您可以只使用更多的晶體管。問題是:速度下降。您需要更多的硬件來從更多的寄存器中進行選擇。寄存器文件的空間變大。所有這些使事情變慢。因此,使用相同的技術,您可能能夠擁有16個寄存器並以2,600 MHz運行,或者有32個寄存器並以2,400 MHz運行。現在,額外的寄存器必須彌補時鐘速度的大幅下降。

Elbehery
2016-09-09 20:03:39 UTC
view on stackexchange narkive permalink

什麼因素影響寄存器的數量

-內存層次結構

寄存器,高速緩存,RAM均使用不同的存儲技術實現。

不同技術的不同之處

  1. 訪問時間
  2. 費用
  3. 密度
  4. ol>

    一個例子:CPU中的內部寄存器是靜態隨機存取存儲器,而計算機主存儲器是動態隨機存取存儲器

    使用6晶體管電路實現靜態RAM二進制單元,而使用電容器和晶體管實現動態RAM二進制單元。比較SRAM和DRAM

  • SRAM存儲器比DRAM存儲器快得多[與DRAM相比,訪問SRAM的周期很少]
  • SRAM電路比DRAM消耗的功率更少
  • 與SRAM不同,DRAM需要定期刷新內存中的每個位
  • SRAM的成本高於DRAM
  • 與DRAM相比,SRAM的密度更低

因此,增加快速,昂貴,密度較小的內存的數量並不是實際的事情。實際上,我們可能會使用其中的一些,編寫良好的程序會將最常用的數據存儲在這些快速寄存器中,而較不常用的數據則存儲在較慢的內存中。

-指令長度

寄存器中的地址包含在一條指令中,該指令根據可以表示該地址的位數來限制可訪問寄存器的數量。例如,在MIPS架構中,32位長度的指令僅保留5位來表示可訪問寄存器的地址,這將寄存器的數量限制為2 5 sup> = 32個寄存器。增加寄存器的數量將需要增加指令長度,以包括足夠的位來訪問所有寄存器。

John Burger
2016-09-09 11:36:35 UTC
view on stackexchange narkive permalink

如果您查看處理器的指令集,則有多種將它們分組的方法。例如,所有 ADD 指令可能會與所有 XOR 指令分組在一起。

在同一指令的每一組中,可能有一些版本在存儲器或寄存器上運行。正是這個子分組有效地定義了處理器擁有的寄存器數量。

作為一個8位的假設示例,假設 $ Ax 指令可能是 ADD 指令,而 $ Cx 可能是 XOR 指令。通過這種設計,只剩下四個位來定義操作數!

  • 一個可能只有四個通用寄存器,並且用兩位定義一個,而用兩位定義另一個。
  • 或者,可以使用第一位來區分“特殊”變量,而使用其他3位來定義要使用累加器操作的八個寄存器中的哪一個( $ x0 可以是累加器本身)
  • 或者,一個寄存器可能會超過此數量-但是要限制哪些指令可以訪問哪些寄存器。

當然,我們已經過了8位指令集。但是,這種邏輯過去仍在幫助定義寄存器集-將來它將繼續這樣做。

編輯(按要求)

說指令的高四位是: ADD SUB XOR MOV CMP 等。這裡有16種可能性。然後,對於那些有意義的寄存器間指令(例如 ADD Rx,Ry ),您需要指定 Rx Ry 。假設接下來的兩位是 x ,最後兩位是 y 。因此:

  ADD R1,R2 = >'ADD'+'R1'+'R2'= > $ A0 + $ 04 + $ 02
 

只有兩個位可以定義一個這樣的寄存器,總共只有四個寄存器!

順便說一句,您會注意到某些寄存器組合沒有意義。例如, MOV Rx,Rx (不執行任何操作)和 SUB Rx,Rx (始終生成 0 )。這些可能成為特殊情況的說明:

  1. SUB Rx,Rx 可能變成 NOT Rx -單操作數指令。
  2. MOV Rx,Rx 可能會成為 MOV 指令,該指令將第二個字節作為立即值,解釋為 MOV Rx,#$ yy
  3. ol>

    通過這種方式,您可以“玩”指令圖,為其他無用或無意義的指令填充空洞,從而為程序員提供更大的指令集。但最終,指令集定義了寄存器集。

我還是很困惑,您能解釋一下操作數只剩下4位嗎?
檢查我更新的答案
恕我直言,通過將“ *假設示例假定為8位指令集*”移至問題的開頭,可以大大改善此答案。我浪費了時間嘗試理解它,得出結論只對8位固定長度的指令有意義,然後繼續閱讀以發現確實如此。恕我直言,這種指令集在問題中並不是很無關緊要。它的整個地址空間可以是緊密耦合的靜態RAM。我還認為以“ *某些寄存器組合沒有意義... *”開頭的部分與該問題無關,可以刪除。我的$ 0.02
MSalters
2016-09-09 12:30:03 UTC
view on stackexchange narkive permalink

如今,英特爾正在使用數千個寄存器-每個CPU內核數百個。但是,存儲在CPU上的最大數據量是在緩存中,這間接地回答了這個問題。緩存是分層組織的,其中較小的快速L1緩存和較慢的L2和L3緩存距離較遠。從某種意義上說,寄存器文件是L0,甚至比L1還要快,但還要更小。因此,您可以增加寄存器的數量,但這可能會減慢它們的速度。



該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 3.0許可。
Loading...