在GPU出现以前,显卡和CPU的关系有点像“主仆”,简单地说这时的显卡就是画笔,根据各种有CPU发出的指令和数据进行着色,材质的填充、渲染、输出等。
较早的娱乐用的3D显卡又称“3D加速卡”,由于大部分坐标处理的工作及光影特效需要由CPU亲自处理,占用了CPU太多的运算时间,从而造成整体画面不能非常流畅地表现出来。
那么,GPU的工作原理是什么?
简单的说GPU就是能够从硬件上支持T&L(Transform and Lighting,多边形转换与光源处理)的显示芯片,因为T&L是3D渲染中的一个重要部分,其作用是计算多边形的3D位置和处理动态光线效果,也可以称为“几何处理”。一个好的T&L单元,可以提供细致的3D物体和高级的光线特效;只不过大多数PC中,T&L的大部分运算是交由CPU处理的(这就也就是所谓的软件T&L),由于CPU的任务繁多,除了T&L之外,还要做内存管理、输入响应等非3D图形处理工作,因此在实际运算的时候性能会大打折扣,常常出现显卡等待CPU数据的情况,其运算速度远跟不上今天复杂三维游戏的要求。
即使CPU的工作频率超过 1GHz或更高,对它的帮助也不大,由于这是PC本身设计造成的问题,与CPU的速度无太大关系。
GPU图形处理,可以大致分成 5 个步骤,如下图箭头的部分。
分别为 vertex shader、primitive processing、rasterisation、fragment shader、testing and blending。
第一步,vertex shader。是将三维空间中数个(x,y,z)顶点放进 GPU 中。
在这一步骤中,电脑会在内部模拟出一个三维空间,并将这些顶点放置在这一空间内部。接着,投影在同一平面上,也是我们将看到的画面。同时,存下各点距离投影面的垂直距离,以便做后续的处理。
这个过程就像是本地球观看星星一般。地球的天空,就像是一个投影面,所有的星星,不管远近皆投影在同一面上。本地球的我们,抬起头来观看星星,分不出星星的远近,只能分辨出亮度。
GPU 所投影出的结果,和这个情况类似。
从地球所看到的星空,星星就像是投影到一球面上,除非使用特别的仪器,不然分不出星星和地球的距离
第二步,primitive processing。是将相关的点链接在一起,以形成图形。在一开始输入数个顶点进入 GPU 时,程序会特别注记哪些点是需要组合在一起,以形成一线或面。就像是看星座的时候一样,将相关连的星星连起来,形成特定的图案。
第三步,rasterisation。因为电脑的屏幕是由一个又一个的像素组成,因此,需要将一条连续的直线,使用绘图的演算法,以方格绘出该直线。图形也是以此方式,先标出边线,再用方格填满整个平面。
第四步,fragment shader。将格点化后的图形着上颜色。所需着上的颜色也是于输入时便被注记。在游玩游戏时,这一步相当耗费 GPU 的计算资源,因为光影的效果、物体表面材质皆是在这一步进行,这些计算决定着游戏画面的精细程度。因此在游玩游戏时,调高游戏画面品质大幅增加这一步的计算负担,降低游戏品质。
将一个三角形,用方格呈现近似原始图案,并着上颜色。一块又一块的方格,就是显示器上的像素
最后一步,testing and blending。便是将第一步所获得的投影垂直距离取出,和第四步的结果一同做最后处理。在去除被会被其他较近距离的物体挡住的物体后,让剩下的图形放进 GPU 的输出内存。之后,结果便会被送到电脑屏幕显示。
GPU与DSP区别
GPU在几个主要方面有别于DSP(Digital Signal Processing,简称DSP(数字信号处理)架构。其所有计算均使用浮点算法,而且目前还没有位或整数运算指令。此外,由于GPU专为图像处理设计,因此存储系统实际上是一个二维的分段存储空间,包括一个区段号(从中读取图像)和二维地址(图像中的X、Y坐标)。此外,没有任何间接写指令。输出写地址由光栅处理器确定,而且不能由程序改变。这对于自然分布在存储器之中的算法而言是极大的挑战。最后一点,不同碎片的处理过程间不允许通信。实际上,碎片处理器是一个SIMD数据并行执行单元,在所有碎片中独立执行代码。
尽管有上述约束,但是GPU还是可以有效地执行多种运算,从线性代数和信号处理到数值仿真。虽然概念简单,但新用户在使用GPU计算时还是会感到迷惑,因为GPU需要专有的图形知识。这种情况下,一些软件工具可以提供帮助。两种高级描影语言CG和HLSL能够让用户编写类似C的代码,随后编译成碎片程序汇编语言。Brook是专为GPU计算设计,且不需要图形知识的高级语言。因此对第一次使用GPU进行开发的工作人员而言,它可以算是一个很好的起点。
Brook是C语言的延伸,整合了可以直接映射到 GPU的简单数据并行编程构造。经GPU存储和操作的数据被形象地比喻成“流”(stream),类似于标准C中的数组。核心(Kernel)是在流上操作的函数。在一系列输入流上调用一个核心函数意味着在流元素上实施了隐含的循环,即对每一个流元素调用核心体。Brook还提供了约简机制,例如对一个流中所有的元素进行和、最大值或乘积计算。
Brook还完全隐藏了图形API的所有细节,并把GPU中类似二维存储器系统这样许多用户不熟悉的部分进行了虚拟化处理。用Brook编写的应用程序包括线性代数子程序、快速傅立叶转换、光线追踪和图像处理。利用ATI的X800XT和Nvidia的GeForce 6800 Ultra型GPU,在相同高速缓存、SSE汇编优化Pentium 4执行条件下,许多此类应用的速度提升高达7倍之多。
对GPU计算感兴趣的用户努力将算法映射到图形基本元素。类似Brook这样的高级编程语言的问世使编程新手也能够很容易就掌握GPU的性能优势。访问GPU计算功能的便利性也使得GPU的演变将继续下去,不仅仅作为绘制引擎,而是会成为个人电脑的主要计算引擎。
,