第1章 绪论-GPU编程与CG语言

2022-11-05 20:49:43 浏览数 (1)

面纱掩盖了过去、现在和将来,历史学家的使命是发现它现在是什么,而不是过去是什么。

------Henry David Thoreau

1.1 Programmable Graphics Processing Unit 发展历程

Programmable Graphics Processing Unit(GPU),即可编程图形处理单元,通常也称之为可编程图形硬件。

GPU 概念在20 世纪70 年代末和80 年代初被提出,使用单片集成电路(monolithic)作为图形芯片,此时的GPU 已经被用于视频游戏和动画方面,它能够很快地进行几张图片的合成(仅限于此)。在20 世纪80 年代末到90 年代初这段时间内,基于数字信号处理芯片(digital signal processor chip)的GPU 被研发出来,与前代相比速度更快、功能更强,当然价格是非常的昂贵。在1991年,S3 Graphics 公司研制出第一个单芯片2D 加速器,到了1995 年,主流的PC图形芯片厂商都在自己的芯片上增加了对2D 加速器的支持。与此同时,固定功能的视窗加速器(fixed-function Windows accelerators)由于其高昂的价格而慢慢退出PC 市场。

1998 年NVIDIA 公司宣布modern GPU 的研发成功,标志着GPU 研发的历史性突破成为现实。通常将20 世纪70 年代末到1998 年的这一段时间称之为pre-GPU 时期,而自1998 年往后的GPU 称之为modern GPU。在pre-GPU 时期,一些图形厂商,如SGI、Evans & Sutherland,都研发了各自的GPU,这些GPU在现在并没有被淘汰,依然在持续改进和被广泛的使用,当然价格也是非常的高昂。

modern GPU 使用晶体管(transistors)进行计算,在微芯片(microchip)中,GPU 所使用的晶体管已经远远超过CPU。例如,Intel 在2.4GHz 的Pentium IV上使用5 千5 百万(55 million)个晶体管;而NVIDIA 在GeForce FX GPU 上使用超过1 亿2 千5 百万(125 million)个晶体管,在NVIDDIA 7800 GXT 上的晶体管达到3 亿2 百万(302 million)个。

回顾Modern GPU 的发展历史,自1998 年后可以分为4 个阶段。NVIDIA于1998 年宣布Modern GPU 研发成功,这标志着第一代Modern GPU 的诞生,第一代Modern GPU 包括NVIDIA TNT2,ATI 的Rage 和3Dfx 的Voodoo3。这些GPU 可以独立于CPU 进行像素缓存区的更新,并可以光栅化三角面片以及进行纹理操作,但是缺乏三维顶点的空间坐标变换能力,这意味着“必须依赖于GPU执行顶点坐标变换的计算”。这一时期的GPU 功能非常有限,只能用于纹理组合的数学计算或者像素颜色值的计算。

从1999 到2000 年,是第二代modern GPU 的发展时期。这一时期的GPU可以进行三维坐标转换和光照计算(3D Object Transformation and Lighting,T&L),并且OpenGL 和DirectX7 都提供了开发接口,支持应用程序使用基于硬件的坐标变换。这是一个非常重要的时期,在此之前只有高级工作站(workstation)的图形硬件才支持快速的顶点变换。同时,这一阶段的GPU 对于纹理的操作也扩展到了立方体纹理(cube map)。NVIDIA 的GeForce256,GeForce MAX,ATI 的Radeon 7500 等都是在这一阶段研发的。

2001 年是第三代modern GPU 的发展时期,这一时期研发的GPU 提供vertexprogrammability(顶点编程能力),如GeForce 3,GeForce 4Ti,ATI 的8500 等。这些GPU 允许应用程序指定一个序列的指令进行顶点操作控制(GPU 编程的本

质!),这同样是一个具有开创意义的时期,这一时期确立的GPU 编程思想一直延续到2009 年的今天,不但深入到工程领域帮助改善人类日常生活(医疗、地质勘探、游戏、电影等),而且开创或延伸了计算机科学的诸多研究领域 (体绘制、光照模拟、人群动画、通用计算等)。同时,Direct8 和OpenGL 都本着与时俱进的精神,提供了支持vertex programmability 的扩展。不过,这一时期的GPU 还不支持像素级的编程能力,即fragment programmability(片段编程能力),在第四代modern GPU 时期,我们将迎来同时支持vertex programmability 和fragment programmability 的GPU。

第四代modern GPU 的发展时期从2002 年末到2003 年。NVIDIA 的GeForce FX 和ATI Radeon 9700 同时在市场的舞台上闪亮登场,这两种GPU 都支持vertex programmability 和fragment programmability。同时DirectX 和OpenGL 也扩展了自身的API,用以支持vertex programmability 和fragment programmability。

自2003年起,可编程图形硬件正式诞生,并且由于DirectX 和OpenGL 锲而不舍的追赶潮流,导致基于图形硬件的编程技术,简称GPU 编程,也宣告诞生。恭喜GeForce和ATI 的硬件研发人员,你们终于可以歇口气了,不用较着劲地出显卡了,同

时也恭喜DirectX 和OpenGL 的研发人员,你们也可以休息下了,不用斗鸡一般的工作了,最后恭喜广大工作在图形图像领域的程序员,你们可以继续学而不倦。

目前最新的可编程图形硬件已经具备了如下功能:

1. 支持 vertex programmability 和fragment programmability;

2. 支持 IEEE32 位浮点运算;

3. 支持 4 元向量,4 阶矩阵计算;

4. 提供分支指令,支持循环控制语句;

5. 具有高带宽的内存传输能力(>27.1GB/s);

6. 支持 1D、2D、3D 纹理像素查询和使用,且速度极快;

7. 支持绘制到纹理功能(Render to Texture,RTT)。

关于GPU 发展历史的相关数据参考了Feng Liu 的“Platform Independent Real-time X3D Shaders and Their Applications in Bioinformatics Visualization”一文

1.2 GPU VS CPU

从上节阐述了GPU 的发展历史,那么为什么在CPU 之外要发展GPU?GPU 的vertex programmability 和fragment programmability 究竟在何处有着怎样的优势?引用在文献【2】第6 页的一段话为:

Modern GPUs implement a number of graphics primitive operations in a way that make running them much faster than drawing directly to the screen with the host CPU. They are efficient at manipulating and displaying computer graphics, and their highly parallel structure makes them more effective than typical CPUs for a range of complex algorithms.

这段话的意思是,由于GPU 具有高并行结构(highly parallel structure),所以GPU 在处理图形数据和复杂算法方面拥有比CPU 更高的效率。图 1 GPU VS CPU 展示了GPU 和CPU 在结构上的差异,CPU 大部分面积为控制器和寄存器,与之相比,GPU 拥有更多的ALU(Arithmetic Logic Unit,逻辑运算单元)用于数据处理,而非数据高速缓存和流控制,这样的结构适合对密集型数据进行并行处理。CPU 执行计算任务时,一个时刻只处理一个数据,不存在真正意义上的并行(请回忆OS 教程上的时间片轮转算法),而GPU 具有多个处理器核,在一个时刻可以并行处理多个数据。

GPU 采用流式并行计算模式,可对每个数据进行独立的并行计算,所谓“对数据进行独立计算”,即,流内任意元素的计算不依赖于其它同类型数据,例如,计算一个顶点的世界位置坐标,不依赖于其他顶点的位置。而所谓“并行计算”是指“多个数据可以同时被使用,多个数据并行运算的时间和1 个数据单独执行的时间是一样的”。图 2 中代码目的是提取2D 图像上每个像素点的颜色值,在CPU 上运算的C 代码通过循环语句依次遍历像素;而在GPU 上,则只需要一条语句就足够。

可能有人会问道:既然GPU 在数据处理速度方面远胜CPU,为什么不用GPU 完全取代CPU 呢?实际上,关于GPU 取代CPU 的论调时有出现,但是作者本人并不同意这种观点,因为GPU 在许多方面与CPU 相比尚有不如。

首先,虽然GPU 采用数据并行处理方式极大加快了运算速度,但正是由于“任意一个元素的计算不依赖于其它同类型数据”,导致“需要知道数据之间相关性的”算法,在GPU 上难以得到实现(但在CPU 上则可以方便的实现),一个典型的例子是射线与不规则物体的求交运算。

此外,GPU 在控制流方面弱于CPU,在图中可以看到,GPU 中的控制器少于CPU,而控制器的主要功能是取指令,并指出下一条指令在内存中的位置,控制和协调计算机的各个部件有条不紊地工作。 在早期的OpenGL fp2.0,fp3.0以及DirectX 的ps_4_0 之前的profile 版本都不支持或不完全支持循环控制流语句(目前在软硬件方面都已得到改进)。由于GPU 编程完全依赖于图形硬件,故而较早版本的GPU 并不支持一些常用的编程需要,而现在很多个人电脑或者公司的电脑的更新换代并没有那么快(考虑个人电脑的使用寿命在4-6 年,所以在2012 之后,旧式显卡的更新换代会基本结束),这也制约了GPU 编程技术的使用。

最后进行GPU 编程必须掌握计算机图像学相关知识,以及图形处理API,入门门槛较高,学习周期较长,尤其国内关于GPU 编程的资料较为匮乏,这些都导致了学习的难度。在早期,GPU 编程只能使用汇编语言,开发难度高、效率低,不过,随着高级Shader language 的兴起,在GPU 上编程已经容易多了。

1.3 国内外研究现状

基于GPU 的科学可视化计算(Visualization in Scientific Computing),在研究和工程运用上都取得了卓越的成果。由于科学可视化计算处理的数据量极大(人体CT、地质勘探、气象数据、流体力学等),仅仅基于CPU 进行计算完全不能满足实时性要求,而在GPU 上进行计算则可以在效率上达到质的突破,许多在CPU 上非常耗时的算法,如体绘制中的光线投射算法,都可以成功移植到GPU 上,所以基于GPU 的科学可视化研究目前已经成为主流。

近年来,基于GPU进行通用计算的研究逐渐成为热点,被称之为GPGPU(General-Purpose Computing on Graphics Processing Units,也被称为GPGP,或GP2),很多数值计算等通用算法都已经在GPU上得到了实现,并有不俗的性能表现,目前,线性代数(linear algebra)【kruger and westermann 2003】,物理仿真(physical simulation)【Harris et al. 2003】和光线跟踪算法(ray tracer)【Purcell et al.2002; Carr et al. 2002】都已经成功的移植到GPU上。在国内,中国科学院计

算技术研究所进行了基于GPU的串匹配算法的实现【29】。关于GPGPU的更多知识点可以参阅网站http://gpgpu.org/

旨在降低GPU 编程难度,设计基于GPU 的高级程序语言的研究同样进行的如火如荼。2004 年,斯坦福大学研究的BROOKGPU 项目设计了一个实时的编译器,编程人员不需掌握图形学知识,只需掌握与C 语言类似的流处理语言BROOK,即可进行基于GPU 的通用编程开发。目前BROOKGPU 已经在AMD公司进行深入研发。国内浙江大学计算机学院针对高级着色语言的编译系统【30】,以及可编程图形硬件的加速等技术进行了研究。

1.4 本书主要内容和结构

本书旨在引导初级GPU 学习者步入GPU 编程的大堂,并普及一些在国内资料中较少见到的GPU 算法,例如光照渲染中的bank BRDF,以及体绘制中的光线投射(ray-casting)算法。在GPU 编程方面有一定基础的同学,可以将本书的一些观点作为参考。

本书并非网络小说,也非“立意新奇,饰以深奥文字,佐以华丽图表的国际论文”,而是作者有感于国内GPU 研究现状堪忧,而抛砖引玉之作,故而以通俗的语言说出自己明白的事情,是我写作的原则。

本书的框架划分,也是希望可以循序渐进、深入浅出的让大家了解GPU 世界。

本书由四大部分组成,第一部分阐述“GPU 的发展历史、GPU 和CPU 的优劣比较、GPU 的图形绘制管线,以及在GPU 上使用的shader language”,这一部分由3 章组成,尤为重要的是第二章“GPU 图形绘制管线”和第三章“Shader Language”。GPU 图形绘制管线描述了GPU 的工作原理,这部分知识是GPU 编程的铸基之石;而Shader Language 章节阐述了vertex program(顶点编程)和fragment program(片段编程)在GPU 管线中的位置、作用和工作机制。

本书的第二部分讲述Cg 语言的使用方法,由五章组成(第四章到第八章)。这部分的知识以NVIDIA 出版的The Cg Tutorial The Definitive Guide to Programmable Real-Time Graphics 和Cg ToolKit User’s Manual 作为基础,并加入了作者本人在实践中的一些总结。The Cg Tutorial The Definitive Guide to Programmable Real-Time Graphics 已经有了中文版本,名为《Cg 教程_可编程实时图形权威指南》。Cg ToolKit User’s Manual 一书,目前还没有中文版(却存在日文版!),此书在语法的阐述

上胜于前者,英文好的读者可以尝试着阅读一下。

本书的第三部分阐述光照模型知识,由三章组成(第九章到第十一章)。这部分首先以较为简单的光照模型作为GPU 编程的实践理论,让读者从实际编程中学习Cg 语言的使用方法,然后介绍较为高级的BRDF 光照模型,以及透明光照模型。BRDF 光照模型的知识点在国内的书籍中并不常见,实现代码更是没有看到过,希望这一章节对这方面的研究人员略有帮助。

本书的第四部分针对投影纹理映射和阴影算法进行讲解,由两章组成(第十二章和第十三章),这部分的知识希望可以引起大家足够的重视,因为投影纹理映射和深度值的使用方法,都是既基础又重要的知识,在更高一级的前沿研究课题(如体绘制、软阴影渲染)中常被使用。

本书的第五部分阐述了体绘制知识点以及基于GPU 的光线投射算法。体绘制是我花费研究时间较多的地方,不但因为技术本身较为复杂,而且因为体数据收集和使用较为困难。体绘制技术的中文资料少之又少,优秀硕博士论文库上一般也是人云亦云,可能高手都比较含蓄,所以我姑且写出两章,如有可用之处,

则可慰我心,如不堪入目,聊供方家一笑。

0 人点赞