基于μ-Chip芯片RFID防偽票證系統的設計
1 CUDA與OpenGL概述
OpenGL是圖形硬件的軟件接口,它是在SGI等多家世界著(zhù)名的計算機公司的倡導下,以SGI的GL三維圖形庫為基礎制定的一個(gè)通用、共享的、開(kāi)放式的、性能卓越的三維圖形標準。OpenGL在醫學(xué)成像、地理信息、石油勘探、氣候模擬以及娛樂(lè )動(dòng)畫(huà)上有著(zhù)廣泛應用,它已經(jīng)成為高性能圖形和交互式視景處理的工業(yè)標準。
OpenGL不是一種編程語(yǔ)言,而是一種API(應用程序編程接口)。程序員可以使用某種編程語(yǔ)言(如C或C++)編寫(xiě)繪圖軟件,其中調用了一個(gè)或多個(gè)OpenGL庫函數。作為一種API,OpenGL遵循C語(yǔ)言的調用約定。OpenGL開(kāi)發(fā)資料可參考文獻[1]和參考文獻[2]。
圖形處理器(GPU)原本是處理計算機圖形的專(zhuān)用設備,近十年來(lái),由于高清晰度復雜圖形實(shí)時(shí)處理的需求,GPU發(fā)展成為高并行度、多線(xiàn)程、多核的處理器。目前,主流GPU的運算能力已超過(guò)主流通用CPU,從發(fā)展趨勢上來(lái)看將來(lái)差距會(huì )越拉越大。為了合理地利用GPU 資源,CUDA(統一計算設備架構)應運而生。CUDA是一種由NVIDIA推出的通用并行計算架構[3],該架構使GPU能夠解決復雜的計算問(wèn)題,并且由于CUDA編程語(yǔ)言基于標準的C語(yǔ)言,從而大大提高了可編程性。
CUDA和OpenGL互操作的基本方式是使用CUDA生成數據,然后使用OpenGL在屏幕上繪制出數據所表示的圖形。兩者的結合可以通過(guò)兩種方式來(lái)實(shí)現:
(1)使用OpenGL的PBO(像素緩沖區對象)。在該方式下,CUDA直接生成像素數據,OpenGL顯示這些像素;
(2)使用OpenGL的VBO(頂點(diǎn)緩沖區對象)。在該方式下,CUDA生成頂點(diǎn)網(wǎng)格數據,OpenGL可以根據需要繪制出平滑的表面圖或線(xiàn)框圖或一系列頂點(diǎn)。
這兩種方式的核心都是利用cudaGLMapBufferObject函數將OpenGL的緩沖區映射到CUDA的內存空間上,這樣,程序員就可以充分利用CUDA的優(yōu)點(diǎn)寫(xiě)出性能高的程序在該內存空間上生成數據,這些數據不需要傳送,OpenGL可以直接使用。如果不使用CUDA,這些數據需要由CPU來(lái)計算產(chǎn)生。一方面,CPU的計算速度通常比GPU慢;另一方面,這些數據需要傳送到GPU上以供OpenGL顯示使用。鑒于此,當數據量很大時(shí),CUDA和OpenGL的混合使用效果明顯。
2 CUDA和OpenGL互操作的過(guò)程[4]
CUDA和OpenGL互操作具體步驟如下:
(1)創(chuàng )建窗口及OpenGL運行環(huán)境。
(2)設置OpenGL視口和坐標系。要根據繪制的圖形是2D還是3D等具體情況設置。(1)和(2)是所有OpenGL程序必需的,這里也沒(méi)什么特殊之處,需要注意的是,后面的一些功能需要OpenGL 2.0及以上版本支持,所以在這里需要進(jìn)行版本檢查。
(3)創(chuàng )建CUDA環(huán)境??梢允褂胏uGLCtxCreate或cudaGLSetGLDevice來(lái)設置CUDA環(huán)境。該設置一定要放在其他CUDA的API調用之前。
(4)產(chǎn)生一個(gè)或多個(gè)OpenGL緩沖區用以和CUDA共享。使用PBO和使用VBO差不多,只是有些函數調用參數不同。以下是具體過(guò)程。
GLuint bufferID;
glGenBuffers(1,bufferID);//產(chǎn)生一個(gè)buffer ID
glBindBuffer(parameter1,bufferID);
//將其設置為當前非壓縮緩沖區,如果是PBO方式,parameter1設置為GL_PIXEL_UNPACK_BUFFER,如果
是VBO方式,parameter1設置為GL_ARRAY_BUFFER
glBufferData(parameter1,parameter2,NULL,GL_DYNAMIC _COPY);
//給該緩沖區分配數據,PBO方式下,parameter1設置為GL_PIXEL_UNPACK_BUFFER,parameter1設置為圖像的長(cháng)度*寬度*4。VBO方式下,parameter1設置為GL_ARRAY_BUFFER,parameter2設置為頂點(diǎn)數*16,因為每個(gè)頂點(diǎn)包含3個(gè)浮點(diǎn)坐標(x,y,z)和4個(gè)顏色字節(RGBA),這樣一個(gè)頂點(diǎn)包含16 B
(5)用CUDA登記緩沖區。登記可以使用cuGLRegisterBufferObject或cudaGLRegisterBufferObject,該命令告訴OpenGL和CUDA 驅動(dòng)程序該緩沖區為二者共同使用。
(6)將OpenGL緩沖區映射到CUDA內存??梢允褂胏uGLMapBufferObject或cudaGLMapBufferObject,它實(shí)際是將CUDA內存的指針指向OpenGL的緩沖區,這樣如果只有一個(gè)GPU,就不需要數據傳遞。當映射完成后,OpenGL不能再使用該緩沖區。
(7)使用CUDA往該映射的內存寫(xiě)圖像數據。前面的準備工作在這里真正發(fā)揮作用了,此時(shí)可以調用CUDA的kernel,像使用全局內存一樣使用映射了的緩沖區,向其中寫(xiě)數據。
(8)取消OpenGL緩沖區映射。要等前面CUDA的活動(dòng)完成以后,使用cuGLUnmapBufferObject或cudaGLUnmapBufferObject函數取消映射。
(9)前面的步驟完成以后就可以真正開(kāi)始繪圖了, OpenGL的PBO和VBO的繪圖方式不同,分別為以下兩個(gè)過(guò)程。
?、偃绻皇抢L制平面圖形,需要使用OpenGL的PBO及紋理。
glEnable(GL_TEXTURE_2D); //使紋理可用
glGenTextures(1,textureID); //生成一個(gè)textureID
glBindTexture(GL_TEXTURE_2D,textureID);
//使該紋理成為當前可用紋理
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,Width, Height,0,GL_BGRA,GL_UNSIGNED_BYTE,NULL);
//分配紋理內存。最后的參數設置數據來(lái)源,這里設置為NULL,表示數據來(lái)自PBO,不是來(lái)自主機內存
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN _FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_ FILTER,GL_LINEAR);//必須設置濾波模式,GL_LINEAR允許圖形伸縮時(shí)線(xiàn)性差值。如果不需要線(xiàn)性差值,可以用GL_TEXTURE_RECTANGLE_ARB代替GL_TEXTURE_2D以提高性能,同時(shí)在glTexParameteri()調用里使用GL_NEAREST替換GL_LINEAR
然后就可以指定4個(gè)角的紋理坐標,繪制長(cháng)方形了。
?、诶L制3D場(chǎng)景,需要使用VBO。
glEnableClientState(GL_VERTEX_ARRAY);
//使頂點(diǎn)和顏色數組可用
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3,GL_FLOAT,16,0);
//設置頂點(diǎn)和顏色指針
glColorPointer(4,GL_UNSIGNED_BYTE,16,12);
glDrawArrays(GL_POINTS,0,numVerticies);
//根據頂點(diǎn)數據繪圖,參數可以使用GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES,GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS,GL_QUAD_STRIP,GL_POLYGON
(10)前后緩存區來(lái)回切換,實(shí)現動(dòng)畫(huà)顯示效果。調用SwapBuffers(),緩沖區切換通常會(huì )在垂直刷新間隙來(lái)處理,因此,可以在控制面板上關(guān)掉垂直同步,使得緩沖區切換立刻進(jìn)行。
3 CUDA和OpenGL互操作性能實(shí)例分析
3.1 測試實(shí)例
這是一個(gè)相對簡(jiǎn)單的實(shí)例,其主要功能是不斷地動(dòng)態(tài)改變一個(gè)紋理圖案中每個(gè)像素的顏色并顯示。該實(shí)例使用了OpenGL的PBO并利用了OpenGL與CUDA互操作方式,紋理圖案數據的生成主要由CUDA的kernel函數完成,完整程序及CUDA的kernel函數請參看參考文獻[5]。
如果不使用CUDA,整個(gè)程序結構變化不大,主要差別是生成該紋理圖案的函數在CPU上運行,因而該函數及其調用方式要重寫(xiě),具體函數如下:
void kernel(uchar4*pos,unsigned int width,unsigned int height,float time)
{ unsigned int index,x,y;
for(x=0;xwidth;x++)
for(y=0;yheight;y++)
{ unsigned char r=(x+(int)time)0xff;
unsigned char g=(y+(int)time)0xff;
unsigned char b=((x+y)+(int)time)0xff;
index=x*width+y;
pos[index].w=0;
pos[index].x=r;
pos[index].y=g;
pos[index].z=b;
}
}
其中,參數pos表示像素數組,width為圖像寬度,height為圖像高度,time是每次調用該函數時(shí)固定遞增的一個(gè)值。
3.2 測試結果
上述實(shí)例在兩種環(huán)境中做了實(shí)驗,CUDA版本都是3.2。測試環(huán)境1的主要配置如下:CPU為Intel Core i3-M380,主頻為2.53 GHz,GPU為 NVIDIA NVS 3100M,內存為2 GB。測試環(huán)境2的主要配置如下:CPU是Intel Core2 duo E7400,主頻為2.8 GHz,GPU使用GeForce 9800 GTX+,內存為2 GB。測試時(shí),顯示設置的垂直同步要關(guān)閉。
測試時(shí)設置紋理圖像的長(cháng)和寬都是512,CUDA的線(xiàn)程塊為1 024,每個(gè)線(xiàn)程塊內的線(xiàn)程數為256,在OpenGL的顯示回調函數里統計f/s(刷新率),結果如表1所示。
從實(shí)驗結果可以看出,CUDA與OpenGL結合的方式效果顯著(zhù),顯示速度比不使用CUDA提高了7~8倍。
CUDA是一種較新的方便使用GPU進(jìn)行通用計算的架構,OpenGL是圖形處理的工業(yè)標準。兩者的互操作充分利用了GPU的特點(diǎn),因而顯得非常自然和合理,實(shí)驗驗證了兩者配合使用的效果。該方式為高性能圖形圖像顯示及科學(xué)計算可視化提供了良好的模式架構。
參考文獻
[1] WRIGHT R S, LIPCHAK B, HAEMEL N. OpenGL superbible (Fourth Edition)[M]. Addison-Wesley, 2007.
[2] AHN S H. The OpenGL tutorials[OL]. [2011-09-01].http://songho.ca/opengl/.
[3] NVIDIA Corporation. NVIDIA CUDA programming Guide Version 3.2[OL]. Mar. 2011,http://developer.nvidia.com/cuda.
[4] STAM J. What every CUDA programmer needs to know about OpenGL[OL]. [2011-09-01].http://nvidia.fullviewmedia.com/GPU2009/1001-valley-1055.html.
[5] FARBER R. CUDA, supercomputing for the masses: Part 15[OL]. [2011-09-01].http://www.drdobbs.com/architecture-and-design/222600097.
相關(guān)推薦
技術(shù)專(zhuān)區
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線(xiàn)
- 開(kāi)關(guān)電源
- 單片機
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開(kāi)發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機控制
- 藍牙
- PLC
- PWM
- 汽車(chē)電子
- 轉換器
- 電源管理
- 信號放大器
評論