计算机运行时内存&处理器CPU初步认知
蕪湖起飛。
1.馮諾依曼計(jì)算機(jī)模型
計(jì)算機(jī)在運(yùn)行時(shí),先從內(nèi)存中取出第一條指令,通過控制器的譯碼,按指令的要求,從存儲器中取出數(shù)據(jù)進(jìn)行指定的運(yùn)算和邏輯操作等加工,然后再按地址把結(jié)果送到內(nèi)存中去。 接下來,再取出第二條指令,在控制器的指揮下完成規(guī)定操作。依此進(jìn)行下去。直至遇到停止指令。
程序與數(shù)據(jù)一樣存貯,按程序編排的順序,一步一步地取出指令,自動地完成指令規(guī)定 的操作是計(jì)算機(jī)最基本的工作模型。
這都是數(shù)學(xué)家馮.諾依曼提出的,所以被稱作馮諾依曼計(jì)算機(jī)模型。
計(jì)算機(jī)核心組成部分:
1. 控制器(Control):是整個(gè)計(jì)算機(jī)的中樞神經(jīng),其功能是對程序規(guī)定的控制信息進(jìn)行 解釋,根據(jù)其要求進(jìn)行控制,調(diào)度程序、數(shù)據(jù)、地址,協(xié)調(diào)計(jì)算機(jī)各部分工作及內(nèi)存與外設(shè) 的訪問等。
2. 運(yùn)算器(Datapath):運(yùn)算器的功能是對數(shù)據(jù)進(jìn)行各種算術(shù)運(yùn)算和邏輯運(yùn)算,即對數(shù)據(jù) 進(jìn)行加工處理。
3. 存儲器(Memory):存儲器的功能是存儲程序、數(shù)據(jù)和各種信號、命令等信息,并在 需要時(shí)提供這些信息。
4. 輸入(Input system):輸入設(shè)備是計(jì)算機(jī)的重要組成部分,輸入設(shè)備與輸出設(shè)備合你 為外部設(shè)備,簡稱外設(shè),輸入設(shè)備的作用是將程序、原始數(shù)據(jù)、文字、字符、控制命令或現(xiàn) 場采集的數(shù)據(jù)等信息輸入到計(jì)算機(jī)。常見的輸入設(shè)備有鍵盤、鼠標(biāo)器、光電輸入機(jī)、磁帶 機(jī)、磁盤機(jī)、光盤機(jī)等。
5. 輸出(Output system):輸出設(shè)備與輸入設(shè)備同樣是計(jì)算機(jī)的重要組成部分,它把外 算機(jī)的中間結(jié)果或最后結(jié)果、機(jī)內(nèi)的各種數(shù)據(jù)符號及文字或各種控制信號等信息輸出出來。 微機(jī)常用的輸出設(shè)備有顯示終端CRT、打印機(jī)、激光印字機(jī)、繪圖儀及磁帶、光盤機(jī)等。
圖解馮諾依曼計(jì)算機(jī)模型:
這是一個(gè)抽象的模型,并不是我們現(xiàn)代計(jì)算機(jī)具體實(shí)現(xiàn)的模型,那么我們現(xiàn)代計(jì)算機(jī)的硬件和模型是怎么樣的呢?
2.運(yùn)行時(shí)內(nèi)存
運(yùn)行時(shí)內(nèi)存,就是內(nèi)存條大小,你的內(nèi)存條是16g,你的計(jì)算機(jī)運(yùn)行內(nèi)存就是接近16g;
操作系統(tǒng)有用戶空間與內(nèi)核空間兩個(gè)概念,目的也是為了做到程序運(yùn)行安全隔離與穩(wěn)定。
以32位系統(tǒng),4g內(nèi)存為例,內(nèi)存的分配就是下圖所示:
Linux為內(nèi)核代碼和數(shù)據(jù)結(jié)構(gòu)預(yù)留了幾個(gè)頁框,這些頁永遠(yuǎn)不會被轉(zhuǎn)出到磁盤上。從 0x00000000 到 0xc0000000(PAGE_OFFSET) 的線性地址可由用戶代碼 和 內(nèi)核代碼進(jìn) 行引用(即用戶空間)。從0xc0000000(PAGE_OFFSET)到 0xFFFFFFFFF的線性地址只 能由內(nèi)核代碼進(jìn)行訪問(即內(nèi)核空間)。內(nèi)核代碼及其數(shù)據(jù)結(jié)構(gòu)都必須位于這 1 GB的地址 空間中,但是對于此地址空間而言,更大的消費(fèi)者是物理地址的虛擬映射。
這意味著在 4 GB 的內(nèi)存空間中,只有 3 GB 可以用于用戶應(yīng)用程序。進(jìn)程與線程只能 運(yùn)行在用戶方式(usermode)或內(nèi)核方式(kernelmode)下。用戶程序運(yùn)行在用戶方式 下,而系統(tǒng)調(diào)用運(yùn)行在內(nèi)核方式下。在這兩種方式下所用的堆棧不一樣:用戶方式下用的是 一般的堆棧(用戶空間的堆棧),而內(nèi)核方式下用的是固定大小的堆棧(內(nèi)核空間的堆棧,一 般為一個(gè)內(nèi)存頁的大小),即每個(gè)進(jìn)程與線程其實(shí)有兩個(gè)堆棧,分別運(yùn)行與用戶態(tài)與內(nèi)核 態(tài)。
(用戶空間和內(nèi)核空間隔離是為了保護(hù)操作系統(tǒng)空間不受用戶進(jìn)程影響,保護(hù)操作系統(tǒng))
jvm運(yùn)行所用的就是用戶空間,那么我們程序跟內(nèi)存是怎么交互的呢?如下圖:
3.CPU處理器
3.1CPU結(jié)構(gòu)
控制單元:控制單元是整個(gè)CPU的指揮控制中心,由指令寄存器IR(Instruction Register)、指 令譯碼器ID(Instruction Decoder)和 操作控制器OC(Operation Controller) 等組 成,對協(xié)調(diào)整個(gè)電腦有序工作極為重要。它根據(jù)用戶預(yù)先編好的程序,依次從存儲器中取出 各條指令,放在指令寄存器IR中,通過指令譯碼(分析)確定應(yīng)該進(jìn)行什么操作,然后通過 操作控制器OC,按確定的時(shí)序,向相應(yīng)的部件發(fā)出微操作控制信號。操作控制器OC中主要 包括:節(jié)拍脈沖發(fā)生器、控制矩陣、時(shí)鐘脈沖發(fā)生器、復(fù)位電路和啟停電路等控制邏輯。
運(yùn)算單元:運(yùn)算單元是運(yùn)算器的核心。可以執(zhí)行算術(shù)運(yùn)算(包括加減乘數(shù)等基本運(yùn)算及其附加運(yùn) 算)和邏輯運(yùn)算(包括移位、邏輯測試或兩個(gè)值比較)。相對控制單元而言,運(yùn)算器接受控 制單元的命令而進(jìn)行動作,即運(yùn)算單元所進(jìn)行的全部操作都是由控制單元發(fā)出的控制信號來 指揮的,所以它是執(zhí)行部件。
存儲單元:存儲單元包括 CPU 片內(nèi)緩存Cache和寄存器組,是 CPU 中暫時(shí)存放數(shù)據(jù)的地方,里 面保存著那些等待處理的數(shù)據(jù),或已經(jīng)處理過的數(shù)據(jù),CPU 訪問寄存器所用的時(shí)間要比訪 問內(nèi)存的時(shí)間短。 寄存器是CPU內(nèi)部的元件,寄存器擁有非常高的讀寫速度,所以在寄存 器之間的數(shù)據(jù)傳送非常快。采用寄存器,可以減少 CPU 訪問內(nèi)存的次數(shù),從而提高了 CPU 的工作速度。寄存器組可分為專用寄存器和通用寄存器。專用寄存器的作用是固定的,分別 寄存相應(yīng)的數(shù)據(jù);而通用寄存器用途廣泛并可由程序員規(guī)定其用途。
圖解CPU結(jié)構(gòu):
3.2CPU緩存結(jié)構(gòu)
現(xiàn)代CPU為了提升執(zhí)行效率,減少CPU與內(nèi)存的交互(交互影響CPU效率),一般在CPU上集 成了多級緩存架構(gòu),常見的為三級緩存結(jié)構(gòu)。
L1 Cache:分為數(shù)據(jù)緩存和指令緩存,邏輯核獨(dú)占
L2 Cache:物理核獨(dú)占,邏輯核共享
L3 Cache:所有物理核共享
打開任務(wù)管理器,打開第二欄性能,我們就能查看自己電腦的CPU緩存情況,下面是我的電腦CPU的L1,L2,L3緩存情況:
圖解CPU緩存結(jié)構(gòu):
存儲器存儲空間大小:內(nèi)存>L3>L2>L1>寄存器;
存儲器速度快慢排序:寄存器>L1>L2>L3>內(nèi)存;(越接近內(nèi)核的存儲容量越小,效率越高)
緩存行:緩存是由最小的存儲區(qū)塊-緩存行(cacheline)組成,緩存行大小通 常為64byte。(比如你的L1緩存大小是512kb,而cacheline = 64byte,那么就是L1里有512 * 1024/64個(gè))
為什么CPU要設(shè)計(jì)緩存?
CPU在摩爾定律的指導(dǎo)下以每18個(gè)月翻一番的速度在發(fā)展,然而內(nèi)存和硬盤的發(fā)展速度遠(yuǎn)遠(yuǎn)不及 CPU。這就造成了高性能能的內(nèi)存和硬盤價(jià)格及其昂貴。然而CPU的高度運(yùn)算需要高速的數(shù)據(jù)。為了解決 這個(gè)問題,CPU廠商在CPU中內(nèi)置了少量的高速緩存以解決IO速度和CPU運(yùn)算速度之間的不匹配問題。(內(nèi)存條的硬件發(fā)展跟不上CPU,為了減少CPU和內(nèi)存條交互,CPU的發(fā)展過程中就加入了緩存)
3.3CPU讀取存儲數(shù)據(jù)過程
1、CPU要取寄存器X的值,只需要一步:直接讀取。
2、CPU要取L1 cache的某個(gè)值,需要1-3步(或者更多):把cache行鎖住,把某個(gè)數(shù)據(jù)拿來,解 鎖,如果沒鎖住就慢了。
3、CPU要取L2 cache的某個(gè)值,先要到L1 cache里取,L1當(dāng)中不存在,在L2里,L2開始加鎖,加 鎖以后,把L2里的數(shù)據(jù)復(fù)制到L1,再執(zhí)行讀L1的過程,上面的3步,再解鎖。
4、CPU取L3 cache的也是一樣,只不過先由L3復(fù)制到L2,從L2復(fù)制到L1,從L1到CPU。
5、CPU取內(nèi)存則最復(fù)雜:通知內(nèi)存控制器占用總線帶寬,通知內(nèi)存加鎖,發(fā)起內(nèi)存讀請求,等待 回應(yīng),回應(yīng)數(shù)據(jù)保存到L3(如果沒有就到L2),再從L3/2到L1,再從L1到CPU,之后解除總線鎖定。
CPU執(zhí)行計(jì)算的流程
1. 程序以及數(shù)據(jù)被加載到主內(nèi)存
2. 指令和數(shù)據(jù)被加載到CPU的高速緩存
3. CPU執(zhí)行指令,把結(jié)果寫到高速緩存
4. 高速緩存中的數(shù)據(jù)寫回主內(nèi)存
3.4CPU局部性
在CPU訪問存儲設(shè)備時(shí),無論是存取數(shù)據(jù)抑或存取指令,都趨于聚集在一片連續(xù)的區(qū)域中,這就被稱為局部性原理。
時(shí)間局部性(Temporal Locality):如果一個(gè)信息項(xiàng)正在被訪問,那么在近期它很可能還會被再次訪問。 比如循環(huán)、遞歸、方法的反復(fù)調(diào)用等。(如果一個(gè)數(shù)據(jù)被load到內(nèi)存里面,對這個(gè)數(shù)據(jù)的操作指令執(zhí)行完成以后,這個(gè)數(shù)據(jù)不會在緩存中馬上清除,很有可能這個(gè)數(shù)據(jù)還會再次被用到)
空間局部性(Spatial Locality):如果一個(gè)存儲器的位置被引用,那么將來他附近的位置也會被引用。 比如順序執(zhí)行的代碼、連續(xù)創(chuàng)建的兩個(gè)對象、數(shù)組等。(從內(nèi)存中加載一個(gè)數(shù)據(jù)到緩存里面去,CPU會把這個(gè)數(shù)據(jù)周圍的一些數(shù)據(jù)也加載到緩存中去)(緩存行)
對于空間局部性,我們來看下面這段代碼:
private static int length1 = 1024*1024;
private static int length2 = 6;
private static int runs = 100;
public static void main(String[] args) {
long[][] array = new long[1024*1024][6];
/**
* 初始化二維數(shù)組
*/
for (int i = 0; i < length1; i++) {
array[i] = new long[length2];
for (int j = 0; j < length2; j++) {
array[i][j] = 1;
}
}
System.out.println("數(shù)組初始化完畢++++");
long sum = 0L;
long start = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
for (int j = 0; j < length1; j++) {
for (int k = 0; k< length2; k++) {
sum += array[j][k];
}
}
}
long end = System.currentTimeMillis();
System.out.println("sum:"+ sum);
System.out.println("第一次相加完畢,耗時(shí)"+ (end - start));
sum = 0L;
start = System.currentTimeMillis();
for (int i = 0; i < runs; i++) {
for (int j = 0; j < length2; j++) {
for (int k = 0; k< length1; k++) {
sum += array[k][j];
}
}
}
end = System.currentTimeMillis();
System.out.println("sum:"+ sum);
System.out.println("第二次相加完畢,耗時(shí)"+ (end - start));
}
執(zhí)行 結(jié)果:
數(shù)組初始化完畢++++ sum:629145600 第一次相加完畢,耗時(shí)1643 sum:629145600 第二次相加完畢,耗時(shí)3461
我們可以看出,第一次執(zhí)行速度明顯要高于第二次執(zhí)行速度。
這是因?yàn)槿绻缘谝环N循環(huán)方式,循環(huán)1024*1024次,每次只相加6條數(shù)據(jù),6條數(shù)據(jù),都是long,一共是48byte,我們cpu的緩存行一個(gè)是64byte,然后根據(jù)空間局部性原則,這6個(gè)數(shù)據(jù)都會被讀到一個(gè)緩存行里面;如果是第二種循環(huán)方式,循環(huán)6次,每次都是1024*1024條數(shù)據(jù),一個(gè)緩存行肯定是放不下的,所以CPU要去和內(nèi)存交互1024*1024次,所以效率比第一種循環(huán)要低得多。
3.4CPU運(yùn)行安全等級
CPU有4個(gè)運(yùn)行級別,分別為:
ring0
ring1
ring2
ring3
Linux與Windows只用到了2個(gè)級別:ring0、ring3,操作系統(tǒng)內(nèi)部內(nèi)部程序指令通常運(yùn)行在ring0級別,操作系統(tǒng)以外的第三方程序運(yùn)行在ring3級別,第三方程序如果要調(diào)用操作 系統(tǒng)內(nèi)部函數(shù)功能,由于運(yùn)行安全級別不夠,必須切換CPU運(yùn)行狀態(tài)(IO操作,JVM創(chuàng)建線程等,都需要切換到ring3級別),從ring3切換到ring0, 然后執(zhí)行系統(tǒng)函數(shù),說到這里相信明白為什么JVM創(chuàng)建線程,線程阻塞喚醒是重型操作了,因?yàn)镃PU要切換運(yùn)行狀態(tài)。
JVM創(chuàng)建線程CPU的工作過程:
1:CPU從ring3切換ring0創(chuàng)建線程
2:創(chuàng)建完畢,CPU從ring0切換回ring3
3:線程執(zhí)行JVM程序
4:線程執(zhí)行完畢,銷毀還得切會ring0
3.5CPU線程模型
內(nèi)核線程模型:系統(tǒng)內(nèi)核管理線程(KLT),內(nèi)核保存線程的狀態(tài)和上下文信息,線程阻塞不會引起進(jìn)程阻塞。在多處理器系統(tǒng)上,多線程在多處理器上并行運(yùn)行。線程的創(chuàng)建、調(diào)度和管 理由內(nèi)核完成,效率比ULT要慢,比進(jìn)程操作快。
用戶線程模型:用戶程序?qū)崿F(xiàn),不依賴操作系統(tǒng)核心,應(yīng)用提供創(chuàng)建、同步、調(diào)度和管理線程 的函數(shù)來控制用戶線程。不需要用戶態(tài)/內(nèi)核態(tài)切換,速度快。內(nèi)核對ULT無感知,線程阻 塞則進(jìn)程(包括它的所有線程)阻塞。
JVM使用的線程模型?
我們來看下面代碼:
public static void main(String[] args) {
for (int i =0; i < 200; i++) {
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
如果我們的CPU能感知到線程的創(chuàng)建,那么久說明JVM用的是用戶線程模型,如果CPU不能感知,那么就是內(nèi)核線程模型。
執(zhí)行前我們打開任務(wù)管理器,看看系統(tǒng)線程是多少個(gè):
基本穩(wěn)定在1940左右,我們執(zhí)行代碼,在看線程數(shù)量:
基本上是多個(gè)200個(gè)線程左右,這說明,這些線程都是由操作系統(tǒng)創(chuàng)建的,所以,JVM的線程就是用戶線程模型。
4.運(yùn)行內(nèi)存和CPU關(guān)系
用一張圖來說的話:
上面就是運(yùn)行內(nèi)存和CPU的一些初步認(rèn)知,我們學(xué)這些東西只是為了更好的了解電腦工作原理,了解程序和硬件之間的交互,為了寫出更高質(zhì)量的代碼!
總結(jié)
以上是生活随笔為你收集整理的计算机运行时内存&处理器CPU初步认知的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 智能变道无压力!百度地图“自动驾驶级”导
- 下一篇: 一只老鹰在南京中暑坠江 终被救治放归自然