基于CUDA技術(shù)模擬雷達余輝的方法
在建立雷達虛擬操作系統或維修訓練系統時(shí),顯示器的仿真效果直接影響模擬器的訓練效果。目前制約余輝實(shí)現的主要瓶頸是余輝效果帶來(lái)的龐大的計算量,使得效果較好的余輝掃描線(xiàn)轉速難以超過(guò)10轉/s,如果要提高轉速,則需要以犧牲顯示畫(huà)質(zhì)為代價(jià)?;诠鈻艗呙栌噍x模擬的主流方法有畫(huà)線(xiàn)法、固定扇掃法、逐點(diǎn)消隱法,由于前兩者圖像易出現輻射狀花紋及掃描速率不穩定,因此后者的應用較多,效果也明顯強于前者[1]。本文在逐點(diǎn)消隱法的基礎上應用CUDA技術(shù),解決了運算量巨大的問(wèn)題,在光柵顯示器上得到了余輝效果逼真、畫(huà)面流暢的余輝圖形。
1 余輝仿真的瓶頸
傳統的雷達P顯采用示波管作為顯示終端,其內部熒光材料具有指數型衰減的余輝效應,電子束掃描線(xiàn)圓周掃過(guò)屏幕將留下逐漸消隱的余輝[2]。但光柵顯示器無(wú)法自動(dòng)產(chǎn)生熒光粉的余輝效應,因此必須人為地模擬余輝效應。
軟模擬通常采用光柵顯示器,用計算機編程實(shí)現。光柵掃描顯示器具有高亮度、高穩定度、大容量顯示的圖文處理能力、豐富的色彩及多灰度等級的優(yōu)點(diǎn)。一般采用以下三種方法實(shí)現[3-4]。
(1)畫(huà)線(xiàn)法較容易實(shí)現,原理是在屏幕上以畫(huà)直線(xiàn)的方式畫(huà)出每一角度的掃描線(xiàn),形成每次畫(huà)一個(gè)扇面的灰度遞減的直線(xiàn)簇。但是當程序運行時(shí),掃描線(xiàn)軌跡不斷地在屏幕上轉動(dòng),該方法不能無(wú)縫地覆蓋整個(gè)扇掃區域,從而產(chǎn)生一個(gè)輻射狀的固定花紋。
(2)固定扇掃法是在畫(huà)線(xiàn)法基礎上改進(jìn)的一種仿真方法,控制扇形區域的圓心角,依次使不同扇形區域亮度減少。它雖然消除了輻射狀花紋,但在沒(méi)有目標到有目標信號時(shí),由于數據量的增加會(huì )造成掃描線(xiàn)的轉速不同。
(3)逐點(diǎn)消隱法,主要原理是將每個(gè)方位像素的亮度逐次遞減,即每個(gè)點(diǎn)都必須被修改,這樣整個(gè)屏幕畫(huà)面亮度逐漸衰減。其產(chǎn)生的余輝效果比較逼真,掃描線(xiàn)轉速也較穩定。
模擬逼真的余輝效果,一般采用逐點(diǎn)消隱法,十分逼真的余輝仿真需要非常高的數據吞吐率,要求在每一顯示幀的時(shí)間內(一般為60 Hz的倒數約16 ms)對屏幕中所有像素進(jìn)行一次衰減運算。以公認的高效算法,即查表法為例:對于一個(gè)像素點(diǎn)而言,最少需要1次讀和2次寫(xiě)操作,分辨率為1 024×1 024的屏幕中會(huì )有1 024×1 024個(gè)像素點(diǎn)參與雷達回波的顯示,數量約為1 M。即在16 ms的時(shí)間內需要進(jìn)行1 M次讀操作和2 M次寫(xiě)操作,分給每個(gè)像素點(diǎn)的時(shí)間為16 ns。由于Windows屬于通用型操作系統,硬件操作過(guò)程極其復雜,無(wú)論如何也無(wú)法在16 ns內完成1次讀和2次寫(xiě)操作。需要說(shuō)明的是,現有的用PC實(shí)現的余輝仿真算法都是以犧牲畫(huà)質(zhì)為前提條件的,例如有的算法降低角度分辨率,有的算法只運算部分像素。
2 瓶頸的解決方案
為了解決此瓶頸,本文將國外主要應用于3D游戲設計的CUDA技術(shù)移植到余輝的模擬上。CUDA(統一計算設備架構)是NVIDIA公司在2007年推出的針對GPGPU(通用計算GPU)的一個(gè)全新構想,使專(zhuān)注于圖像處理的GPU超高性能在數據處理和科學(xué)計算等通用計算領(lǐng)域發(fā)揮優(yōu)勢[5]。
GPU特別適合并行數據運算問(wèn)題,同一個(gè)程序可操作許多并行數據元素,并具有高運算密度(算術(shù)運算與內存操作的比例),且在高密度運算時(shí),GPU訪(fǎng)問(wèn)內存的延遲可以被掩蓋。目前高端GPU計算性能已達到Teraflops(每秒萬(wàn)億次浮點(diǎn)運算)級別,其運算速度遠遠高于CPU的速度[6-7]。2008年初國內建成的首套實(shí)驗系統,其計算性能的理論峰值124 Teraflops,可用峰值82 Teraflops。
但是常規的GPU通用計算還存在以下問(wèn)題[7]:編程過(guò)于繁雜,難以學(xué)習與使用,在非圖形領(lǐng)域應用很不充分;GPU編程缺乏靈活性,對GPU性能的發(fā)揮有很大的限制。
而CUDA采用GPU+CPU的方式,通過(guò)標準C語(yǔ)言將GPU的眾多的計算特性結合到一起,由線(xiàn)程來(lái)創(chuàng )建應用程序。程序代碼在實(shí)際執行中分為兩種,一種是運行在CPU上的主機代碼,另一種是運行在GPU上的設備代碼。它類(lèi)似于CPU上的多線(xiàn)程程序,但與僅能有很少線(xiàn)程同時(shí)工作的多核CPU相比,GPU可以同時(shí)執行成千上萬(wàn)個(gè)線(xiàn)程[8-9]。CPU程序以異步的方式調用GPU核程序,GPU作為CPU的協(xié)處理器(CoProeessor)提供服務(wù)。
當前CUDA提供的主要功能如下[7]:
(1)在GPU上提供標準C編程語(yǔ)言。
(2)為在支持CUDA的NVIDIA GPU的并行計算提供統一的軟硬件解決方案。
(3)支持CUDA的GPU能進(jìn)行并行數據緩存和線(xiàn)程執行管理。
(4)經(jīng)過(guò)優(yōu)化的,從CPU到支持CUDA的GPU的直接上傳、下載通道。
(5)CUDA驅動(dòng)與DirectX和OpenGL等圖形驅動(dòng)程序兼容。
為了解決巨大計算量的問(wèn)題,主要采用CPU+GPU的編程模式來(lái)模擬余輝,在GPU中為每一個(gè)像素點(diǎn)創(chuàng )建一個(gè)線(xiàn)程獨立進(jìn)行亮度衰減處理。由于每個(gè)像素的線(xiàn)程并行執行,完成整個(gè)屏幕像素的數據處理幾乎不需要計算時(shí)間,真正花費時(shí)間的是畫(huà)面繪制和翻轉。因此繪制畫(huà)面在后臺表面進(jìn)行,繪制完成后翻轉到前臺顯示,這樣繪制和顯示可以同時(shí)進(jìn)行,既為畫(huà)面的繪制留足了時(shí)間,又能得到流暢不閃爍的畫(huà)質(zhì)。
3 采用CUDA技術(shù)來(lái)實(shí)現余輝效果
為了產(chǎn)生不同方位的掃描線(xiàn),將方位、距離進(jìn)行量化,由于掃描區域的分辨率為1 024×1 024,因此半徑為512像素。由于掃描半徑為512個(gè)像素,理論上只要角度量化數N大于3 217就不會(huì )出現顯示死地址的現象[10],方位上量化為4 096個(gè)等分。這樣初始生成一個(gè)4 096×512個(gè)像素的圓域。雷達P顯中采用的是極坐標系,而在光柵顯示器中采用的是直角坐標,通過(guò)坐標變換,將建立一張坐標變換表,如表1所示。
通過(guò)查表可以避免坐標變換帶來(lái)的正余弦計算,方便地在極坐標和直角坐標間轉換,從而節省大量的運算時(shí)間[11]??紤]到近距離區域,多個(gè)角度的距離單元會(huì )對應相同的像素點(diǎn),首先為每個(gè)像素點(diǎn)定義一個(gè)屬性的結構體:
typedef struct
{ WORD x;//屏幕直角坐標x
WORD y;//屏幕直角坐標y
WORD ScanlinePtIndex;//該點(diǎn)在掃描線(xiàn)上的
//距離索引
BYTE MapTo2Pt;//該點(diǎn)與同一條掃描上的
//點(diǎn)是否重合
BYTE RadEnd;//標記該條掃描線(xiàn)處理完畢
}RADIUSPOINT;
為圓域內的點(diǎn)分配內存空間:
RADIUSPOINT m_pRadPtToLintPtMap=new RADIUSPOINT[4 096×512]。
對于同一條掃描線(xiàn)上相鄰的兩點(diǎn),如果直角坐標相同就把MapTo2Pt設為1,標記為相同的點(diǎn);如果相鄰兩點(diǎn)的直角坐標不相同,則把距離索引值賦給ScanlinePtIndex,每條線(xiàn)最后一個(gè)點(diǎn)設置RadEnd為1來(lái)標記每條線(xiàn)處理已完畢。對于相鄰兩條線(xiàn)上的點(diǎn),如果當前線(xiàn)上點(diǎn)與前一條線(xiàn)上相鄰4個(gè)點(diǎn)的直角坐標相等,設置為m_pPixelOverlap[i]=1,否則設為0。
考慮到余輝呈指數型衰減,而指數運算需要花費大量的時(shí)間,對于計算機,其最快的操作是取值和賦值,為了提高光柵掃描雷達顯示系統的實(shí)時(shí)性,需要提高單位時(shí)間內能夠處理的像素點(diǎn)個(gè)數。于是對指數運算采用查表法以提高速度,維護一張按角度劃分的指數型衰減因子表m_wAttenuation[4 096]以進(jìn)行數值的取值和賦值操作。
同時(shí)還要建立一個(gè)Brightness[4 096×512]的亮度表,來(lái)存儲每個(gè)像素對應的RGB顏色值。
以上這些工作在程序的初始化中即完成,一經(jīng)完成即可在后續的程序中直接調用。
通過(guò)CUDA編程時(shí),GPU可看作為可以并行執行非常多個(gè)線(xiàn)程的計算設備,執行并行計算的線(xiàn)程被組織成線(xiàn)程塊(Block),每個(gè)線(xiàn)程塊可以包含多達512個(gè)線(xiàn)程,而線(xiàn)程塊又組成了柵格(Grid)。GPU可以支持成百上千萬(wàn)個(gè)并行線(xiàn)程,于是可以為每個(gè)像素點(diǎn)開(kāi)一個(gè)線(xiàn)程,這樣每個(gè)像素點(diǎn)可以并行處理,能極大地提高對整個(gè)屏幕像素的處理速度,為CPU留出足夠多的時(shí)間去處理其他相關(guān)的任務(wù)。
定義線(xiàn)程塊Block包含的線(xiàn)程維數:
dim3 threads(BLOCK_SIZE,BLOCK_SIZE);
定義柵格Grid包含的線(xiàn)程塊數:
dim3 grid(Width/threads.x,Height/ threads.y);
每個(gè)像素點(diǎn)對應的線(xiàn)程處理工作如下:
由于某型雷達轉速為10轉/min,相當于每次更新的掃描線(xiàn)數應為4 096×10/60/1 000=0.683條/ms,像素處理在GPU中并行進(jìn)行,對CPU的占用率幾乎為零,所消耗的時(shí)間主要是Direct3D紋理的繪制和表面的翻轉,大約為16 ms,因此每次更新的掃描線(xiàn)數目約為16×0.683=10.928,即每次更新11條。將當前要更新的掃描線(xiàn)上的像素點(diǎn)設為初始亮度,其后的每條掃描線(xiàn)上的像素點(diǎn)的亮度按與當前掃描線(xiàn)角度差m_anglediff取m_wAttenuation[m_anglediff]的亮度進(jìn)行衰減。由于近距離區域多個(gè)角度的距離單元對應相同的像素點(diǎn),因此中心部位被消隱的次數明顯要比其他部位多,導致效果有些失真。于是需要對這些坐標相同的點(diǎn)進(jìn)行處理,對于屬性MapTo2Pt為1的點(diǎn),比較坐標相同的點(diǎn)處于不同距離時(shí)的亮度,取其大者賦值給亮度表Brightness[4 096×512]。對于屬性m_pPixelOverlap為1的點(diǎn),比較處于各個(gè)角度時(shí)的亮度,取其大者賦值給亮度表。這樣對于同一個(gè)點(diǎn)只顯示一次且取其最亮者顯示,較好地避免了中心部位被消隱次數過(guò)多的情況。
對于實(shí)現余輝等級的情況,只需要調制m_wAttenuation的大小就可以方便地調節余輝等級。如果需要提高轉速,只需增大每次更新的掃描線(xiàn)數目即可,且基本不會(huì )影響程序運行速度。
通過(guò)CPU+GPU組合的方式模擬不同等級余輝效果如圖1、圖2所示,此時(shí)對應的CPU占用率幾乎為零,如圖3所示。該方法得到的余輝效果逼真、畫(huà)面流暢、掃描速度達到了預定的10轉/s的要求,且CPU占用率極低,并不妨礙CPU處理其他數據。
評論