什么是專用處理器?
先說(shuō)一般的處理器概念,wiki定義是“ In computing, a processor is an electronic circuit which performs operations on some external data source, usually memory or some other data stream ”。專用處理器就是針對(duì)特定應(yīng)用或者領(lǐng)域的處理器,類似于是我們經(jīng)常說(shuō)的Domain Specific Architecture的概念。
最為通用的處理器當(dāng)然是CPU(比如intel的桌面CPU,ARM的嵌入式CPU),可以運(yùn)行任何程序,處理各種數(shù)據(jù)。但問(wèn)題是CPU對(duì)某些應(yīng)用效率太低(處理能力不夠,無(wú)法實(shí)時(shí)處理,或者是能耗太大)。比如,處理graphic不行,于是出現(xiàn)了GPU;信號(hào)處理不行,于是出現(xiàn)了DSP。GPU可以做圖像處理,也可以做DNN的training和inference,但是在處理某些DNN應(yīng)用的時(shí)候效率不高,于是有了專用針對(duì)這些應(yīng)用處理器,也就是我最近討論的AI/ML/DL處理器。所以說(shuō),專用處理器也是個(gè)相對(duì)概念,相對(duì)CPU而言,別的類型處理器都可以認(rèn)為是專用處理器。而我在本文里主要討論的是相對(duì)GPU/DSP而言更為“ 專用 ”的處理器。
專用處理器的覆蓋范圍也很廣,有的能夠運(yùn)行標(biāo)準(zhǔn)的C程序,比如很多ASIP處理器(Application Specific ISA Processor);有的只有很簡(jiǎn)單的可編程性,比如一些可配置的硬件加速器(Configurable Hardware Accelerators),極端的例子就是“只運(yùn)行一條fft指令的“FFT硬件加速器。當(dāng)然具體的硬件設(shè)計(jì)里可能并沒(méi)有指令的概念,只有配置的概念。我討論的重點(diǎn)是至少具有一定可編程能力,可以(并需要)運(yùn)行程序的專用處理器。
指令集設(shè)計(jì)
這里先簡(jiǎn)單說(shuō)一下指令集的概念。指令集就是一個(gè)處理器的硬件可以支持的基本操作(符號(hào)化的抽象描述)的集合。(wiki:“ An instruction set, with its instruction set architecture (ISA), is the interface between a computer's software and its hardware, and thereby enables the independent development of these two computing realms; it defines the valid instructions that a machine may execute. ”)。借用Patterson老爺子最近講演里了一張圖,ISA就是傳統(tǒng)上軟件和硬件的分界線。
通常,處理器的指令集架構(gòu)(ISA:Instruction Set Architecture)決定了處理器的功能(編程模型)。最著名的x86就是intel CPU的指令集。一個(gè)通用處理器,為了適應(yīng)所有的應(yīng)用,其指令集必須考慮最大的靈活性。這種靈活性主要表現(xiàn)在指令功能是不是完備和粒度是不是足夠細(xì)。
舉個(gè)例子,大家都知道FFT運(yùn)算是由蝶形運(yùn)算組成的;而蝶形運(yùn)算是由復(fù)數(shù)乘法和加法組成;復(fù)數(shù)的乘法和加法又是由普通的乘法和加法組成。如果你設(shè)計(jì)一個(gè)可以處理FFT的處理器,可以有幾種方法設(shè)計(jì)指令集。最簡(jiǎn)單的就是用一個(gè)通用指令集,指令集里有最基本的乘法和加法就沒(méi)問(wèn)題。FFT的處理分解為這些基本運(yùn)算,一步一步完成。這樣,你的處理器具有最高的靈活性,如果這個(gè)處理器不做FFT,還可以做其它的運(yùn)算。還有一種方法,指令集里只設(shè)計(jì)一條指令,fft指令,執(zhí)行這條指令就可以完成所有操作。當(dāng)然,這樣顯然沒(méi)什么靈活性。即使是要做一個(gè)“1+1”的操作,你的處理器也干不了。這個(gè)例子比較極端,實(shí)際設(shè)計(jì)中一般是折中的處理。但是后者就是我想討論的專用處理器的一個(gè)重要特點(diǎn),一條指令完成更多的處理。
由于專用處理器這個(gè)名稱可以用在很多地方,我想再明確一下本文說(shuō)的專用處理器設(shè)計(jì)的范圍:1. 我們主要討論IP級(jí)的設(shè)計(jì),也就是說(shuō)專用處理器設(shè)計(jì)最終作為一個(gè)SoC(System-on-Chip)芯片中的IP出現(xiàn)。它需要和其它模塊合作完成整個(gè)芯片要實(shí)現(xiàn)的功能(下圖為一個(gè)簡(jiǎn)化模型)。2. 我們主要討論的專用處理器是要運(yùn)行程序的,有自己的指令集(可能很簡(jiǎn)單,比如Google第一代TPU,主要指令不超過(guò)10條),需要有存儲(chǔ)程序的空間和讀取指令,執(zhí)行指令的機(jī)制。
專用處理器雖然強(qiáng)調(diào)專用二字,但實(shí)際上還是一個(gè)處理器。因此,設(shè)計(jì)一個(gè)專用處理器,和設(shè)計(jì)通用處理器的內(nèi)容和過(guò)程類似。簡(jiǎn)單來(lái)說(shuō),這一過(guò)程覆蓋指令集(ISA),微結(jié)構(gòu)(硬件)和工具鏈(軟件)的設(shè)計(jì)和實(shí)現(xiàn)。下面先討論一下指令集的問(wèn)題。
對(duì)專用處理器來(lái)說(shuō),指令集的設(shè)計(jì)直接反映了對(duì)應(yīng)用需求的理解。比如,第一篇中介紹的例子,如果我們的專用處理器只是為了加速256點(diǎn)的FFT用的,那么指令集里只有FFT指令就夠用了。考慮到數(shù)據(jù)搬移的需求,再加上幾條數(shù)據(jù)搬移的指令,比如讀取數(shù)據(jù),寫(xiě)回?cái)?shù)據(jù)。于是可以得到一個(gè)有三條指令的指令集(fft,load,store)。這個(gè)處理器執(zhí)行的匯編(Assembly)程序大概就是這樣的。
當(dāng)然,這里做了很多簡(jiǎn)化,但看起來(lái)這個(gè)指令集已經(jīng)可以work了。同時(shí),這也是一個(gè)“高效”的設(shè)計(jì),沒(méi)有多余的東西。如果你要循環(huán)做8次fft,那么可能需要增加一條loop(循環(huán))指令,要不然你就得把上面的代碼copy八次。加了loop指令,匯編代碼可能是下面這樣。
設(shè)計(jì)指令集除了確定每條指令的功能和操作數(shù)(比如上面的例子里的寄存器的名字,循環(huán)次數(shù)等等),還有一個(gè)重要工作就是設(shè)計(jì)指令編碼。像“l(fā)oad”這樣的指令名稱只是個(gè)抽象的描述,而處理器的硬件看到的實(shí)際上是二進(jìn)制的指令編碼。還是上面這個(gè)例子,由于我們的指令集有4條指令,則需要2個(gè)比特來(lái)區(qū)分,比如,00:fft;01:load:10;store;11:loop。再具體看load指令,還需要幾個(gè)bit來(lái)說(shuō)明目標(biāo)寄存器,假設(shè)一共有8個(gè)寄存器(R0-R7),區(qū)分他們又需要3個(gè)bit;另外需要一個(gè)bit來(lái)說(shuō)明數(shù)據(jù)的來(lái)源:是一個(gè)立即數(shù)還是來(lái)自內(nèi)存;如果來(lái)源是內(nèi)存,還需要幾個(gè)bit表示內(nèi)存地址,或者指示存放內(nèi)存地址的寄存器編號(hào),等等。你會(huì)發(fā)現(xiàn),可能對(duì)于一個(gè)load指令,一共需要32個(gè)bit的指令編碼。上面的匯編程序第三行對(duì)應(yīng)的機(jī)器碼可能是這樣的。
最后,把所有的情況列出來(lái),就形成一個(gè)指令和指令編碼的列表。這就是一個(gè)完整的指令集架構(gòu)(ISA)了。實(shí)際上的ISA當(dāng)然比這個(gè)復(fù)雜很多,但不管多復(fù)雜,主要也就是這幾大類功能:第一是執(zhí)行運(yùn)算或處理功能的,比如算數(shù)運(yùn)算;第二類是控制程序流的,比如循環(huán),分支和跳轉(zhuǎn);第三類實(shí)現(xiàn)數(shù)據(jù)搬移的,比如內(nèi)存到寄存器,寄存器之間;最后還有一些輔助功能,比如debug,中斷,cache之類的指令。這里就不展開(kāi)講了,有興趣的同學(xué)可以自己研究一下現(xiàn)在很火的開(kāi)源指令集RISC-V。個(gè)人感覺(jué),仔細(xì)看明白一個(gè)好的指令集的設(shè)計(jì)思想,比看教科書(shū)收獲要多得多。
以上算是指令集的背景知識(shí)吧,回到設(shè)計(jì)專用處理器的問(wèn)題。當(dāng)我們有了一個(gè)應(yīng)用需求,怎么來(lái)設(shè)計(jì)和優(yōu)化一套專用的指令集呢?我想這個(gè)問(wèn)題可能很難有個(gè)統(tǒng)一的答案,這里就說(shuō)說(shuō)我的個(gè)人經(jīng)驗(yàn)吧。
1. 確定評(píng)價(jià)標(biāo)準(zhǔn)
我們?cè)O(shè)計(jì)專用處理器都是有明確目的性的,先把目標(biāo)弄清楚至關(guān)重要。評(píng)價(jià)一般的通用處理器有一些成熟的benchmark。還有一些benchmark更面向?qū)S妙I(lǐng)域,比如多媒體,DSP,或者針對(duì)特殊結(jié)構(gòu)的,比如cache。
那么評(píng)價(jià)專用處理器的標(biāo)準(zhǔn)是什么呢?很簡(jiǎn)單,目標(biāo)應(yīng)用。 所以,最好在開(kāi)始設(shè)計(jì)之前,就把目標(biāo)應(yīng)用定量化。如果目標(biāo)應(yīng)用已經(jīng)有程序代碼,就可以直接用這些程序代碼做benchmark,來(lái)評(píng)價(jià)你的設(shè)計(jì)。如果還沒(méi)有完整的應(yīng)用程序代碼,最好也要把關(guān)鍵算法部分寫(xiě)出來(lái)。當(dāng)然,這一條不只是針對(duì)指令集,而是針對(duì)完整的專用處理器,包括工具鏈的設(shè)計(jì)(后續(xù)再介紹)。對(duì)于專用處理器設(shè)計(jì)來(lái)說(shuō),評(píng)價(jià)標(biāo)準(zhǔn)一般是有限而明確,是正是它能夠在一個(gè)領(lǐng)域做的比通用處理器效率高的最重要因素。
2. 選擇一個(gè)參考指令集作為基礎(chǔ)
從零開(kāi)始做專用處理器相當(dāng)于“重新發(fā)明輪子”,存在很大的風(fēng)險(xiǎn)。那么我們能否把問(wèn)題變成“優(yōu)化輪子設(shè)計(jì)”呢(是不是看起來(lái)要簡(jiǎn)單了很多)?在多數(shù)情況下都是可以,而且有效的。對(duì)于大部分應(yīng)用來(lái)說(shuō),其合理的指令集都需要一些基本的指令,比如基本的算術(shù)指令和跳轉(zhuǎn)控制指令等,這一部分完全可以參考已有的設(shè)計(jì)。這樣可以大大降低設(shè)計(jì)的風(fēng)險(xiǎn)。
比如,我們現(xiàn)在有一個(gè)應(yīng)用,在通用處理以外需要大量的FFT操作。一種方法是自己設(shè)計(jì)一套指令集,即包括通用指令,又包括特殊指令,比如專門(mén)的蝶形運(yùn)算(butterfly)操作。另一種方法是參考一個(gè)成熟的指令集,在它的基礎(chǔ)上做優(yōu)化工作,增加butterfly指令,并減少一些不常用的指令。相比第一種方法,這樣顯然風(fēng)險(xiǎn)要小的多。還有一個(gè)好處,我們 可以重用參考處理器的工具鏈 ,或者只要少量改動(dòng),進(jìn)一步降低的工作量。
結(jié)合第1點(diǎn),一般我們可以先把目標(biāo)應(yīng)用的程序在參考的處理器上跑一下,做一些評(píng)估,找到瓶頸。針對(duì)瓶頸問(wèn)題設(shè)計(jì)或改進(jìn)指令集,以及后面要介紹的微結(jié)構(gòu)和工具鏈。這也說(shuō)明在開(kāi)始的時(shí)候就有一個(gè)明確的評(píng)價(jià)標(biāo)準(zhǔn)的好處。
3. 充分利用工具
實(shí)際上,不管是指令集還是微結(jié)構(gòu),設(shè)計(jì)和優(yōu)化過(guò)程就是一個(gè)在優(yōu)化目標(biāo)指導(dǎo)下的設(shè)計(jì)空間探索問(wèn)題。如果你足夠厲害,你當(dāng)然可以采用“pencil & paper”的方法。但對(duì)于我們大部分設(shè)計(jì)者來(lái)說(shuō),人肉探索這個(gè)設(shè)計(jì)空間幾乎是不可能的。能不能充分利用工具幫忙,往往決定我們是不是能夠盡快得出一個(gè)比較好的設(shè)計(jì)。在第2點(diǎn)里,我們先把應(yīng)用在一個(gè)現(xiàn)有的處理器上跑一下,然后根據(jù)profiling結(jié)果做優(yōu)化設(shè)計(jì),實(shí)際就是借助工具幫助我們分析問(wèn)題。
如果你有足夠的資金,還可以借助一些商用的工具。比如,有的DSP IP支持一些擴(kuò)展和定制的功能和工具,你可以在一個(gè)基礎(chǔ)設(shè)計(jì)上針對(duì)你的應(yīng)用設(shè)計(jì)你自己的專用處理器;還有專門(mén)設(shè)計(jì)ASIP(專用指令處理器)的工具,你甚至可以用一些高層次的語(yǔ)言來(lái)描述處理器,工具自動(dòng)生成工具鏈和硬件設(shè)計(jì)(RTL代碼),并且評(píng)估設(shè)計(jì)的好壞,幫忙進(jìn)行優(yōu)化。當(dāng)然,這些IP或者工具一般價(jià)格昂貴,也有一定的技術(shù)門(mén)檻。以后有機(jī)會(huì)在詳細(xì)介紹吧。
微結(jié)構(gòu)
下面我們來(lái)看看上述指令集的硬件實(shí)現(xiàn),微結(jié)構(gòu)(microarchitecture)。wiki對(duì)微結(jié)構(gòu)的定義如下:
“In electronics engineering and computer engineering, microarchitecture, also called computer organization and sometimes abbreviated as μarch or uarch, is the way a given instruction set architecture (ISA) is implemented in a particular processor. A given ISA may be implemented with different microarchitectures; implementations may vary due to different goals of a given design or due to shifts in technology.”
如果說(shuō)指令集是一個(gè)處理器的功能規(guī)范,那么微結(jié)構(gòu)可以認(rèn)為是實(shí)現(xiàn)ISA的硬件架構(gòu)。對(duì)于不同的優(yōu)化目標(biāo),相同的一個(gè)ISA可能用不同的微結(jié)構(gòu)來(lái)實(shí)現(xiàn)。換句話說(shuō),微結(jié)構(gòu)是最終實(shí)現(xiàn)性能指標(biāo)要求的途徑。當(dāng)然,一個(gè)優(yōu)秀合理的ISA的在設(shè)計(jì)的時(shí)候肯定也考慮了微結(jié)構(gòu)實(shí)現(xiàn)的問(wèn)題。在我們?cè)O(shè)計(jì)一個(gè)專用處理器的時(shí)候,ISA和微結(jié)構(gòu)的設(shè)計(jì)和優(yōu)化往往是一個(gè)交織進(jìn)行的過(guò)程。先設(shè)計(jì)一個(gè)ISA,然后在做微結(jié)構(gòu)實(shí)現(xiàn)的過(guò)程中再修改ISA也是很常見(jiàn)的。
微結(jié)構(gòu)的設(shè)計(jì)和優(yōu)化又是一個(gè)巨大的話題,也涉及很多知識(shí)。我還是先通過(guò)FFT專用處理器的例子來(lái)說(shuō)明一下基本概念。為了實(shí)現(xiàn)上一部分設(shè)計(jì)的ISA,我們可以設(shè)計(jì)這樣一個(gè)處理器微結(jié)構(gòu)。
如果讀者您一看就明白了這個(gè)圖的意思,請(qǐng)?zhí)^(guò)下面這段簡(jiǎn)要說(shuō)明,直接看微結(jié)構(gòu)優(yōu)化的討論。
首先,我們要執(zhí)行的關(guān)鍵指令是fft指令,這里假設(shè)fft指令就是做一次蝶形運(yùn)算(buffterfly)。所以我們要有一個(gè)做蝶形運(yùn)算的硬件單元(圖中的4)。而這個(gè)功能單元FU(Functional Unit)需要輸入和輸出數(shù)據(jù)。數(shù)據(jù)了來(lái)源可能是通用寄存器堆RF(Register File,圖中的3),也可能是memory或者流水線寄存器。同樣,數(shù)據(jù)的輸出也有很多可能。因此,需要一些MUX來(lái)進(jìn)行選擇。簡(jiǎn)單說(shuō),圖中的3和4就構(gòu)成了處理器中的數(shù)據(jù)通道(datapath),也就是處理數(shù)據(jù)的通路。另外,為了把數(shù)據(jù)從數(shù)據(jù)存儲(chǔ)器(data memory)中讀進(jìn)來(lái)進(jìn)行處理(load),或者將處理的結(jié)果再寫(xiě)回到存儲(chǔ)器,還需要一個(gè)“l(fā)oad store單元”(圖中的5)。
但是,數(shù)據(jù)通道要正確運(yùn)行,需要很多控制信息。比如,在寄存器堆中倒底哪個(gè)存放的是輸入數(shù)據(jù);哪個(gè)應(yīng)該存放運(yùn)算結(jié)果?FU的數(shù)據(jù)來(lái)源倒底來(lái)自RF還是memory;結(jié)果要寫(xiě)回哪里?等等。而這些信息實(shí)際上就包含在程序指令里。我們假想?yún)R編程序,每行指令都包含對(duì)datapath的控制信息。因此,在一個(gè)處理器里還需要有一條控制通路(control path),根據(jù)程序指令實(shí)現(xiàn)對(duì)datapath的設(shè)置和控制。
我們先要把指令從程序存儲(chǔ)器(PM:program memory)讀進(jìn)來(lái)。這需要一個(gè)取指令的功能模塊(fetch);取指模塊的功能是向PM發(fā)出地址,執(zhí)行“讀”操作。這個(gè)地址是根據(jù)一個(gè)特殊的寄存器:程序計(jì)數(shù)器(PC:program counter)產(chǎn)生的。PC也可以看作是指向程序存儲(chǔ)空間的一個(gè)指針,它實(shí)際控制著程序執(zhí)行的流程。如果程序按正常順序執(zhí)行,則PC = PC + 1。如果需要改變程序流,比如跳轉(zhuǎn),則需要改變PC的值,指向要跳轉(zhuǎn)的新地址,PC = PC + offset。這樣取指模塊讀出的就是跳轉(zhuǎn)目標(biāo)位置的指令。
上篇文章已經(jīng)介紹了,指令經(jīng)過(guò)編碼以后形成一個(gè)二進(jìn)制的機(jī)器碼。取指模塊讀進(jìn)來(lái)的正是這個(gè)機(jī)器碼。要確定這條指令要執(zhí)行的具體操作,就需要進(jìn)行譯碼(decode)。比如,在咱們的例子中,根據(jù)機(jī)器碼的頭兩個(gè)bit就可以判斷倒底是那一條指令。
分辨出具體是什么指令,就可以執(zhí)行該指令的操作了。通常這個(gè)過(guò)程稱為指令發(fā)射(issue)或者執(zhí)行(execution)。其結(jié)果包括,對(duì)數(shù)據(jù)通路的控制,比如“fft”指令;對(duì)PC的修改,比如指令“l(fā)oop”和對(duì)訪的控制“l(fā)oad和store”指令,等等。
到此為止,我們已經(jīng)有了一個(gè)workable的硬件架構(gòu)了,在這個(gè)硬件上可以運(yùn)行前面說(shuō)的匯編程序并且輸出結(jié)果。但實(shí)際上,這是一個(gè)“極簡(jiǎn)”微結(jié)構(gòu),忽略了很多重要內(nèi)容。為了后面討論的方便,下面介紹幾個(gè)和微結(jié)構(gòu)相關(guān)的名詞。
指令周期(Instruction cycle):
一條指令一般會(huì)經(jīng)歷“取指”,“譯碼”,“發(fā)射/執(zhí)行”和“寫(xiě)回”這些操作。處理器執(zhí)行程序的過(guò)程就是不斷重復(fù)這幾個(gè)操作。
指令流水線(Instruction pipeline):
當(dāng)一條指令,完成了“取指”操作,開(kāi)始進(jìn)行“譯碼”的時(shí)候,取指模塊就可以取下一條指令了,這樣可以讓這些模塊不至于閑著沒(méi)用。wiki對(duì)指令流水線的示例如下(IF:取指;ID:指令譯碼;EX:執(zhí)行;MEM:訪存;WB:寫(xiě)回):
指令并行(Instruction-level parallelism):
同時(shí)執(zhí)行多條指令。比如,一邊從memory讀數(shù)據(jù),一邊進(jìn)行fft處理。我們經(jīng)常聽(tīng)到的超標(biāo)量(Superscalar),超長(zhǎng)指令字(VLIW),亂序執(zhí)行( Out-of-order execution)等等技術(shù)都是發(fā)掘指令級(jí)并行的技術(shù)。
數(shù)據(jù)并行(Data parallelism):
同時(shí)處理多個(gè)數(shù)據(jù)。我們常聽(tīng)到的向量處理器(vector procesor),張量處理器(Tensor processor)多數(shù)都是利用了SIMD(一條指令可以處理多個(gè)數(shù)據(jù),比如一個(gè)向量乘法)技術(shù)。
存儲(chǔ)層次(memory hierarchy):
處理器相關(guān)的存儲(chǔ)實(shí)際是由多種類型的存儲(chǔ)器組成。一般訪問(wèn)速度越快(離datapath的“距離”越近),成本越高;相應(yīng)的容量也越小。按從快到慢的順序,包括芯片內(nèi)的存儲(chǔ)器:寄存器(Register),TCM(Tightly Coupled Memory),L1 cache,L2 cache和芯片外的存儲(chǔ)器,DDR,硬盤(pán)等等。
實(shí)際上,對(duì)處理器微結(jié)構(gòu)的研究到今天為止已經(jīng)非常非常成熟,想有很大的創(chuàng)新幾乎不太可能了。做一個(gè)專用處理器無(wú)非是怎么針對(duì)應(yīng)用的特點(diǎn),利用好這些經(jīng)驗(yàn)的問(wèn)題。當(dāng)然,這也是一種創(chuàng)新。下面談一些做專用處理器的個(gè)人感受吧。
1. 通用處理器的背景知識(shí)
既然專用處理器只是一種特殊的處理器,那么處理器的一般性知識(shí)還是非常重要的。如果你對(duì)處理器設(shè)計(jì)的常用技術(shù)和技巧都非常熟悉,那么你設(shè)計(jì)專用處理器肯定也是游刃有余。比如指令級(jí)并行和數(shù)據(jù)并行是微結(jié)構(gòu)設(shè)計(jì)的兩個(gè)重要方向,你是否能準(zhǔn)確的了解每一種并行技術(shù)的優(yōu)勢(shì),劣勢(shì)和代價(jià)呢?最好你能夠在腦子里就有一個(gè)對(duì)比的表格,隨時(shí)可以拿出來(lái)和目標(biāo)應(yīng)用放在一起做評(píng)估。另外,還是要跟蹤這個(gè)領(lǐng)域的最新進(jìn)展,也許能給你帶來(lái)很大的啟發(fā)。
2. 突破通用處理器的思維
雖然做專用處理器要以處理器的一般知識(shí)為基礎(chǔ)。但也要敢于做出突破。實(shí)際上,我們看到的處理器設(shè)計(jì)經(jīng)典知識(shí)往往針對(duì)通用處理器。畢竟它的應(yīng)用范圍廣,討論的也比較多。而面向某個(gè)領(lǐng)域的專用處理器通常都是by design的優(yōu)化,可能就只有你自己或者很少的人做,討論的也比較少。這種時(shí)候就要相信自己對(duì)應(yīng)用的理解,敢于做出一些“奇怪”的設(shè)計(jì)。當(dāng)然,前提是我們有嚴(yán)謹(jǐn)?shù)亩糠治鲎鲋?。這一點(diǎn)我會(huì)在后續(xù)介紹方法學(xué)和工具鏈的文章里進(jìn)一步說(shuō)明。
3. 發(fā)掘歷史的寶藏
從最近兩年AI硬件熱潮中我們發(fā)現(xiàn),很多在歷史上曇花一現(xiàn)的架構(gòu)重新獲得了成功,或者至少獲得了新的關(guān)注,Google TPU中使用的脈動(dòng)陣列架構(gòu)就是最好的例子。在歷史上有過(guò)體系結(jié)構(gòu)百花齊放的年代,當(dāng)時(shí)很多有趣的設(shè)計(jì)只是由于生不逢時(shí)而被遺忘了。對(duì)于專用處理器來(lái)說(shuō),重點(diǎn)是高效解決特定問(wèn)題,因此歷史上很多當(dāng)時(shí)看起來(lái)”非主流“的設(shè)計(jì)可能反而是最合適的。所以我們不妨經(jīng)常做做“考古”工作,能發(fā)現(xiàn)金礦也說(shuō)不定。
設(shè)計(jì)方法和工具
前面我們分別討論了專用處理器的指令集和微結(jié)構(gòu)的問(wèn)題。其實(shí),在指令集和微結(jié)構(gòu)方面,專用處理器用的技術(shù)基本上都是在通用處理器發(fā)展過(guò)程中探索過(guò)的東西。要說(shuō)專用處理器設(shè)計(jì)最為特殊的地方,我個(gè)人認(rèn)為應(yīng)該是設(shè)計(jì)方法(方法學(xué))和工具。專用處理器設(shè)計(jì)成功與否完全由目標(biāo)應(yīng)用來(lái)檢驗(yàn),而應(yīng)用的多樣性也決定了專用處理器的多樣性。這種多樣性不僅反映在軟硬件設(shè)計(jì)本身,也反映在設(shè)計(jì)方法和工具上。
上面這副圖展示的domain-specific computing的概念既包括了專用處理器(圖中的ASP,Application Specific Processor)設(shè)計(jì)和也包括了相應(yīng)的工具開(kāi)發(fā)。下面我們就結(jié)合這副圖,把DNN作為一個(gè)domain,討論一下專用處理器的設(shè)計(jì)方法和各種工具。
Domain Modeling
首先是對(duì)特定領(lǐng)域(domain,比我們說(shuō)的目標(biāo)應(yīng)用的概念要更廣泛一下)進(jìn)行建模,把需求模型化和量化,作為后續(xù)工作的評(píng)價(jià)標(biāo)準(zhǔn)。建??赡軙?huì)使用特殊的語(yǔ)言擴(kuò)展或者數(shù)據(jù)流圖的形式,比如在DNN領(lǐng)域經(jīng)常使用的Tensorflow就是典型的例子。
Domain Model是后續(xù)開(kāi)發(fā)的基礎(chǔ),據(jù)此可以得到兩個(gè)重要的中間描述:一個(gè)是用于硬件架構(gòu)設(shè)計(jì)的Domain Characteristics;另一個(gè)是用于生成C/C++應(yīng)用代碼(當(dāng)然也可能是其它語(yǔ)言)的Application Model。這里的具體名稱并不太重要,重要的是一個(gè)domain model需要經(jīng)過(guò)處理,分離出指導(dǎo)硬件設(shè)計(jì)和生成應(yīng)用軟件代碼的兩部分信息。
HW Architecture design和Architecture Model
硬件架構(gòu)設(shè)計(jì)的主要工作是設(shè)計(jì)專用的計(jì)算引擎(Customized Computing Engine)和互連機(jī)制(Customized Interconnection)。比如在CNN加速器中比較常見(jiàn)的由PE(Processing Engine)組成的2D mesh網(wǎng)絡(luò),PE就是專用的計(jì)算引擎,2D網(wǎng)絡(luò)就是適應(yīng)CNN 2D卷積特征的互連機(jī)制。
硬件架構(gòu)設(shè)計(jì)還要輸出一個(gè)架構(gòu)模型。而這個(gè)硬件架構(gòu)模型也是整個(gè)設(shè)計(jì)方法中重要的一環(huán)。一方面,這個(gè)架構(gòu)模型可以生成虛擬原型系統(tǒng)(Virtual Prototyping);另一方面,它也是程序代碼映射工具(Source-to-source mapper)的輸入,而代碼映射功能用于將一些特殊的模型轉(zhuǎn)換為C/C++這類傳統(tǒng)的編程語(yǔ)言(這類語(yǔ)言有很好的工具進(jìn)行處理),同時(shí)輸出Analysis Annotations,用于指導(dǎo)硬件設(shè)計(jì)和軟件工具鏈的前端設(shè)計(jì)。
虛擬原型(Virtual Prototyping)
我們通常說(shuō)的Prototyping一般指基于FPGA或者測(cè)試芯片(testchip)系統(tǒng)原型,即用于驗(yàn)證硬件設(shè)計(jì),又可以debug固件,操作系統(tǒng)和應(yīng)用程序。但是開(kāi)發(fā)硬件原型系統(tǒng)本身也是一項(xiàng)費(fèi)時(shí)的工作,并且要等等所有硬件設(shè)計(jì)完成了才能實(shí)現(xiàn)。虛擬原型則是個(gè)純軟件的仿真器。最常見(jiàn)的方式是使用SystemC這樣語(yǔ)言(抽象層次更高)來(lái)對(duì)硬件進(jìn)行建模,而不是直接使用RTL級(jí)的硬件模型。建模的抽象層次提高雖然會(huì)損失一些細(xì)節(jié),但好處是開(kāi)發(fā)便捷(C++編程),仿真速度快。和硬件的原型系統(tǒng)相比,虛擬原型可以在項(xiàng)目開(kāi)始階段就開(kāi)發(fā)完成,提供給軟件開(kāi)發(fā)人員,而不需要等到硬件準(zhǔn)備好。最后,虛擬原型是純軟件仿真,很容易debug,也很容易部署。虛擬原型是個(gè)有趣的話題,以后有機(jī)會(huì)可以專門(mén)講一下。
計(jì)算引擎硬件實(shí)現(xiàn)
這里把計(jì)算引擎分為三種:專用處理器(ASP),硬件加速器(HW Accelerators)和可編程陣列(Programing fabric)。前兩種我們都介紹過(guò),第三種的硬件結(jié)果類似于FPGA,差別是這里的邏輯電路陣列也是根據(jù)應(yīng)用定制的。實(shí)現(xiàn)這三類計(jì)算引擎可以靠工程師完成,也可以借助專門(mén)的工具,比如,High-level Synthesizer(高層次綜合工具,也有叫行為級(jí)綜合的)可以把C,systemC甚至Matlab代碼(當(dāng)然有一定的約束)自動(dòng)綜合成硬件設(shè)計(jì)(RTL代碼)。也有一些工具可以根據(jù)特殊的處理器描述語(yǔ)言,如Synopsys的LISA,NML和RISC-V處理器用的Bluespec等,自動(dòng)生成RTL代碼。
這里插一句,自動(dòng)生成RTL代碼看起來(lái)高大上,實(shí)際也沒(méi)那么難。記得10年前在SiliconHive(也是一個(gè)做專用處理器和工具的公司,后來(lái)被Intel收購(gòu)了)實(shí)習(xí)做NoC的時(shí)候,RTL代碼就是從XML描述里自動(dòng)生成的。其實(shí)就是大家平時(shí)形成的好習(xí)慣:RTL代碼盡量用腳本生成,積累起來(lái)也就成了自己的自動(dòng)化工具。
這之后的工作主要就是將計(jì)算引擎和互連機(jī)制集成在一起,并且實(shí)現(xiàn)硬件的原型系統(tǒng)?;ミB機(jī)制的設(shè)計(jì)也有很多內(nèi)容,這里就暫不深入了。
軟件開(kāi)發(fā)工具鏈
圖的右半部分就是軟件開(kāi)發(fā)的工具鏈,這個(gè)和我們傳統(tǒng)上說(shuō)的工具鏈基本是類似的,即從C/C++的源代碼,經(jīng)過(guò)一系列的工具,生成運(yùn)行在最終硬件上的機(jī)器代碼(可以有很多形式)。工具鏈主要包括,前端(front end)后端(back end)和runtime。這里和通用CPU的工具鏈的主要差別在于back end和runtime,因?yàn)檫@兩部分和硬件架構(gòu)(指令集和微結(jié)構(gòu))關(guān)系密切。對(duì)應(yīng)專用處理器的硬件,主要體現(xiàn)在customized和adaptive這種特征。不過(guò)這里還有一些輔助性的工具,比較典型的比如debuger,就不細(xì)說(shuō)了。
小結(jié)一下:
1.專用處理器雖然特殊,但設(shè)計(jì)方法和工具是有普遍性的,這也是研究方法學(xué)的價(jià)值所在。2. 設(shè)計(jì)方法往大說(shuō)是方法學(xué),但在實(shí)際的工程中體現(xiàn)為任務(wù),流程和工具,設(shè)計(jì)專用處理器的過(guò)程也是優(yōu)化方法學(xué)的過(guò)程。3. 專用處理器設(shè)計(jì)面向應(yīng)用,往往有比較高的Time to Market要求,因此從架構(gòu)探索到RTL生成到原型驗(yàn)證,都要盡量利用自動(dòng)化工具提高設(shè)計(jì)的效率,自己設(shè)計(jì)小工具并且不斷積累是很好的實(shí)踐;4. 采用專用處理器的系統(tǒng)往往是軟硬件緊密協(xié)同的系統(tǒng),設(shè)計(jì)方法上最重要的理念是軟硬件的聯(lián)合優(yōu)化:在設(shè)計(jì)硬件的時(shí)候充分利用對(duì)應(yīng)用軟件的分析;而在設(shè)計(jì)軟件工具鏈的時(shí)候也要充分結(jié)合硬件架構(gòu)的特點(diǎn);Architecture Model和Analysis Annotations就是軟硬件設(shè)計(jì)和工具間的橋梁。
“自己動(dòng)手”設(shè)計(jì)專用處理器
最后實(shí)戰(zhàn)一下專用處理器的設(shè)計(jì)項(xiàng)目吧。我們先從結(jié)果說(shuō)起,也就是這項(xiàng)任務(wù)的最終交付物。這里不妨參考ARM處理器核的deliverables。當(dāng)然,如果只是一個(gè)自己用的專用處理器,不一定要有這么完整的交付物。
硬件 :主要是處理器相關(guān)的RTL代碼,驗(yàn)證環(huán)境,EDA工具的腳本,文檔等等。
工具軟件 :主要包括編譯工具(compiler),調(diào)試工具(debugger),仿真工具(simulator)和性能分析工具(profiler)。下圖是ARM的編譯工具的例子,主要包括armclang(C編譯器),armasm(匯編器),armlink(鏈接器)和fromelf(image工具)。
source: arm.com
仿真工具一般至少包括一個(gè)指令仿真器 instruction set simulator (ISS)。
模型 :此外,現(xiàn)在一般的處理器IP還會(huì)提供一些處理器的模型來(lái)支持系統(tǒng)級(jí)設(shè)計(jì),比如用于前面介紹的虛擬原型的處理器模型(類似于ARM的Fast Model)。專用的處理器模型是虛擬平臺(tái)的重要組成部分,和總線模型以及其它IP模型一起模擬系統(tǒng)的功能。
看到這一大堆工作,如果你沒(méi)有膽怯,而是覺(jué)得很有意思。那么我也很愿意給你點(diǎn)幫助,看看是不是可以把你的想法變成現(xiàn)實(shí)。其實(shí)方法也很簡(jiǎn)單 -- 自己做不了就“找別人幫忙唄”。具體來(lái)說(shuō),根據(jù)你的預(yù)算情況,可以分為“ 窮 ”和“ 富 ”兩種玩法。
我先說(shuō)說(shuō)有錢(qián)的玩法吧。其實(shí),不止你一個(gè)人想做專用處理器,很多大公司也有這樣的需求。所以,就有人為這種需求專門(mén)提供了解決方案,比如Synopsys的ASIP-designer工具就是為了滿足定制處理器的需求而設(shè)計(jì)的。ASIP designer支持從零開(kāi)始設(shè)計(jì)和實(shí)現(xiàn)一個(gè)專用處理器。你可以非常自由的設(shè)計(jì)指令集和微結(jié)構(gòu),覆蓋從Extensible processor,到Application-specific uP/DSP,到Programmable datapath這樣一個(gè)更大的架構(gòu)空間,如下圖所示。這里也可以看出,這個(gè)工具的目標(biāo)并不是設(shè)計(jì)通用處理器。
source:synopsys.com
下圖是該工具完整的方法學(xué)。
source: synopsys.com
它的輸入就是兩個(gè),算法(C/C++代碼)和處理器模型(Processor Model),輸出則是一個(gè)處理器相關(guān)的所有設(shè)計(jì)和工具鏈。從輸入到輸出的過(guò)程同樣是自動(dòng)化完成的。當(dāng)然,這個(gè)過(guò)程并不像看起來(lái)那么簡(jiǎn)單,處理器建模的門(mén)檻不低。而且,工具賦予你的靈活性越高,掌握這種工具的門(mén)檻也越高。ASIP designer的處理器建模需要使用一種專門(mén)的語(yǔ)言,即nML,對(duì)處理器的指令集和架構(gòu)進(jìn)行高層次建模;此外還需要很多和編譯器相關(guān)的設(shè)計(jì)。所以,即使你能買(mǎi)得起,要玩好這套工具,還得具備兩個(gè)條件:第一,是你必須熟悉處理器架構(gòu)和編譯方面知識(shí);第二,是要學(xué)習(xí)這套建模語(yǔ)言和工具。
總的來(lái)說(shuō),如果你有專用處理器設(shè)計(jì)的需求,足夠的資金和學(xué)習(xí)的耐心,可以考慮引入這類輔助設(shè)計(jì)工具。在經(jīng)歷過(guò)一定的學(xué)習(xí)周期后,你不僅可以完成一個(gè)設(shè)計(jì),還能獲得快速、高效設(shè)計(jì)處理器的能力。
下面再看看“ 窮玩法 ”。如果你沒(méi)有足夠的資金來(lái)購(gòu)買(mǎi)上述工具,或者是你的目標(biāo)收益還不值得做出這樣的投資。這種情況下,我建議你從開(kāi)源免費(fèi)的處理器(或者指令集)開(kāi)始做你自己的專用處理器。其實(shí)這也算是廢話吧。
假設(shè)你想在RSIC-V的基礎(chǔ)上做定制處理器吧。RSIC-V是現(xiàn)在一個(gè)相對(duì)成熟的開(kāi)源處理器指令集,也有開(kāi)源的處理器實(shí)現(xiàn)和非常活躍的社區(qū)。相信大家都聽(tīng)說(shuō)過(guò),就不科普了。這里得說(shuō)明一下,我并沒(méi)有對(duì)RISC-V進(jìn)行過(guò)深入的研究和嘗試,以下的說(shuō)法基本上是紙上談兵,不對(duì)的地方請(qǐng)大家批評(píng)指正。
首先,你要好好學(xué)習(xí)一下RISC-V指令集手冊(cè)中的“Chapter 10 Extending RISC-V”,這里明確介紹了給RISC-V指令集擴(kuò)展指令的規(guī)則。包括標(biāo)準(zhǔn)的擴(kuò)展和非標(biāo)準(zhǔn)擴(kuò)展兩個(gè)方面。
第二,在現(xiàn)有的RISC-V的硬件實(shí)現(xiàn)基礎(chǔ)上,增加新指令對(duì)應(yīng)的硬件??赡苄枰黾訉S玫募拇嫫?,運(yùn)算單元,pipeline寄存器,控制信號(hào)等等。或者,你可以按照新的指令集(假設(shè)叫“RISC-V++ ISA”)自己做完整的硬件實(shí)現(xiàn)。其實(shí)我覺(jué)得第二種方法還更靠譜一點(diǎn)。很多時(shí)候,修改別人的東西,要比自己做困難的多。
第三,在RISC-V原有的工具鏈(比如GNU或者LLVM的編譯器)基礎(chǔ)上做出修改,支持新的指令。相對(duì)來(lái)說(shuō),這項(xiàng)工作是有比較完善的規(guī)則的,只要按照編譯工具的規(guī)則就可以把新增的指令加進(jìn)去。當(dāng)然,如果你增加的指令比較特殊,比如是向量操作,那么工具鏈的設(shè)計(jì)會(huì)困難很多。這種情況下的一個(gè)選擇是在高級(jí)程序語(yǔ)言的編譯器中不增加對(duì)新指令的支持,這些新的指令以匯編或者intrinsic的方法實(shí)現(xiàn)。
最后,這套方法是不是也能支持在前面提到的快速design space exploration呢?基本的思路也是差不多的。你可以先用基本指令集來(lái)仿真你的算法;根據(jù)profiling的結(jié)果(比如性能指標(biāo),指令效率,code size等)考慮對(duì)指令集進(jìn)行的修改;然后更新相應(yīng)的微架構(gòu)設(shè)計(jì),硬件實(shí)現(xiàn)和工具鏈,再編譯和測(cè)試你的算法,并不斷迭代。如果這個(gè)過(guò)程沒(méi)有自動(dòng)化工具的幫忙,可能需要比較長(zhǎng)的時(shí)間才能完成,特別是需要對(duì)功耗面積進(jìn)行詳細(xì)優(yōu)化的情況。
這種方法看起來(lái)行的通,不過(guò)中間的坑可能非常多,要求你對(duì)基礎(chǔ)處理器(比如RISC-V)非常熟悉。適合那些已經(jīng)完整的做過(guò)RISC-V實(shí)現(xiàn)的玩家嘗試。否則,也許有的坑你根本過(guò)不去。
設(shè)計(jì)專用處理器常見(jiàn)的”坑“
做專用處理器是個(gè)復(fù)雜工程,坑很多,以下僅舉幾例。
我們并不真的了解目標(biāo)應(yīng)用
在我們做一個(gè)面向特定應(yīng)用的專用處理器的時(shí)候,也許沒(méi)有想象中那么了解這個(gè)應(yīng)用。我傾向于用這樣問(wèn)題來(lái)判斷:“1.你是否已經(jīng)有了全部目標(biāo)應(yīng)用或者算法的軟件(程序)?2. 你是否有定量的約束條件?”。如果有,那么你就可以保證對(duì)你的設(shè)計(jì)進(jìn)行客觀和定量的評(píng)價(jià)(驗(yàn)證)。如果在對(duì)設(shè)計(jì)進(jìn)行評(píng)估的時(shí)候,能夠覆蓋目標(biāo)應(yīng)用的軟件程序還不到80%,或者具體的約束條件還不明確,那么就有很大風(fēng)險(xiǎn)。一種可能是,你為不確定性做出一些over design;另一種可能是你的優(yōu)化目標(biāo)和實(shí)際情況并不相符。不管是那一種情況,實(shí)際上都沒(méi)有能夠很好的發(fā)揮專用處理器的優(yōu)勢(shì)。
不知道什么不應(yīng)該做
如果我們不具備自己做專用處理器的能力,往往覺(jué)得它很神秘,會(huì)夸大設(shè)計(jì)的難度和風(fēng)險(xiǎn)。而當(dāng)我們具備了這種能力,一個(gè)可能的傾向是夸大專用處理器的優(yōu)勢(shì),什么地方都想用專用處理器來(lái)搞定。實(shí)際上,掌握了設(shè)計(jì)專用處理器的能力,相當(dāng)于一個(gè)團(tuán)隊(duì)有了一件強(qiáng)有力的武器。至于是否使用和怎樣使用則是一種更強(qiáng)的能力。一個(gè)好的SoC架構(gòu),往往是各種類型的處理器和硬件加速器配合工作的。能夠得到這樣的架構(gòu),或者是通過(guò)了多次迭代和優(yōu)化,或者是以定量分析和仿真為基礎(chǔ)(再次強(qiáng)調(diào)這一點(diǎn))。
忽視工具鏈的開(kāi)發(fā)
設(shè)計(jì)一個(gè)專用處理器,要經(jīng)歷需求分析,架構(gòu)設(shè)計(jì),硬件實(shí)現(xiàn)和工具鏈開(kāi)發(fā)等多項(xiàng)工作。一個(gè)比較常見(jiàn)的問(wèn)題是忽視工具鏈的開(kāi)發(fā)。但正如我在對(duì)方法和工具的討論中指出的,工具鏈(包括處理器開(kāi)發(fā)工具和應(yīng)用開(kāi)發(fā)工具)對(duì)于專用處理器開(kāi)發(fā)和使用是至關(guān)重要的。即使你的架構(gòu)設(shè)計(jì)和硬件實(shí)現(xiàn)做的再好,如果沒(méi)有一個(gè)完善的工具鏈,這些硬件就沒(méi)法發(fā)揮最大的效能。從另一個(gè)角度來(lái)說(shuō),如果沒(méi)有好的開(kāi)發(fā)工具,架構(gòu)設(shè)計(jì)和硬件實(shí)現(xiàn)也很難做好。個(gè)人認(rèn)為,比較好的實(shí)踐是在項(xiàng)目開(kāi)始的時(shí)候就能夠?qū)ぞ哝溤O(shè)計(jì)做出規(guī)劃并配置專職的人員。
評(píng)論