<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>
"); //-->

博客專(zhuān)欄

EEPW首頁(yè) > 博客 > 數據結構是如何裝入 CPU 寄存器的?

數據結構是如何裝入 CPU 寄存器的?

發(fā)布人:編碼之外 時(shí)間:2021-08-19 來(lái)源:工程師 發(fā)布文章
我們在之前很多文章的講解中涉及了CPU與寄存器,然后有同學(xué)問(wèn)了這樣一個(gè)問(wèn)題:既然CPU內部的寄存器數量有限,容量有限,那么我們使用的龐大的數據結構是怎樣裝入寄存器供CPU計算的呢?

這篇文章就為你講解一下這個(gè)問(wèn)題。


內存與數據

真正有用的程序是離不開(kāi)數據的,比如一個(gè)int、一個(gè)float等,這些都是非常簡(jiǎn)單的數據。當然也有非常復雜的數據,這樣的數據通常在內存中以數據結構的形式組織起來(lái),比如你創(chuàng )建了一個(gè)數組、一個(gè)鏈表、創(chuàng )建了一棵樹(shù)、一張圖,就像這樣:那么很顯然這些數據存放在內存中,而且這些數據在不同的場(chǎng)景下有不同的大小,從數B、數KB到數百GB都有可能,與此同時(shí),CPU內部的寄存器數量是固定的,容量也是極其有限的,那么CPU是如何利用有限的資源操作龐大的數據結構呢?要回答這一問(wèn)題,我們需要要認識一位農夫,因為他不生產(chǎn)數據,他只是數據的搬運工,這位農夫就是。。

搬運數據的機器指令

你沒(méi)有看錯,這位農夫就是我們之前多次提到的機器指令。機器指令中除了負責邏輯運算、執行流控制、函數調用等指令外,還有一類(lèi)指令,這類(lèi)執行只負責和內存打交道,典型的就是精簡(jiǎn)指令集架構中的Load/Store機器指令,即內存讀寫(xiě)指令(雜指令集沒(méi)有單獨的內存讀寫(xiě)指令)。原來(lái),從宏觀(guān)上看的話(huà),存放在內存中的數據,比如一個(gè)數組,可能會(huì )非常龐大,但是具體到代碼,每一個(gè)步驟操作的數據又會(huì )非常簡(jiǎn)單,就像這樣:


int* huge_arr = new int[1 * 1024* 1024 *1024];
我們創(chuàng )建了一個(gè)長(cháng)度為1G的數組,每個(gè)int 4字節,則這個(gè)數組的大小就是4GB,這顯然是一個(gè)很龐大的數組。對于這樣的數據,我們通常都會(huì )怎么使用呢?最常見(jiàn)的情況可能是遍歷一邊,然后對每個(gè)字符進(jìn)行一個(gè)簡(jiǎn)單操作,這里以計算數組之和為例:
long int sum = 0;for (int i = 0; i < 1 * 1024* 1024 *1024; i++) {    sum += huge_arr[i];}
雖然整個(gè)數組多達4GB,但具體到每一步我們一次只能操作一個(gè)元素,就像這里的:

sum += huge_arr[i];
這行代碼翻譯成機器指令可能是這樣的,我們假設此時(shí)i為100:


load $r0 100($r2)add $r1 $r1 $r0
(注意,實(shí)際當中編譯器不會(huì )傻傻的生成100這樣的常數,這里代碼僅用來(lái)方便講解問(wèn)題)。
第一行指令中數組首地址存放在寄存器r2中,100($r2)表示數組首地址+100,這樣我們就能得到huge_arr[100]的地址了,然后將該地址中的值利用load指令加載到寄存器r0中。第二行就簡(jiǎn)單多了,r1寄存器中保存的是sum的值,該行指令執行過(guò)后r1中的值就已經(jīng)加上了huge_arr[100]。現在你應該能看出來(lái)了吧,雖然我們不能把整個(gè)數組加載到寄存器供CPU計算,但這其實(shí)是沒(méi)有必要的,因為我們一次只能操作數組中的一個(gè)元素,我們只需要把這一個(gè)元素加載到寄存器就足矣了。對于其它復雜的數據結構也是同樣的道理,無(wú)論多么復雜的數據,代碼對其一次的操作都是很簡(jiǎn)單很微小的,這一微小的操作使用的基本元素都可以通過(guò)內存讀寫(xiě)指令加載到寄存器,修改完后再寫(xiě)回內存。

編譯器

現在你應該知道了為什么CPU內部那么少的寄存器能操作內存中龐大的數據結構,實(shí)際上由于內存中的數據要遠大于CPU寄存器的容量,因此編譯器必須精心挑選,好讓那些經(jīng)常使用的數據放到寄存器中的時(shí)間更長(cháng)一點(diǎn),這樣可以減少內存讀寫(xiě)次數。在上面的示例中,r2寄存器保存的是huge_arr這個(gè)數組在內存中的起始地址,那么這個(gè)數據應該放到寄存器中,因為后續遍歷到的每一個(gè)元素都要用到該地址,這項工作就是編譯器來(lái)完成的。編譯器把那些經(jīng)常使用的數據放到寄存器,剩下的放到內存中,然后利用內存讀寫(xiě)指令在寄存器和內存之間來(lái)回搬運數據。

總結

通過(guò)本文不難發(fā)現,實(shí)際上我們沒(méi)有必要一次性把整個(gè)數據全部裝到CPU寄存器中,而是用到哪些才裝載哪些。在最細粒度的操作中,依賴(lài)的操作數都可以直接加載到內存,這通常是由內存讀寫(xiě)機器指令來(lái)完成的。


*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。



關(guān)鍵詞: 數據結構

相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>