Cuda技術(shù)革命一瞥
當(dāng)前在老百姓眼中有關(guān)計(jì)算機(jī)技術(shù)的最時(shí)髦的詞匯莫過于“多核”了。從前年起,“多核”這個(gè)東西就走進(jìn)了家用的行列,現(xiàn)在購(gòu)置的計(jì)算機(jī)基本上都是雙核心或者是四核心的。由于“硅芯片主頻的物理極限已經(jīng)達(dá)到,CPU將來的發(fā)展即將走向多核方向”,得到的結(jié)果就是AMD和Intel兩家公司的競(jìng)爭(zhēng)進(jìn)入了進(jìn)一步的白熱化階段。
其實(shí)一臺(tái)計(jì)算機(jī)多個(gè)計(jì)算單元的現(xiàn)象很早就出現(xiàn)了。古代有所謂的“解霸卡”,這是一個(gè)專門為視頻解壓處理而設(shè)計(jì)的處理器,原理基本就是一個(gè)為浮點(diǎn)優(yōu)化的CPU。把視頻解壓的工作分給解霸卡,而CPU則留下進(jìn)行更重要的工作。之后Intel推出了MMX指令集,這種卡旋即消失。后來著名的就是Voodoo卡(以及同時(shí)代的各類3D加速卡),這是現(xiàn)代顯卡的雛形。他把浮點(diǎn)計(jì)算分離出來,并且直接加入了貼圖和燈光的特性,使得3D游戲開始普及。伴隨著DirectX技術(shù)的成熟,就產(chǎn)生了現(xiàn)代顯卡?,F(xiàn)代顯卡指的是支持一定的渲染標(biāo)準(zhǔn)的顯卡,如OpenGL標(biāo)準(zhǔn)、DirectX標(biāo)準(zhǔn)等。通過這種設(shè)計(jì),程序員可以方便的通過OpenGL和DirectX接口來編制程序,而不需要考慮具體的硬件類型。這是一個(gè)跨時(shí)代的突破。
在普通的情況下用顯卡進(jìn)行渲染,速度要比用普通的CPU計(jì)算快上幾千倍,而且圖像大?。ㄏ袼?cái)?shù))越大,加速的比例就越大。這是顯卡的自身特性造成的。顯卡當(dāng)中,相當(dāng)于封裝了成百上千個(gè)“核心”,所有的“核心”可以一起處理。由于GPU的計(jì)算是一種特殊的計(jì)算任務(wù),即所計(jì)算的每一個(gè)像素之間不需要(或者用方法使它不需要)考慮先后順序,那么如果有了上百萬個(gè)線程,就可以讓所有的像素同時(shí)渲染,這樣所有的像素就可以在一個(gè)像素的時(shí)間內(nèi)計(jì)算完成。而實(shí)際上在CPU上的運(yùn)算通常是做了一件才能再做一件,這樣就算有一萬個(gè)核心,在前一個(gè)結(jié)果計(jì)算出來之前,其他的線程只能傻傻等待,這就相當(dāng)于一個(gè)核心了,因此CPU多核心的發(fā)展要比GPU慢得多。由于兩者計(jì)算的目的不同,造成他們的構(gòu)架不同。因此顯卡與CPU的計(jì)算任務(wù)通常是分離的。
實(shí)際上,假如你知道你現(xiàn)在的將要做的計(jì)算是可以高度并行的密集型計(jì)算,那么就應(yīng)該使用GPU來進(jìn)行運(yùn)算。然而一般的顯卡卻沒有這樣的功能,它通常只能處理矩陣、貼圖、采樣等等的已經(jīng)有實(shí)際圖形學(xué)意義的問題,而對(duì)其他的運(yùn)算,只能轉(zhuǎn)換成圖形運(yùn)算才能進(jìn)行。利用GPU進(jìn)行通用目的計(jì)算(General Purpose Computing)的想法很早就有了,成熟的產(chǎn)品有GPGPU語言等。我曾經(jīng)歷盡千辛萬苦編寫了一份在顯卡上進(jìn)行FFT計(jì)算的程序,其代碼量之龐大簡(jiǎn)直是駭人聽聞。普通的FFT在150行以內(nèi)就可以完成,而GPU的FFT計(jì)算則需要至少千行(利用GPGPU語言的話代碼量會(huì)少很多,但是相對(duì)于FFT程序,這個(gè)語言產(chǎn)品本身的空間就不小)。之所以有如此之多的代碼量,是因?yàn)樾枰獙⒏鞣N數(shù)據(jù)通過一個(gè)圖形接口(一般是擴(kuò)展的OpenGL)發(fā)送到GPU,計(jì)算之后,再通過這個(gè)圖形接口接收結(jié)果。
另外,程序員從娘胎里帶出來的“一根筋”(單線程,算完一個(gè)再用結(jié)果來算另一個(gè))的思維習(xí)慣是非常不容易改變的。除非是像渲染 這種明顯就應(yīng)該是并行運(yùn)行的東西,其他的東西找出成熟的并行算法非常困難。這就意味著,多核的潛力還必須得到進(jìn)一步的開發(fā)。當(dāng)然有一個(gè)簡(jiǎn)單的方法就是運(yùn)行很多的進(jìn)程,可以以此把CPU塞滿。
原理
nVidia公司一直以來是顯卡界的兩位登峰造極者(nVidia和ATI,后者前些日子與AMD公司合并為AMD&ATI公司) 之中更時(shí)尚的一位。2006年11月8日,nVidia拋出了他們的通用目的GPU計(jì)算的方案CUDA——Compute Unified Device Architecture 即計(jì)算統(tǒng)一的設(shè)備架構(gòu)。這是業(yè)界第一個(gè)可以用C語言進(jìn)行編程的通用目GPU計(jì)算解決方案。實(shí)際上走在了時(shí)間的前頭。
CUDA的原理基本如下:
把 大量的線程(這個(gè)概念與一般的不同,他是更輕量級(jí)的,更快速的)分布在一個(gè)個(gè)的“塊”中。每個(gè)塊共享一段指令和數(shù)據(jù),而塊中的每一個(gè)線程只能訪問到本塊的 數(shù)據(jù)以及外層的共享數(shù)據(jù),訪問不到塊之間的數(shù)據(jù)。外部的驅(qū)動(dòng)程序負(fù)責(zé)把所有的數(shù)據(jù)和指令拷貝到塊中,然后所有的線程開始同時(shí)運(yùn)行。當(dāng)最后一個(gè)線程結(jié)束后運(yùn) 行結(jié)束。 #p#page_title#e#
這樣,指令也相同,數(shù)據(jù)也相同,因此既不會(huì)有換頁問題,也沒有緩存刷新問題(考慮到實(shí)際上GPU是不具備與內(nèi)存速度不同的緩存的,這個(gè)速度的提升是靠多點(diǎn)同時(shí)訪問和顯卡版內(nèi)的超大帶寬得到的——總之就是比那么多個(gè)CPU要快啦!囧)。僅僅這樣,我們就可以得到前所未有的強(qiáng)大速度提升,這靠的是無以倫比的超大線程數(shù)!
在編程方面,如果我們想向一個(gè)塊中寫入指令,只需要像C/C++一樣編寫一個(gè)函數(shù),然后用CUDA的簡(jiǎn)寫方法進(jìn)行調(diào)用(可以自由設(shè)置塊數(shù)和線程數(shù))。之后CUDA編譯器nvcc自動(dòng)將代碼編譯成CPU代碼和GPU代碼,并讓GPU代碼可以自動(dòng)的發(fā)送到適當(dāng)?shù)目熘?。期間的一切硬件問題程序員都不需要管,結(jié)果就是寫一個(gè)CUDA程序和寫一個(gè)普通的C程序一樣方便。
我現(xiàn)在的顯卡的參數(shù)是這樣的(不是什么高端的顯卡,每個(gè)人的顯卡都有類似的能力):14個(gè)多核處理器,每個(gè)多核理器112個(gè)核心,每個(gè)核心65536*65536*1個(gè)格點(diǎn)(這個(gè)不能達(dá)到最大值。實(shí)際使用中取決于顯卡的當(dāng)前狀態(tài)),每個(gè)格點(diǎn)有512*512*64塊,每塊同時(shí)可以運(yùn)行512個(gè)線程(同時(shí)每塊具有8k個(gè)寄存器)??梢源致杂?jì)算一下,就算我們只用到了一個(gè)格點(diǎn),我們就可以得到85億個(gè)線程。這就是說只要我們的顯存(才十億字節(jié))足夠,那么我們就可以想開多少個(gè)線程就開多少個(gè)線程。
根據(jù)官方發(fā)布的資料,如果是更高端的Tesla卡的話,可以每秒進(jìn)行500G次浮點(diǎn)運(yùn)算。CPU浮點(diǎn)運(yùn)算平均大約消耗400周期的話,那么CPU每秒可以進(jìn)行2*3G/400=0.15G次浮點(diǎn)運(yùn)算。相比之下大約能快3000倍左右。但是在這種構(gòu)架只下,最花費(fèi)時(shí)間的操作不再是運(yùn)算,而是把指令和數(shù)據(jù)從內(nèi)存中拷貝到顯存中的過程?,F(xiàn)在的GPU(PCI-E)帶寬在4G/s左右,這就是我們每毫秒可以把4百萬字節(jié)數(shù)據(jù)從內(nèi)存調(diào)入到顯卡中,這對(duì)于大部分的應(yīng)用而言可能足夠了,但是如果需要更高端的計(jì)算性能,恐怕只有等待顯卡的插槽更新?lián)Q代了。
應(yīng)用
我有幸參加了CUDA技術(shù)的創(chuàng)始人之一David Kirk博士在清華進(jìn)行的講座。講座中提到了CUDA從開始到現(xiàn)在不足兩年的時(shí)間里的大量應(yīng)用。實(shí)際上有些是令人比較失望的——在一般的狀況下,CUDA的運(yùn)行速度只達(dá)到了CPU的一百倍到一千倍左右,并沒有達(dá)到那么夸張的地步——不過這依然足夠改變?nèi)藗兊墓ぷ鞣绞搅恕?/span>
- 神經(jīng)網(wǎng)絡(luò)模擬。有一個(gè)人建立了一個(gè)巨大的神經(jīng)網(wǎng)絡(luò),用來模擬真實(shí)生物的神經(jīng)活動(dòng)。眾所周知,每個(gè)神經(jīng)細(xì)胞都可以當(dāng)作是并行運(yùn)行的,因此這個(gè)模型非常適用于CUDA。
- 股票分析軟件。它是以復(fù)雜計(jì)算為基礎(chǔ),進(jìn)行整個(gè)美國(guó)股市的實(shí)時(shí)分析的一個(gè)軟件。由于股票之間的情況異常復(fù)雜,造成經(jīng)濟(jì)學(xué)上的公式無法準(zhǔn)確預(yù)測(cè)時(shí)間稍微一點(diǎn)的大盤情況。然而,有了CUDA,我們就可以在幾百毫秒之內(nèi)計(jì)算出當(dāng)前的全美的大盤走勢(shì),這通常將花費(fèi)數(shù)分鐘時(shí)間,等我們得到結(jié)果之后,它已經(jīng)沒用了。CUDA讓股票分析軟件從不可能成為了可能。
- 分子流體模擬。這是中科院物理所的一位老師做的。他就是把分子的范德化力(其模型相對(duì)復(fù)雜)考慮進(jìn)去。他制作了一個(gè)包含幾億個(gè)分子水滴,然后進(jìn)行 模擬。由于每個(gè)水滴之間的范德華力只在周圍的范圍內(nèi)有效,因此可以把每個(gè)分子的受力狀況看做是不相干的或弱相干的。這也很適于CUDA。
- 地震研究與模擬。地震研究方面的一個(gè)重要問題就是如何快速的處理地震數(shù)據(jù)。這讓我想起了當(dāng)時(shí)MRI剛被發(fā)明的時(shí)候,雖然有了實(shí)驗(yàn)數(shù)據(jù),但是算不出結(jié)果來。動(dòng)用了當(dāng)時(shí)最先進(jìn)的軍用超級(jí)計(jì)算機(jī)才得到一張圖像?,F(xiàn)在的醫(yī)學(xué)器械里,MRI是太常見的東西了。這說明將來我們有可能處理更多的地震數(shù)據(jù),解開地震規(guī)律之謎。
展望
CUDA是一項(xiàng)以提高計(jì)算性能為目的的新興技術(shù),但是其影響將遠(yuǎn)遠(yuǎn)超出“計(jì)算”的范圍。GPGPU是一個(gè)神奇的事物,因?yàn)槿绻幚淼煤玫脑挘敲纯梢詭浊П兜拇蚱颇柖?,而跳躍到下一個(gè)時(shí)代。GPGPU的問題就在于編程的痛苦性太高,而 #p#page_title#e#CUDA就是為此目的而設(shè)計(jì)。就如同David Kirk所言,計(jì)算性能提高十倍會(huì)使現(xiàn)在的工具變得很方便,計(jì)算性能提高一百倍會(huì)使現(xiàn)在的軟件更新?lián)Q代。而計(jì)算性能提高一千倍,則會(huì)徹底改變?nèi)藗兊墓ぷ鞣绞健T?jīng)不可能的慢慢變?yōu)榭赡?。我們期待?span lang="EN-US">CUDA技術(shù)以及未來的新的GPGPU技術(shù)能夠帶領(lǐng)我們(程序員和用戶)走向新的時(shí)代!