我(作者)開始寫這東西基本上是由于太閑。發這篇文是由于,一來本身就是想科普,二來發現到很多人對isa,cpu架構的誤解。
先說明關于本文的幾點:
1. 既然是科普向,那不是專門寫給專業人員看的,專業人員都喜歡看那些非常嚴肅,定義嚴謹的教科書,我本人是一個不大喜歡教科書式教育的人,所以這篇也不會是那種各種專業詞語亂飛的文章。但是我沒有在國內學習過cpu架構,所以有些名字我的確不喜歡或者不知道中文翻譯,會用英語原文。盡量不用這種文縐縐的語氣,多點用調侃或者比較非正式的話語。
2. 在這邊的公司面試的時候,我遇到過一個比較有趣的問題是:
你要設計cpu,你怎么向你奶奶解釋你現在的工作。
首先,我奶奶已經去世了,也沒辦法向她解釋。其實,這是一個非常有趣的問題,為什么面試的時候回經常問?因為cpu設計行業里面,很多專業的知識,別說一般市民,即使是公司里面的其他員工,隨時是跨領域的對話,所以,必須會用比較簡單的例子來解釋復雜的問題。
我當時回答是用廚房煮菜的過程來解釋cpu的流水線,這篇文當然也會常常用到類似的比喻,不是因為我喜歡做菜或者我是吃貨,是因為我當時只想到廚房。
3. 一篇全是文字的科普向文章是非常非常沉悶的,為了讓讀者不睡著,我會偶爾講冷笑話,如果太冷了,本人水平有限,望包含!下面開始:
什么是ISA?
ISA, Instruction Set Architecture. 中文就是,指令,集合,架構。在計算機里面,什么是ISA呢?就是xx定義的一個指令集,這里的xx可以指任何東西。比如你只會做加法,你就定義一個叫假發ISA,這個指令集只做加法,這也是一個isa。
任何一個ISA對于另外一個isa都沒有根本意義上的“先進”,ISA之間的對比是非常復雜的。你只會做加法,我只會做乘法,你說我們誰先進?我見得比較多的是爭吵x86 ISA比ARM ISA先進的,我往往一臉懵逼,好像他們比我懂,我是不是不應該插一腿進去...
x86 ISA現在是Intel和AMD共同擁有,也就是說如果你要開新的x86 cpu公司你必須向這兩者付版權費用,而且必須兩者都同意你才能獲得完整的ISA,如果你只獲得一部分不完整的ISA,那就和完全沒拿到ISA一樣(編者:我突然想到最近AMD給國內X86授權,按照作者的意思,是不是國內拿到的X86授權是不完整的?因為感覺Intel沒同意)。
ISA在cpu里面,就像是字典,用廚房的比喻就是菜譜,菜譜定義了你這個廚房會做什么菜,這個菜做出來是什么樣什么味道,那么顧客在這家連鎖店的任何一間都能叫到相同的菜,吃到相同的味道。
ARM ISA當然是ARM公司所有的,當時ARM公司是定菜單的,并且給出試菜的人,說你們每家店都要做出這個味才算ARM。而做店的則是不同的公司,像Qualcomn啦,他們中間喜歡怎么做菜是他們的自由,但是必須會那幾道菜,必須做出這個味。
各家的菜單都一樣,所以顧客不需要知道是誰做的菜,只要是這個菜單,做出來肯定一個味。因為操作系統根本不需要知道你cpu是怎么設計的,操作系統只要知道,我需要運行這些指令,你知道怎么運行就行了,每個不同牌子的cpu,只要你運行出來結果都一樣,就行了。
如果isa定義1+1=9,那么這個是定義下來的,所有人都這樣錯,就沒錯。如果isa定義了1+1=9,你要糾正他,我的cpu是1+1=2,那么你做出來的cpu雖然數學上正確,但是所有軟件,系統,就突然不知道怎么辦了。你說這么愚蠢的錯誤cpu不可能犯是吧?
自行百度一下蘋果75-37.5 bug(雖然不一定是cpu或者isa上的錯誤,也許是軟件上的)
然后又有人說ISA是鐵定下來的,x86的良好生態環境是因為他的ISA一直有legacy支持。legacy直接翻譯就是遺產。x86的legacy支持的意思就是,世界上第一個x86 cpu支持的東西,今年你發明的x86 cpu也支持,以后的也要支持。
的確從某個角度上來說,農企和Intel都非常努力的去支持很多已經沒什么人的東西,就是餐館里菜譜里面有些菜基本上你都不會去試的。你說你都不用了,農企Intel還在那里浪費設計是吧?你不用不代表沒人用啊,X國很多軍用的設備還是Windows95啊,甚至還是服役中的Windows3.1啊,銀行的atm還有用Windows98的。別問我為什么他們要那樣,如果他們肯花錢找些軟件工程師重新寫那些程序,就可以用最新的東西,很多沒有注釋,現在沒有人學的語言,或者算法詭異的程序,很多軍事設備還在用啊。
原因大概是:這種語言連學都沒人學,我自己都看不懂,我看你怎么破解我的坦克系統!
但是實際上x86又不是完全100%的legacy支持,至少ISA上面沒有這樣定義,農企和Intel也沒有官方明文定義。
x86里面有一個指令叫cpuid,系統/編譯器運行它的時候,它會給出一些數據,就是告訴系統/編譯器,這個cpu支持什么東西,這個cpu有些什么新東西之類的。所以,理論上可以設計一個cpu,不支持那些非常少用的指令,以降低cpu的設計復雜程度,也更省電省事。(對不起,你想吃的這個菜,我們不賣了,你找另外一家試試)
CPU架構
這個主題,如果你有編程經驗,食用效果更佳。
下面這段純屬個人經歷,無關主題,可跳過。
如果你有編程經驗,你有沒有想過,你寫的代碼是怎么運行的?
我當初就是由于這個原因而對cpu感興趣然后不知不覺進了這一行。
我是這樣的一個人,我看到輪子轉,我就想知道輪子是怎么轉的,我就想拆開馬達,拆開電線,然后學物理,學磁感線,然后知道是什么讓輪子轉。
后來由于各種原因我有緣接觸匯編,cpu架構之后,對比起編程,我對cpu的運行原理非常興趣,我是興趣使動的,然后就花時間去研究了。其實UIUC對于半導體,EE那邊的研究更多更有趣,但是那邊的教授的所有課讓我對computer architecture的有濃厚興趣。
我學習過程是這樣的,怎么寫c->c怎么編譯會匯編語言->匯編語言怎么在cpu里面運行->cpu的組成->transistor的原理->半導體的電子學應用->半導體的工業使用。
在學習半導體的時候,對各種光學半導體也曾經非常感興趣,沒有繼續學下去的原因是,設備太貴了,里面的數學太難了(對,說的就是數學,很多方程都沒有解答方法,很多是以前的數學家通過直接觀察式子,然后試答案試出來的,所以很多differential equation要單純靠記憶,我對背書非常非常不在行,如果有哪一天有數學家發現了可以怎么算,我學了算法也許還能去學一點)!
后來就去研究cpu怎么才能提高效率。
回歸正題,代碼是怎樣運行的呢?
給純來看科普的讀者的廚房比喻,你要組織一個宴會,然后你說了要弄些什么,你就是軟件。然后有個人,專門根據你你要求,弄成一份菜單,他就是編譯器。然后把這份菜單給廚房,基本上就是:讀菜單拿食材(instruction fetch),切菜(decode),煮菜(execute),上盤出餐(load store and writeback)。然后前面就一讀菜單,后面就一直工作。
給有一點編程知識的讀者:舉個例子,c:
int func(){
...
int a = 1;
a = a +3;
...
}
這段編譯后,大概就是
sub sp, 4 ; stack point increase變量都在函數棧里留一個位置,因為是int所以留4
mov ebx, 1 ; ebx用來存1,就是你定義 a了,a=1
; mov [sp], ebx ;有時候如果需要,就把ebx是值存到剛剛預留的棧里
; mov ebx, [sp] ;需要用的時候再讀出來,不是必然會發生的,但是這兩步可能發生
add ebx, 3 ; ebx = ebx+3, 當然你可以用其他register
...
你不需要讀得懂,因為我手打的,分分鐘錯給你看。
然后這些東西,就會跑到內存,沒錯,你運行軟件的時候,代碼是先去到內存,如果想了解他們怎么從硬盤跑到內存,這是另外一個主題,我這里先不討論,然后緩存又會把這些代碼讀取,緩存就已經在SoC里面的,cpu在從緩存里面讀取,別問為什么這么麻煩讀這么多次,都是為了省錢和稍微加快速度。
由于是舉例子,我就隨便亂說個decode。這個是Intel公布的manual,問我為什么不用本家農企是吧?因為我拿到農企那個不是對外公布的,公布版我還要上網找。
Opcode Instruction Op/ En 64-bit Mode Compat/ Leg Mode D
05 id ADD EAX, imm32 I Valid Valid Add imm32 to EAX.
在cacheline里面看起來大概是這樣的 0x05__02___00000003
里面的_代表其他位不詳細講的,大概這個翻譯成機械碼就是 要做05(ADD加法)在02(ebx實際上我印象中ebx是02,然而eax是00,不是01,這些編碼亂七八糟的,Intel決定的,別問我)后面的00000003就是32為imm32,就是 add, ebx 03
cpu讀了這條cacheline叫instruction fetch,然后下一步就是把它decode,解釋成add, ebx 03,再下一步就是把運行(execute,沒錯,這么麻煩之后,最后終于要算了),把算得的結果存到ebx上,然后再看看需不需要存回去cacheline或者內存里面(load/store writeback)。這個就是cpu的基本運行原理。
CPU pipeline
有時候會聽到cpu流水線,如果按照上面的做法,沒一個指令都要通過這幾部來預算,那么只有一部分電子器件在用的時候,其他部分都在發呆浪費電。就像是,廚房里面,從取菜到上盤全部都一個人做,肯定要累死那個人,但是你炒菜的時候,是不是想,如果有人已經幫你切好菜,我就一直炒菜好了,這樣我們廚房工作效率就高了,cpu也是這樣。
上圖是一個經典的cpu運行流水線。
換成廚房理論,就是,一個人專門去食材,一個人專門切菜,一個人專門炒菜,一個人專門上盤,一個人專門給客人下單上菜,是不是現代化很多呢!
然而這樣不能滿足我們cpu的工程師,我們還有branch prediction,什么叫branch prediction呢?程序黎里面最耗時間的一個就是branch,就像c里面的if,你得到答案之前不知道是繼續往下走還是進去if里面的括號。就像下單的小哥,那些猶豫不決而改菜單的人最討厭了。
于是cpu里面有了這個東西,他是怎么用的呢。下單的小哥也不是笨蛋,顧客a來了100多次了,有80次都改單把豬肉改成雞肉,那么他下單時候,小哥就先說了,改雞肉,如果顧客a覺得還是豬肉吧,就再抄,如果顧客a真的改單,那么廚房以及開始做了,而且有80%的幾率啊,小哥還是挺聰明的吧。
cpu也大概是這樣,根據每個loop的地址(顧客)來訓練出一個未卜先知的系統。
上圖里面還有OOO(out of order),x86里面,real mode可以用的general register只有8個,eax,ebx,之類的,64位之后增加了8個。流水線工作,如果
mov eax,1;
add eax,1;
sub eax,2;
你們發現問題了沒,eax用了再用,但是流水線做add的時候,eax是1,sub在等add retire之前,是不能做的,那么你就不得不等。
那么流水線的效率就體現不出來了。因為這里有一個write after write 的dependency,就是同一個register,你兩個pipeline stage要用同一個register,而且x86在傳統模式只有8個register,eax,ebx等等,64位模式增加了一些。所以這中情況是非常常見的。為了解決這個問題,就有了out of order execute, in order commit。就是不按順序來運行指令,但是按順序完成指令。
用廚房理論解釋就是,有這么一道菜(或者說兩道菜),雞要先煮了然后炸,你煮熟雞之前不能炸,否則炸了再煮,口感就不同了,顧客肯定罵死你,但是后面又有其他菜在等,鍋你是有的,所以在煮雞的時候,你先做后面的菜,然后雞煮好了,再炸。出餐的時候,你還是先出了這道雞肉再出后的菜,那樣顧客就不會投訴出餐的順序不按菜單了。
大概就說這么一通吧,也不知道有沒有解釋清楚,我中文越來越差了,說話都咬舌頭,而且我說方言版本的粵語比較多,普通話有時候也說不準確了Orz(求別噴,用得少就說不好了)。
里面夾雜了一些英文,因為我看了中文的翻譯,我覺得那樣翻譯不好,也不準確,但是我又不想自己想個新詞來誤導讀者,只好用英文了。如果有讀者對某些題目有特別的興趣,我再想想什么時候有空再寫點什么吧。
-
cpu
+關注
關注
68文章
10898瀏覽量
212534 -
操作系統
+關注
關注
37文章
6870瀏覽量
123554 -
ISA
+關注
關注
0文章
55瀏覽量
43764
原文標題:老奶奶都能看懂的CPU技術科普
文章出處:【微信號:EngicoolArabic,微信公眾號:電子工程技術】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論