如何通过编程将GPU用于通用计算任务

2009-10-9 作者: Ian Buck 来源: 互联网

关键字: GPU 通用计算 

  随着现代图形处理器(GPU)可编程能力及性能的提高,应用开发商们一直希望图形硬件可以解决以前只有通用CPU才能完成的高密集计算任务。尽管利用通用GPU进行计算很有发展前景,但传统图像应用编程接口仍然将GPU抽象成一个包括纹理、三角形和像素在内的图像绘制器。寻找一种能够使用这些基本元素的映射算法并不是一项简单的操作,即便对最先进的图形开发商而言也是如此。

  幸运的是,基于GPU的计算从概念上讲很容易理解,并且现有多种高级语言和软件工具可以简化GPU的编程工作。但是,开发商必须首先了解GPU在图像绘制过程中是如何工作的,然后才能确定可用于计算的各个组件。

  在绘制图像时,GPU首先接收宿主系统以三角顶点形式发送的几何数据。这些顶点数据由一个可编程的顶点处理器进行处理,该处理器可以完成几何变换、亮度计算等任何三角形计算。接下来,这些三角形由一个固定功能的光栅器转换成显示在屏幕上的单独“碎片(fragment)”。在屏幕显示之前,每个碎片都通过一个可编程的碎片处理器计算最终颜色值。


图1: 执行两向量相加的简单Brook代码示例

  计算碎片颜色的运算一般包括集合向量数学操作以及从“纹理”中提取存储数据,“纹理”是一种存储表面材料颜色的位图。最终绘制的场景可以显示在输出设备上,或是从GPU的存储器重新复制到宿主处理器中。

  可编程顶点处理器和碎片处理器提供了许多相同的功能和指令集。但是,大部分GPU编程人员只将碎片处理器用于通用计算任务,因为它通常提供更优的性能,而且可以直接输出到存储器。

  利用碎片处理器进行计算的一个简单例子是对两个向量进行相加。首先,我们发布一个大三角形,其所包含的碎片数量和向量大小(容纳的元素)相同。产生的碎片通过碎片处理器进行处理,处理器以单指令多数据(SIMD)的并行方式执行代码。进行向量相加的代码从存储器中提取两个待加元素,并根据碎片的位置进行向量相加,同时为结果分配输出颜色。输出存储器保存了向量和,这个值在下一步计算中可以被任意使用。

  可编程碎片处理器的ISA类似于DSP或Pentium SSE的指令集,由四路SIMD指令和寄存器组成。这些指令包括标准数·运算、存储器提取指令和几个专用图形指令。

  GPU与DSP的比较

  GPU在几个主要方面有别于DSP架构。其所有计算均使用浮点算法,而且目前还没有位或整数运算指令。此外,由于GPU专为图像处理设计,因此存储系统实际上是一个二维的分段存储空间,包括一个区段号(从中读取图像)和二维地址(图像中的X、Y坐标)。

  此外,没有任何间接写指令。输出写地址由光栅处理器确定,而且不能由程序改变。这对于自然分布在存储器之中的算法而言是极大的挑战。最后一点,不同碎片的处理过程间不允许通信。实际上,碎片处理器是一个SIMD数据并行执行单元,在所有碎片中独立执行代码。

  尽管有上述约束,但是GPU还是可以有效地执行多种运算,从线性代数和信号处理到数值仿真。虽然概念简单,但新用户在使用GPU计算时还是会感到迷惑,因为GPU需要专有的图形知识。这种情况下,一些软件工具可以提供帮助。两种高级描影语言CG和HLSL能够让用户编写类似C的代码,随后编译成碎片程序汇编语言。这些语言编译器可以从Nvidia和微软公司的网站免费下载。尽管这些语言大大简化了描影汇编代码的编写,但实际应用时仍然必须使用图形API来建立并发布计算任务。

  Brook是专为GPU计算设计,且不需要图形知识的高级语言。因此对第一次使用GPU进行开发的工作人员而言,它可以算是一个很好的起点。Brook是C语言的延伸,整合了可以直接映射到GPU的简单数据并行编程构造。

  经GPU存储和操作的数据被形象地比喻成“流”(stream),类似于标准C中的数组。核心(Kernel)是在流上操作的函数。在一系列输入流上调用一个核心函数意味着在流元素上实施了隐含的循环,即对每一个流元素调用核心体。Brook还提供了约简机制,例如对一个流中所有的元素进行和、最大值或乘积计算。

  Brook编译器是一个源到源的编译器,能够把用户的核心代码映射成碎片汇编语言,并生成C++短代码,从而链接到大型应用中。这允许用户只把应用中的性能关键部分输入Brook。Brook还完全隐藏了图形API的所有细节,并把GPU中类似二维存储器系统这样许多用户不熟悉的部分进行了虚拟化处理。

  用Brook编写的应用程序包括线性代数子程序、快速傅立叶转换、光线追踪和图像处理。Brook的编译器和实时运行环境可以从http://brook网站上免费获取。

  sourceforge.net网站也为许多此类应用提供资源。利用ATI的X800XT和Nvidia的GeForce 6800 Ultra型GPU,在相同高速缓存、SSE汇编优化Pentium 4执行条件下,许多此类应用的速度提升高达7倍之多。

  对GPU计算感兴趣的用户努力将算法映射到图形基本元素。类似Brook这样的高级编程语言的问世使编程新手也能够很容易就掌握GPU的性能优势。访问GPU计算功能的便利性也使得GPU的演变将继续下去,不仅仅作为绘制引擎,而是会成为个人电脑的主要计算引擎。



责任编辑:熊东旭