资料介绍
1 CUDA与OpenGL概述
OpenGL是图形硬件的软件接口,它是在SGI等多家世界著名的计算机公司的倡导下,以SGI的GL三维图形库为基础制定的一个通用、共享的、开放式的、性能卓越的三维图形标准。OpenGL在医学成像、地理信息、石油勘探、气候模拟以及娱乐动画上有着广泛应用,它已经成为高性能图形和交互式视景处理的工业标准。
OpenGL不是一种编程语言,而是一种API(应用程序编程接口)。程序员可以使用某种编程语言(如C或C++)编写绘图软件,其中调用了一个或多个OpenGL库函数。作为一种API,OpenGL遵循C语言的调用约定。OpenGL开发资料可参考文献[1]和参考文献[2]。
图形处理器(GPU)原本是处理计算机图形的专用设备,近十年来,由于高清晰度复杂图形实时处理的需求,GPU发展成为高并行度、多线程、多核的处理器。目前,主流GPU的运算能力已超过主流通用CPU,从发展趋势上来看将来差距会越拉越大。为了合理地利用GPU 资源,CUDA(统一计算设备架构)应运而生。CUDA是一种由NVIDIA推出的通用并行计算架构[3],该架构使GPU能够解决复杂的计算问题,并且由于CUDA编程语言基于标准的C语言,从而大大提高了可编程性。
CUDA和OpenGL互操作的基本方式是使用CUDA生成数据,然后使用OpenGL在屏幕上绘制出数据所表示的图形。两者的结合可以通过两种方式来实现:
(1)使用OpenGL的PBO(像素缓冲区对象)。在该方式下,CUDA直接生成像素数据,OpenGL显示这些像素;
(2)使用OpenGL的VBO(顶点缓冲区对象)。在该方式下,CUDA生成顶点网格数据,OpenGL可以根据需要绘制出平滑的表面图或线框图或一系列顶点。
这两种方式的核心都是利用cudaGLMapBufferObject函数将OpenGL的缓冲区映射到CUDA的内存空间上,这样,程序员就可以充分利用CUDA的优点写出性能高的程序在该内存空间上生成数据,这些数据不需要传送,OpenGL可以直接使用。如果不使用CUDA,这些数据需要由CPU来计算产生。一方面,CPU的计算速度通常比GPU慢;另一方面,这些数据需要传送到GPU上以供OpenGL显示使用。鉴于此,当数据量很大时,CUDA和OpenGL的混合使用效果明显。
2 CUDA和OpenGL互操作的过程[4]
CUDA和OpenGL互操作具体步骤如下:
(1)创建窗口及OpenGL运行环境。
(2)设置OpenGL视口和坐标系。要根据绘制的图形是2D还是3D等具体情况设置。(1)和(2)是所有OpenGL程序必需的,这里也没什么特殊之处,需要注意的是,后面的一些功能需要OpenGL 2.0及以上版本支持,所以在这里需要进行版本检查。
(3)创建CUDA环境。可以使用cuGLCtxCreate或cudaGLSetGLDevice来设置CUDA环境。该设置一定要放在其他CUDA的API调用之前。
(4)产生一个或多个OpenGL缓冲区用以和CUDA共享。使用PBO和使用VBO差不多,只是有些函数调用参数不同。以下是具体过程。
GLuint bufferID;
glGenBuffers(1,&bufferID);//产生一个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设置为图像的长度*宽度*4。VBO方式下,parameter1设置为GL_ARRAY_BUFFER,parameter2设置为顶点数*16,因为每个顶点包含3个浮点坐标(x,y,z)和4个颜色字节(RGBA),这样一个顶点包含16 B
(5)用CUDA登记缓冲区。登记可以使用cuGLRegisterBufferObject或
cudaGLRegisterBufferObject,该命令告诉OpenGL和CUDA 驱动程序该缓冲区为二者共同使用。
(6)将OpenGL缓冲区映射到CUDA内存。可以使用cuGLMapBufferObject或cudaGLMapBufferObject,它实际是将CUDA内存的指针指向OpenGL的缓冲区,这样如果只有一个GPU,就不需要数据传递。当映射完成后,OpenGL不能再使用该缓冲区。
(7)使用CUDA往该映射的内存写图像数据。前面的准备工作在这里真正发挥作用了,此时可以调用CUDA的kernel,像使用全局内存一样使用映射了的缓冲区,向其中写数据。
(8)取消OpenGL缓冲区映射。要等前面CUDA的活动完成以后,使用cuGLUnmapBufferObject或cudaGLUnmapBufferObject函数取消映射。
(9)前面的步骤完成以后就可以真正开始绘图了, OpenGL的PBO和VBO的绘图方式不同,分别为以下两个过程。
①如果只是绘制平面图形,需要使用OpenGL的PBO及纹理。
glEnable(GL_TEXTURE_2D); //使纹理可用
glGenTextures(1,&textureID); //生成一个textureID
glBindTexture(GL_TEXTURE_2D,textureID);
//使该纹理成为当前可用纹理
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,Width, Height,0,GL_BGRA,GL_UNSIGNED_BYTE,NULL);
//分配纹理内存。最后的参数设置数据来源,这里设置为NULL,表示数据来自PBO,不是来自主机内存
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN _FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_ FILTER,GL_LINEAR);//必须设置滤波模式,GL_LINEAR允许图形伸缩时线性差值。如果不需要线性差值,可以用GL_TEXTURE_RECTANGLE_ARB代替GL_TEXTURE_2D以提高性能,同时在glTexParameteri()调用里使用GL_NEAREST替换GL_LINEAR
然后就可以指定4个角的纹理坐标,绘制长方形了。
②绘制3D场景,需要使用VBO。
glEnableClientState(GL_VERTEX_ARRAY);
//使顶点和颜色数组可用
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3,GL_FLOAT,16,0);
//设置顶点和颜色指针
glColorPointer(4,GL_UNSIGNED_BYTE,16,12);
glDrawArrays(GL_POINTS,0,numVerticies);
//根据顶点数据绘图,参数可以使用GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES,GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS,GL_QUAD_STRIP,GL_POLYGON
(10)前后缓存区来回切换,实现动画显示效果。调用SwapBuffers(),缓冲区切换通常会在垂直刷新间隙来处理,因此,可以在控制面板上关掉垂直同步,使得缓冲区切换立刻进行。
3 CUDA和OpenGL互操作性能实例分析
3.1 测试实例
这是一个相对简单的实例,其主要功能是不断地动态改变一个纹理图案中每个像素的颜色并显示。该实例使用了OpenGL的PBO并利用了OpenGL与CUDA互操作方式,纹理图案数据的生成主要由CUDA的kernel函数完成,完整程序及CUDA的kernel函数请参看参考文献[5]。
如果不使用CUDA,整个程序结构变化不大,主要差别是生成该纹理图案的函数在CPU上运行,因而该函数及其调用方式要重写,具体函数如下:
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;
}
}
其中,参数pos表示像素数组,width为图像宽度,height为图像高度,time是每次调用该函数时固定递增的一个值。
3.2 测试结果
上述实例在两种环境中做了实验,CUDA版本都是3.2。测试环境1的主要配置如下:CPU为Intel Core i3-M380,主频为2.53 GHz,GPU为 NVIDIA NVS 3100M,内存为2 GB。测试环境2的主要配置如下:CPU是Intel Core2 duo E7400,主频为2.8 GHz,GPU使用GeForce 9800 GTX+,内存为2 GB。测试时,显示设置的垂直同步要关闭。
测试时设置纹理图像的长和宽都是512,CUDA的线程块为1 024,每个线程块内的线程数为256,在OpenGL的显示回调函数里统计f/s(刷新率),结果如表1所示。
从实验结果可以看出,CUDA与OpenGL结合的方式效果显著,显示速度比不使用CUDA提高了7~8倍。
CUDA是一种较新的方便使用GPU进行通用计算的架构,OpenGL是图形处理的工业标准。两者的互操作充分利用了GPU的特点,因而显得非常自然和合理,实验验证了两者配合使用的效果。该方式为高性能图形图像显示及科学计算可视化提供了良好的模式架构。
OpenGL是图形硬件的软件接口,它是在SGI等多家世界著名的计算机公司的倡导下,以SGI的GL三维图形库为基础制定的一个通用、共享的、开放式的、性能卓越的三维图形标准。OpenGL在医学成像、地理信息、石油勘探、气候模拟以及娱乐动画上有着广泛应用,它已经成为高性能图形和交互式视景处理的工业标准。
OpenGL不是一种编程语言,而是一种API(应用程序编程接口)。程序员可以使用某种编程语言(如C或C++)编写绘图软件,其中调用了一个或多个OpenGL库函数。作为一种API,OpenGL遵循C语言的调用约定。OpenGL开发资料可参考文献[1]和参考文献[2]。
图形处理器(GPU)原本是处理计算机图形的专用设备,近十年来,由于高清晰度复杂图形实时处理的需求,GPU发展成为高并行度、多线程、多核的处理器。目前,主流GPU的运算能力已超过主流通用CPU,从发展趋势上来看将来差距会越拉越大。为了合理地利用GPU 资源,CUDA(统一计算设备架构)应运而生。CUDA是一种由NVIDIA推出的通用并行计算架构[3],该架构使GPU能够解决复杂的计算问题,并且由于CUDA编程语言基于标准的C语言,从而大大提高了可编程性。
CUDA和OpenGL互操作的基本方式是使用CUDA生成数据,然后使用OpenGL在屏幕上绘制出数据所表示的图形。两者的结合可以通过两种方式来实现:
(1)使用OpenGL的PBO(像素缓冲区对象)。在该方式下,CUDA直接生成像素数据,OpenGL显示这些像素;
(2)使用OpenGL的VBO(顶点缓冲区对象)。在该方式下,CUDA生成顶点网格数据,OpenGL可以根据需要绘制出平滑的表面图或线框图或一系列顶点。
这两种方式的核心都是利用cudaGLMapBufferObject函数将OpenGL的缓冲区映射到CUDA的内存空间上,这样,程序员就可以充分利用CUDA的优点写出性能高的程序在该内存空间上生成数据,这些数据不需要传送,OpenGL可以直接使用。如果不使用CUDA,这些数据需要由CPU来计算产生。一方面,CPU的计算速度通常比GPU慢;另一方面,这些数据需要传送到GPU上以供OpenGL显示使用。鉴于此,当数据量很大时,CUDA和OpenGL的混合使用效果明显。
2 CUDA和OpenGL互操作的过程[4]
CUDA和OpenGL互操作具体步骤如下:
(1)创建窗口及OpenGL运行环境。
(2)设置OpenGL视口和坐标系。要根据绘制的图形是2D还是3D等具体情况设置。(1)和(2)是所有OpenGL程序必需的,这里也没什么特殊之处,需要注意的是,后面的一些功能需要OpenGL 2.0及以上版本支持,所以在这里需要进行版本检查。
(3)创建CUDA环境。可以使用cuGLCtxCreate或cudaGLSetGLDevice来设置CUDA环境。该设置一定要放在其他CUDA的API调用之前。
(4)产生一个或多个OpenGL缓冲区用以和CUDA共享。使用PBO和使用VBO差不多,只是有些函数调用参数不同。以下是具体过程。
GLuint bufferID;
glGenBuffers(1,&bufferID);//产生一个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设置为图像的长度*宽度*4。VBO方式下,parameter1设置为GL_ARRAY_BUFFER,parameter2设置为顶点数*16,因为每个顶点包含3个浮点坐标(x,y,z)和4个颜色字节(RGBA),这样一个顶点包含16 B
(5)用CUDA登记缓冲区。登记可以使用cuGLRegisterBufferObject或
cudaGLRegisterBufferObject,该命令告诉OpenGL和CUDA 驱动程序该缓冲区为二者共同使用。
(6)将OpenGL缓冲区映射到CUDA内存。可以使用cuGLMapBufferObject或cudaGLMapBufferObject,它实际是将CUDA内存的指针指向OpenGL的缓冲区,这样如果只有一个GPU,就不需要数据传递。当映射完成后,OpenGL不能再使用该缓冲区。
(7)使用CUDA往该映射的内存写图像数据。前面的准备工作在这里真正发挥作用了,此时可以调用CUDA的kernel,像使用全局内存一样使用映射了的缓冲区,向其中写数据。
(8)取消OpenGL缓冲区映射。要等前面CUDA的活动完成以后,使用cuGLUnmapBufferObject或cudaGLUnmapBufferObject函数取消映射。
(9)前面的步骤完成以后就可以真正开始绘图了, OpenGL的PBO和VBO的绘图方式不同,分别为以下两个过程。
①如果只是绘制平面图形,需要使用OpenGL的PBO及纹理。
glEnable(GL_TEXTURE_2D); //使纹理可用
glGenTextures(1,&textureID); //生成一个textureID
glBindTexture(GL_TEXTURE_2D,textureID);
//使该纹理成为当前可用纹理
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,Width, Height,0,GL_BGRA,GL_UNSIGNED_BYTE,NULL);
//分配纹理内存。最后的参数设置数据来源,这里设置为NULL,表示数据来自PBO,不是来自主机内存
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN _FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_ FILTER,GL_LINEAR);//必须设置滤波模式,GL_LINEAR允许图形伸缩时线性差值。如果不需要线性差值,可以用GL_TEXTURE_RECTANGLE_ARB代替GL_TEXTURE_2D以提高性能,同时在glTexParameteri()调用里使用GL_NEAREST替换GL_LINEAR
然后就可以指定4个角的纹理坐标,绘制长方形了。
②绘制3D场景,需要使用VBO。
glEnableClientState(GL_VERTEX_ARRAY);
//使顶点和颜色数组可用
glEnableClientState(GL_COLOR_ARRAY);
glVertexPointer(3,GL_FLOAT,16,0);
//设置顶点和颜色指针
glColorPointer(4,GL_UNSIGNED_BYTE,16,12);
glDrawArrays(GL_POINTS,0,numVerticies);
//根据顶点数据绘图,参数可以使用GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES,GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, GL_QUADS,GL_QUAD_STRIP,GL_POLYGON
(10)前后缓存区来回切换,实现动画显示效果。调用SwapBuffers(),缓冲区切换通常会在垂直刷新间隙来处理,因此,可以在控制面板上关掉垂直同步,使得缓冲区切换立刻进行。
3 CUDA和OpenGL互操作性能实例分析
3.1 测试实例
这是一个相对简单的实例,其主要功能是不断地动态改变一个纹理图案中每个像素的颜色并显示。该实例使用了OpenGL的PBO并利用了OpenGL与CUDA互操作方式,纹理图案数据的生成主要由CUDA的kernel函数完成,完整程序及CUDA的kernel函数请参看参考文献[5]。
如果不使用CUDA,整个程序结构变化不大,主要差别是生成该纹理图案的函数在CPU上运行,因而该函数及其调用方式要重写,具体函数如下:
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;
}
}
其中,参数pos表示像素数组,width为图像宽度,height为图像高度,time是每次调用该函数时固定递增的一个值。
3.2 测试结果
上述实例在两种环境中做了实验,CUDA版本都是3.2。测试环境1的主要配置如下:CPU为Intel Core i3-M380,主频为2.53 GHz,GPU为 NVIDIA NVS 3100M,内存为2 GB。测试环境2的主要配置如下:CPU是Intel Core2 duo E7400,主频为2.8 GHz,GPU使用GeForce 9800 GTX+,内存为2 GB。测试时,显示设置的垂直同步要关闭。
测试时设置纹理图像的长和宽都是512,CUDA的线程块为1 024,每个线程块内的线程数为256,在OpenGL的显示回调函数里统计f/s(刷新率),结果如表1所示。
从实验结果可以看出,CUDA与OpenGL结合的方式效果显著,显示速度比不使用CUDA提高了7~8倍。
CUDA是一种较新的方便使用GPU进行通用计算的架构,OpenGL是图形处理的工业标准。两者的互操作充分利用了GPU的特点,因而显得非常自然和合理,实验验证了两者配合使用的效果。该方式为高性能图形图像显示及科学计算可视化提供了良好的模式架构。
下载该资料的人也在下载
下载该资料的人还在阅读
更多 >
- 基于图论原理的互操作性模型改进方法 16次下载
- 与能源收集的互操作性
- 汽车自适应前灯照明概述及设计方案资料下载
- OpenGL常用术语解析
- Qt OpenGL中文使用教程免费下载 38次下载
- OpenGL教程之《OpenGL超级宝典》中文第七版资料免费下载 0次下载
- AMR音频编码器概述及文件格式分析 16次下载
- 基于Cortex-M0微控制器概述及性能分析 6次下载
- icepeak教程概述及工程应用 13次下载
- 基于DSRC的ETC交易互操作规范 74次下载
- 示波器探头概述及应用 0次下载
- TD-SCDMA和GSM系统间互操作研究
- 23G互操作培训(TD技术培训)
- XML和VR技术在GIS中数据互操作设计与实现
- 基于XML的现场总线设备互操作性研究
- 光伏逆变器拓扑概述及关键技术 518次阅读
- 如何使DS34S132 TDM包IC与其他厂商的TDMoP器件互操作 1101次阅读
- 使用CUDA进行编程的要求有哪些 2357次阅读
- 构造具有动态参数的CUDA图表 778次阅读
- CUDA矩阵乘法优化手段详解 1763次阅读
- 如何在OpenCV中实现CUDA加速 4898次阅读
- OpenGL中的深度、深度缓存、深度测试 3611次阅读
- OpenGL绘制图形单元的技巧介绍 2665次阅读
- 初学OpenGL:什么是绘制上下文 2396次阅读
- opengl主要功能介绍 7658次阅读
- 交流充电桩的互操作性测试标准 4083次阅读
- 浅析交流充电桩的互操作性测试标准 3278次阅读
- 概述及汇总ARM的嵌入式操作系统 2951次阅读
- LTE与eHRPD混合组网的互操作关键 4362次阅读
- DS34S132与TDMoP器件互操作的实现 1899次阅读
下载排行
本周
- 1TC358743XBG评估板参考手册
- 1.36 MB | 330次下载 | 免费
- 2开关电源基础知识
- 5.73 MB | 6次下载 | 免费
- 3100W短波放大电路图
- 0.05 MB | 4次下载 | 3 积分
- 4嵌入式linux-聊天程序设计
- 0.60 MB | 3次下载 | 免费
- 5基于FPGA的光纤通信系统的设计与实现
- 0.61 MB | 2次下载 | 免费
- 6基于FPGA的C8051F单片机开发板设计
- 0.70 MB | 2次下载 | 免费
- 751单片机窗帘控制器仿真程序
- 1.93 MB | 2次下载 | 免费
- 8基于51单片机的RGB调色灯程序仿真
- 0.86 MB | 2次下载 | 免费
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 2555集成电路应用800例(新编版)
- 0.00 MB | 33564次下载 | 免费
- 3接口电路图大全
- 未知 | 30323次下载 | 免费
- 4开关电源设计实例指南
- 未知 | 21548次下载 | 免费
- 5电气工程师手册免费下载(新编第二版pdf电子书)
- 0.00 MB | 15349次下载 | 免费
- 6数字电路基础pdf(下载)
- 未知 | 13750次下载 | 免费
- 7电子制作实例集锦 下载
- 未知 | 8113次下载 | 免费
- 8《LED驱动电路设计》 温德尔著
- 0.00 MB | 6653次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935054次下载 | 免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB | 537796次下载 | 免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 | 420026次下载 | 免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 5Altium DXP2002下载入口
- 未知 | 233046次下载 | 免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 | 191185次下载 | 免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M | 183278次下载 | 免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 | 138040次下载 | 免费
评论
查看更多