《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計應(yīng)用 > CUDA和OpenGL互操作的實現(xiàn)及分析
CUDA和OpenGL互操作的實現(xiàn)及分析
來源:微型機與應(yīng)用2011年第23期
劉進鋒,,郭 雷
(西北工業(yè)大學(xué) 自動化學(xué)院,陜西 西安 710129)
摘要: CUDA和OpenGL互操作的基本方式是使用CUDA生成數(shù)據(jù),,再利用OpenGL在屏幕上繪制出數(shù)據(jù)所表示的圖形,。兩者的結(jié)合可以通過使用OpenGL的PBO(像素緩沖區(qū)對象)或VBO(頂點緩沖區(qū)對象)兩種方式來實現(xiàn),。描述了CUDA和OpenGL互操作的步驟并展示了一個使用PBO的實例。該實例運行結(jié)果表明,,互操作的方式比單純使用OpenGL方式快了7~8倍,。
Abstract:
Key words :

摘  要: CUDAOpenGL互操作的基本方式是使用CUDA生成數(shù)據(jù),再利用OpenGL在屏幕上繪制出數(shù)據(jù)所表示的圖形,。兩者的結(jié)合可以通過使用OpenGL的PBO(像素緩沖區(qū)對象)或VBO(頂點緩沖區(qū)對象)兩種方式來實現(xiàn),。描述了CUDA和OpenGL互操作的步驟并展示了一個使用PBO的實例。該實例運行結(jié)果表明,,互操作的方式比單純使用OpenGL方式快了7~8倍。
關(guān)鍵詞: CUDA,;OpenGL,;像素緩沖區(qū)對象;頂點緩沖區(qū)對象

1 CUDA與OpenGL概述
 OpenGL是圖形硬件的軟件接口,,它是在SGI等多家世界著名的計算機公司的倡導(dǎo)下,,以SGI的GL三維圖形庫為基礎(chǔ)制定的一個通用、共享的,、開放式的,、性能卓越的三維圖形標(biāo)準(zhǔn)。OpenGL在醫(yī)學(xué)成像,、地理信息,、石油勘探、氣候模擬以及娛樂動畫上有著廣泛應(yīng)用,,它已經(jīng)成為高性能圖形和交互式視景處理的工業(yè)標(biāo)準(zhǔn),。
 OpenGL不是一種編程語言,而是一種API(應(yīng)用程序編程接口),。程序員可以使用某種編程語言(如C或C++)編寫繪圖軟件,,其中調(diào)用了一個或多個OpenGL庫函數(shù)。作為一種API,,OpenGL遵循C語言的調(diào)用約定,。OpenGL開發(fā)資料可參考文獻[1]和參考文獻[2]。
 圖形處理器(GPU)原本是處理計算機圖形的專用設(shè)備,,近十年來,,由于高清晰度復(fù)雜圖形實時處理的需求,GPU發(fā)展成為高并行度,、多線程,、多核的處理器。目前,,主流GPU的運算能力已超過主流通用CPU,,從發(fā)展趨勢上來看將來差距會越拉越大。為了合理地利用GPU 資源,CUDA(統(tǒng)一計算設(shè)備架構(gòu))應(yīng)運而生,。CUDA是一種由NVIDIA推出的通用并行計算架構(gòu)[3],,該架構(gòu)使GPU能夠解決復(fù)雜的計算問題,并且由于CUDA編程語言基于標(biāo)準(zhǔn)的C語言,,從而大大提高了可編程性,。
CUDA和OpenGL互操作的基本方式是使用CUDA生成數(shù)據(jù),然后使用OpenGL在屏幕上繪制出數(shù)據(jù)所表示的圖形,。兩者的結(jié)合可以通過兩種方式來實現(xiàn):
 (1)使用OpenGL的PBO(像素緩沖區(qū)對象),。在該方式下,CUDA直接生成像素數(shù)據(jù),,OpenGL顯示這些像素,;
 (2)使用OpenGL的VBO(頂點緩沖區(qū)對象)。在該方式下,,CUDA生成頂點網(wǎng)格數(shù)據(jù),,OpenGL可以根據(jù)需要繪制出平滑的表面圖或線框圖或一系列頂點。
這兩種方式的核心都是利用cudaGLMapBufferObject函數(shù)將OpenGL的緩沖區(qū)映射到CUDA的內(nèi)存空間上,,這樣,,程序員就可以充分利用CUDA的優(yōu)點寫出性能高的程序在該內(nèi)存空間上生成數(shù)據(jù),這些數(shù)據(jù)不需要傳送,,OpenGL可以直接使用,。如果不使用CUDA,這些數(shù)據(jù)需要由CPU來計算產(chǎn)生,。一方面,,CPU的計算速度通常比GPU慢;另一方面,,這些數(shù)據(jù)需要傳送到GPU上以供OpenGL顯示使用,。鑒于此,當(dāng)數(shù)據(jù)量很大時,,CUDA和OpenGL的混合使用效果明顯,。
2 CUDA和OpenGL互操作的過程[4]
 CUDA和OpenGL互操作具體步驟如下:
 (1)創(chuàng)建窗口及OpenGL運行環(huán)境。
 (2)設(shè)置OpenGL視口和坐標(biāo)系,。要根據(jù)繪制的圖形是2D還是3D等具體情況設(shè)置,。(1)和(2)是所有OpenGL程序必需的,這里也沒什么特殊之處,,需要注意的是,,后面的一些功能需要OpenGL 2.0及以上版本支持,所以在這里需要進行版本檢查,。
 (3)創(chuàng)建CUDA環(huán)境,??梢允褂胏uGLCtxCreate或cudaGLSetGLDevice來設(shè)置CUDA環(huán)境。該設(shè)置一定要放在其他CUDA的API調(diào)用之前,。
 (4)產(chǎn)生一個或多個OpenGL緩沖區(qū)用以和CUDA共享,。使用PBO和使用VBO差不多,只是有些函數(shù)調(diào)用參數(shù)不同,。以下是具體過程,。
 GLuint bufferID;
 glGenBuffers(1,,&bufferID),;//產(chǎn)生一個buffer ID
 glBindBuffer(parameter1,bufferID),;
 //將其設(shè)置為當(dāng)前非壓縮緩沖區(qū),,如果是PBO方式,parameter1設(shè)置為GL_PIXEL_UNPACK_BUFFER,,如果
 是VBO方式,parameter1設(shè)置為GL_ARRAY_BUFFER
 glBufferData(parameter1,,parameter2,,NULL,GL_DYNAMIC _COPY),;
 //給該緩沖區(qū)分配數(shù)據(jù),,PBO方式下,parameter1設(shè)置為GL_PIXEL_UNPACK_BUFFER,,parameter1設(shè)置為圖像的長度*寬度*4,。VBO方式下,parameter1設(shè)置為GL_ARRAY_BUFFER,,parameter2設(shè)置為頂點數(shù)*16,,因為每個頂點包含3個浮點坐標(biāo)(x,y,,z)和4個顏色字節(jié)(RGBA),,這樣一個頂點包含16 B
 (5)用CUDA登記緩沖區(qū)。登記可以使用cuGLRegisterBufferObject或cudaGLRegisterBufferObject,,該命令告訴OpenGL和CUDA 驅(qū)動程序該緩沖區(qū)為二者共同使用,。
 (6)將OpenGL緩沖區(qū)映射到CUDA內(nèi)存??梢允褂胏uGLMapBufferObject或cudaGLMapBufferObject,,它實際是將CUDA內(nèi)存的指針指向OpenGL的緩沖區(qū),這樣如果只有一個GPU,,就不需要數(shù)據(jù)傳遞,。當(dāng)映射完成后,,OpenGL不能再使用該緩沖區(qū)。
 (7)使用CUDA往該映射的內(nèi)存寫圖像數(shù)據(jù),。前面的準(zhǔn)備工作在這里真正發(fā)揮作用了,,此時可以調(diào)用CUDA的kernel,像使用全局內(nèi)存一樣使用映射了的緩沖區(qū),,向其中寫數(shù)據(jù),。
 (8)取消OpenGL緩沖區(qū)映射。要等前面CUDA的活動完成以后,,使用cuGLUnmapBufferObject或cudaGLUnmapBufferObject函數(shù)取消映射,。
 (9)前面的步驟完成以后就可以真正開始繪圖了, OpenGL的PBO和VBO的繪圖方式不同,,分別為以下兩個過程,。
 ①如果只是繪制平面圖形,,需要使用OpenGL的PBO及紋理,。
 glEnable(GL_TEXTURE_2D); //使紋理可用
 glGenTextures(1,,&textureID),; //生成一個textureID
 glBindTexture(GL_TEXTURE_2D,textureID),;
 //使該紋理成為當(dāng)前可用紋理
 glTexImage2D(GL_TEXTURE_2D,,0,GL_RGBA8,,Width,, Height,0,,GL_BGRA,,GL_UNSIGNED_BYTE,NULL),;
 //分配紋理內(nèi)存,。最后的參數(shù)設(shè)置數(shù)據(jù)來源,這里設(shè)置為NULL,,表示數(shù)據(jù)來自PBO,,不是來自主機內(nèi)存
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN _FILTER,,GL_LINEAR),;
 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_ FILTER,,GL_LINEAR),;//必須設(shè)置濾波模式,,GL_LINEAR允許圖形伸縮時線性差值。如果不需要線性差值,,可以用GL_TEXTURE_RECTANGLE_ARB代替GL_TEXTURE_2D以提高性能,,同時在glTexParameteri()調(diào)用里使用GL_NEAREST替換GL_LINEAR
 然后就可以指定4個角的紋理坐標(biāo),繪制長方形了,。
?、诶L制3D場景,需要使用VBO,。
glEnableClientState(GL_VERTEX_ARRAY),;
//使頂點和顏色數(shù)組可用
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3,,GL_FLOAT,,16,0),;
//設(shè)置頂點和顏色指針
glColorPointer(4,,GL_UNSIGNED_BYTE,16,,12),;
glDrawArrays(GL_POINTS,0,,numVerticies);
//根據(jù)頂點數(shù)據(jù)繪圖,,參數(shù)可以使用GL_LINES,, GL_LINE_STRIP, GL_LINE_LOOP,, GL_TRIANGLES,,GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN,, GL_QUADS,,GL_QUAD_STRIP,GL_POLYGON
(10)前后緩存區(qū)來回切換,,實現(xiàn)動畫顯示效果,。調(diào)用SwapBuffers(),緩沖區(qū)切換通常會在垂直刷新間隙來處理,,因此,,可以在控制面板上關(guān)掉垂直同步,使得緩沖區(qū)切換立刻進行,。
3 CUDA和OpenGL互操作性能實例分析
3.1 測試實例

 


 這是一個相對簡單的實例,,其主要功能是不斷地動態(tài)改變一個紋理圖案中每個像素的顏色并顯示,。該實例使用了OpenGL的PBO并利用了OpenGL與CUDA互操作方式,紋理圖案數(shù)據(jù)的生成主要由CUDA的kernel函數(shù)完成,,完整程序及CUDA的kernel函數(shù)請參看參考文獻[5],。
如果不使用CUDA,整個程序結(jié)構(gòu)變化不大,,主要差別是生成該紋理圖案的函數(shù)在CPU上運行,,因而該函數(shù)及其調(diào)用方式要重寫,具體函數(shù)如下:
void kernel(uchar4*pos,,unsigned int width,,unsigned int height,float time)
{ unsigned int index,,x,,y;
  for(x=0,;x<width,;x++)
    for(y=0;y<height,;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;
     }
}
    其中,,參數(shù)pos表示像素數(shù)組,,width為圖像寬度,height為圖像高度,,time是每次調(diào)用該函數(shù)時固定遞增的一個值,。
3.2 測試結(jié)果
 上述實例在兩種環(huán)境中做了實驗,CUDA版本都是3.2,。測試環(huán)境1的主要配置如下:CPU為Intel Core i3-M380,,主頻為2.53 GHz,GPU為 NVIDIA NVS 3100M,,內(nèi)存為2 GB,。測試環(huán)境2的主要配置如下:CPU是Intel Core2 duo E7400,主頻為2.8 GHz,,GPU使用GeForce 9800 GTX+,,內(nèi)存為2 GB,。測試時,顯示設(shè)置的垂直同步要關(guān)閉,。
 測試時設(shè)置紋理圖像的長和寬都是512,,CUDA的線程塊為1 024,每個線程塊內(nèi)的線程數(shù)為256,,在OpenGL的顯示回調(diào)函數(shù)里統(tǒng)計f/s(刷新率),,結(jié)果如表1所示。

 從實驗結(jié)果可以看出,,CUDA與OpenGL結(jié)合的方式效果顯著,,顯示速度比不使用CUDA提高了7~8倍。
CUDA是一種較新的方便使用GPU進行通用計算的架構(gòu),,OpenGL是圖形處理的工業(yè)標(biāo)準(zhǔn),。兩者的互操作充分利用了GPU的特點,因而顯得非常自然和合理,,實驗驗證了兩者配合使用的效果,。該方式為高性能圖形圖像顯示及科學(xué)計算可視化提供了良好的模式架構(gòu)。
參考文獻
[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.

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載,。