日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构是如何装入 CPU 寄存器的?

發(fā)布時(shí)間:2024/8/23 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构是如何装入 CPU 寄存器的? 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

作者|碼農(nóng)的荒島求生

來源|碼農(nóng)的荒島求生

有同學(xué)問了這樣一個(gè)問題:既然CPU內(nèi)部的寄存器數(shù)量有限,容量有限,那么我們使用的龐大的數(shù)據(jù)結(jié)構(gòu)是怎樣裝入寄存器供CPU計(jì)算的呢

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

內(nèi)存與數(shù)據(jù)

真正有用的程序是離不開數(shù)據(jù)的,比如一個(gè)int、一個(gè)float等,這些都是非常簡單的數(shù)據(jù)。

當(dāng)然也有非常復(fù)雜的數(shù)據(jù),這樣的數(shù)據(jù)通常在內(nèi)存中以數(shù)據(jù)結(jié)構(gòu)的形式組織起來,比如你創(chuàng)建了一個(gè)數(shù)組、一個(gè)鏈表、創(chuàng)建了一棵樹、一張圖,就像這樣:

那么很顯然這些數(shù)據(jù)存放在內(nèi)存中,而且這些數(shù)據(jù)在不同的場景下有不同的大小,從數(shù)B、數(shù)KB到數(shù)百GB都有可能,與此同時(shí),CPU內(nèi)部的寄存器數(shù)量是固定的,容量也是極其有限的,那么CPU是如何利用有限的資源操作龐大的數(shù)據(jù)結(jié)構(gòu)呢?

要回答這一問題,我們需要要認(rèn)識一位農(nóng)夫,因?yàn)樗簧a(chǎn)數(shù)據(jù),他只是數(shù)據(jù)的搬運(yùn)工,這位農(nóng)夫就是。。

搬運(yùn)數(shù)據(jù)的機(jī)器指令

你沒有看錯(cuò),這位農(nóng)夫就是我們之前多次提到的機(jī)器指令。

機(jī)器指令中除了負(fù)責(zé)邏輯運(yùn)算、執(zhí)行流控制、函數(shù)調(diào)用等指令外,還有一類指令,這類執(zhí)行只負(fù)責(zé)和內(nèi)存打交道,典型的就是精簡指令集架構(gòu)中的Load/Store機(jī)器指令,即內(nèi)存讀寫指令(復(fù)雜指令集沒有單獨(dú)的內(nèi)存讀寫指令)。

原來,從宏觀上看的話,存放在內(nèi)存中的數(shù)據(jù),比如一個(gè)數(shù)組,可能會非常龐大,但是具體到代碼,每一個(gè)步驟操作的數(shù)據(jù)又會非常簡單,就像這樣:

int*?huge_arr?=?new?int[1?*?1024*?1024?*1024];

我們創(chuàng)建了一個(gè)長度為1G的數(shù)組,每個(gè)int 4字節(jié),則這個(gè)數(shù)組的大小就是4GB,這顯然是一個(gè)很龐大的數(shù)組。

對于這樣的數(shù)據(jù),我們通常都會怎么使用呢?

最常見的情況可能是遍歷一邊,然后對每個(gè)字符進(jìn)行一個(gè)簡單操作,這里以計(jì)算數(shù)組之和為例:

long int sum = 0; for (int i = 0; i < 1 * 1024* 1024 *1024; i++) {sum += huge_arr[i]; }

雖然整個(gè)數(shù)組多達(dá)4GB,但具體到每一步我們一次只能操作一個(gè)元素,就像這里的:

sum += huge_arr[i];

這行代碼翻譯成機(jī)器指令可能是這樣的,我們假設(shè)此時(shí)i為100:

load $r0 100($r2) add $r1 $r1 $r0

(注意,實(shí)際當(dāng)中編譯器不會傻傻的生成100這樣的常數(shù),這里代碼僅用來方便講解問題)。

第一行指令中數(shù)組首地址存放在寄存器r2中,100($r2)表示數(shù)組首地址+100,這樣我們就能得到huge_arr[100]的地址了,然后將該地址中的值利用load指令加載到寄存器r0中。

第二行就簡單多了,r1寄存器中保存的是sum的值,該行指令執(zhí)行過后r1中的值就已經(jīng)加上了huge_arr[100]。

現(xiàn)在你應(yīng)該能看出來了吧,雖然我們不能把整個(gè)數(shù)組加載到寄存器供CPU計(jì)算,但這其實(shí)是沒有必要的,因?yàn)槲覀円淮沃荒懿僮鲾?shù)組中的一個(gè)元素,我們只需要把這一個(gè)元素加載到寄存器就足矣了

對于其它復(fù)雜的數(shù)據(jù)結(jié)構(gòu)也是同樣的道理,無論多么復(fù)雜的數(shù)據(jù),代碼對其一次的操作都是很簡單很微小的,這一微小的操作使用的基本元素都可以通過內(nèi)存讀寫指令加載到寄存器,修改完后再寫回內(nèi)存。

編譯器

現(xiàn)在你應(yīng)該知道了為什么CPU內(nèi)部那么少的寄存器能操作內(nèi)存中龐大的數(shù)據(jù)結(jié)構(gòu),實(shí)際上由于內(nèi)存中的數(shù)據(jù)要遠(yuǎn)大于CPU寄存器的容量,因此編譯器必須精心挑選,好讓那些經(jīng)常使用的數(shù)據(jù)放到寄存器中的時(shí)間更長一點(diǎn),這樣可以減少內(nèi)存讀寫次數(shù)。

在上面的示例中,r2寄存器保存的是huge_arr這個(gè)數(shù)組在內(nèi)存中的起始地址,那么這個(gè)數(shù)據(jù)應(yīng)該放到寄存器中,因?yàn)楹罄m(xù)遍歷到的每一個(gè)元素都要用到該地址,這項(xiàng)工作就是編譯器來完成的。

編譯器把那些經(jīng)常使用的數(shù)據(jù)放到寄存器,剩下的放到內(nèi)存中,然后利用內(nèi)存讀寫指令在寄存器和內(nèi)存之間來回搬運(yùn)數(shù)據(jù)。

總結(jié)

通過本文不難發(fā)現(xiàn),實(shí)際上我們沒有必要一次性把整個(gè)數(shù)據(jù)全部裝到CPU寄存器中,而是用到哪些才裝載哪些。

在最細(xì)粒度的操作中,依賴的操作數(shù)都可以直接加載到內(nèi)存,這通常是由內(nèi)存讀寫機(jī)器指令來完成的。

希望這篇文章對大家理解CPU與寄存器有所幫助。

往期推薦

做安全操作系統(tǒng),這位技術(shù)老兵很認(rèn)真

這個(gè)高薪行業(yè)正在大量招人!

如何給女朋友解釋什么是“元宇宙”?

張一鳴購得元宇宙入場券,誰將是頭號玩家?

點(diǎn)分享

點(diǎn)收藏

點(diǎn)點(diǎn)贊

點(diǎn)在看

總結(jié)

以上是生活随笔為你收集整理的数据结构是如何装入 CPU 寄存器的?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。