基本信息
- 原书名:The CUDA Handbook: A Comprehensive Guide to GPU Programming

【插图】

编辑推荐
英伟达公司CUDA首席架构师Nicholas Wilt亲笔撰写,英伟达中国首批CUDA官方认证工程师翻译;全面而系统地讲解CUDA编程的各方面知识,深度解析CUDA各种优化技术,包含大量实用代码示例,是深入掌握主流异构并行计算技术的权威指南。
内容简介
计算机书籍
《CUDA专家手册:GPU编程权威指南》由英伟达公司CUDA首席架构师NicholasWilt亲笔撰写,深度解析GPU的架构、系统软件、编程环境,以及CUDA编程各方面的知识和各种优化技术,包含大量实用代码示例,是并行程序开发领域最有影响力的著作之一。
《CUDA专家手册:GPU编程权威指南》分为三部分,共15章。第一部分(第1~4章)介绍CUDA开发的基础知识、硬件/软件架构和软件环境;第二部分(第5~10章)详细解析CUDA开发的各个方面,包括内存、流与事件、内核执行、流处理器簇、多GPU编程和纹理操作;第三部分(第11~15章)利用多个实例,深入分析流式负载、归约算法、扫描算法、N-体问题和图像处理的归一化相关系数计算,介绍如何应用各种优化技术。
作译者
苏统华,博士,英伟达中国首批CUDA官方认证工程师,哈尔滨工业大学英伟达教学中心负责人,主要研究领域包括大规模并行计算、模式识别、物联网智能信息处理、智能媒体交互与计算等。2013年,其所开发的CUDA识别算法,在文档分析和识别国际会议(ICDAR’2013)上获得手写汉字识别竞赛的双料冠军。另外,他在手写汉字识别领域建立了里程碑式工作,论文他引约300次;他所建立的HIT-MW库,为全世界100多家科研院所采用;目前负责国家自然科学基金项目2项。著有英文专著《Chinese Handwriting Recognition:An Algorithmic Perspective》(德国施普林格出版社),CUDA*II关译作2本(机械工业出版社)。现任哈尔滨工业大学软件学院高级讲师、硕士生导师。
马培军,教授、博土生导师、哈尔滨工业大学软件学院院长。20余年行业经验,经验十分丰富。曾游学日本,获日本琦玉大学计算机应用专业硕士和博士学位,并在日本佳能集团工作多年。主要研究方向包括:航天软件工程、智能信息处理与信息融合、图像处理与识别、嵌入式系统仿真等。主持或参加多项国家自然科学基金、国家863项目、国防基础科研和国际合作项目,获省部级二等奖2项,软件著作权3项,申请发明专利2项,在国内外期刊和会议上发表论文100余篇。现任哈尔滨工业大学计算机科学与技术学院航天软件工程研究中心主任、中国宇航学会计算机应用专业委员会委员、日本计算机服务公司IT教育顾问。
目录
中文版序
推荐序
译者序
前言
第一部分基础知识
第1章简介2
1.1方法4
1.2代码4
1.2.1验证型代码5
1.2.2演示型代码5
1.2.3探究型代码5
1.3资源5
1.3.1开源代码5
1.3.2CUDA专家手册库(chLib)6
1.3.3编码风格6
1.3.4CUDA SDK6
1.4结构6
第2章硬件架构8
2.1CPU配置8
译者序
本书为深度优化CUDA程序性能提供了全方位的指导。乍看起来,本书只是一本参考手册。不错,它确实基于英伟达官方CUDA参考手册的很多内容。然而它又不单单是一本传统意义上的手册,它比较全面地介绍了CUDA的高级编程特性,是该领域难得的权威参考书。全书高屋建瓴而又简明扼要。作者从繁芜的文献资源中提炼并予以升华形成独到的总结。对很多复杂的主题,能够举重若轻;在很多关键的问题上,给大家一种豁然开朗之感。很多精辟论述是市面上任何一本GPU书籍所缺失的。译者在阅读本书时,亦为作者在技术和语言上的双重驾驭能力所折服。
本书作者Wilt从事GPU底层开发逾20年,功力深厚。在CUDA诞生之前,从事了8年Direct3D的开发;在英伟达供职的8年间,参与了CUDA的开发,实现了多数CUDA的抽象机制;目前转战亚马逊,从事GPU云产品的开发。作者根据自身多年的经验积淀,对CUDA编程模型进行了深入浅出的介绍,并结合四个典型应用场合,完美诠释了它们的具体用法和优化过程。得益于本书的启发,我们研究组基于CUDA的文字识别算法得到194X的加速,使我们能够抢在其他竞争者之前,取得2013年手写汉字识别竞赛的两项冠军。很多时候,速度意味着胜利!
本书的技术深度和欲覆盖的读者层面,决定了本书翻译工作的难度。本书的翻译持续了一年之久,期间得到过很多人的帮助。除了本书列出的四位译者外,还有5位译者参与了本书的初稿翻译:韦振良参与了第2章和第7章,李硕参与了第4章和第6章,李松泽参与了第10章,孙黎参与了第14章,胡光龙参与了第15章。其中,与光龙是在参加第一届英伟达认证工程师的考试途中相遇,我们一起迷了路、一起考试过关、一起分享CUDA技术点滴,又一起在本书的翻译期间进行合作,谢谢光龙的友谊和无私帮助。在本书译文统稿之后,我们努力想找到合适的CUDA专家为我们把关。如果没有英伟达公司的侯宇涛经理,这可能会变成无法完成的任务。感谢侯经理为我们推荐了最优秀的技术审校专家,帮我们邀请了高性能计算开发技术中国区经理王鹏博士为本译作写序并选定本译作在全国推广。感谢英伟达高性能计算部门的专家王泽寰和赖俊杰,即使在春节期间,他们也在为改进本书的译稿质量而绞尽脑汁。如果没有泽寰和赖经理的审校,原书的内容恐难以尽可能原汁原味地展现。王鹏经理特意为本书作了推荐序,其中浓缩了他多年的CUDA性能优化经验;非常感谢,您真的做到了“读者最需要什么,您就写点什么”的宗旨。最后,还要特别感谢机械工业出版社的编辑团队,他们做了大量卓有成效的工作,是本书的幕后英雄。
本书的翻译,还得到了多项项目的资助,在此一并致谢。国家自然科学基金(资助号:61203260)、黑龙江省科研启动基金(资助号:LBH-Q13066)、哈尔滨工业大学科研创新基金(资助号:HITNSRIF2015083)对本书的翻译提供了部分资助。另外,哈尔滨工业大学创新实验课《CUDA高性能并行程序设计》、黑龙江省教育厅高等教育教学改革项目(资助号:JG2013010224)、哈尔滨工业大学研究生教育教学改革研究项目(资助号:JCJS-201309)也对本书的翻译提供了大力支持。
很多时候,翻译技术书籍是件吃力不讨好的事情。即使是最有资格的译者,也一定无法免受被读者指责的境遇。对读者负责,对CUDA教学推广负责,是我和我的团队始终铭记的准则。我们很享受翻译本书的过程,也很愿意承担因我们的水平和疏忽所招致的批评。文中可能存在的任何翻译问题,都是我们的责任。真诚地希望读者朋友不吝赐教,欢迎大家的任何意见:cudabook@gmail.com。
并行计算是计算的未来。希望本书的翻译可以帮助你让并行计算与大数据成功联姻,并享用由此带来的前所未有的新鲜体验。愿你的CUDA探索之旅愉快!
苏统华
哈尔滨工业大学软件学院
前言
我在审校《CUDA by Example》时,惊诧于该书内容的浅显。它假设读者是零基础,试图描述从内存类型及其实际应用到图形互操作性,甚至到原子操作等方方面面的内容。它是很优秀的CUDA入门书籍,但也只能做到泛泛而谈。对于更深层次的知识,例如,平台的工作机理、GPU的硬件结构、编译器驱动程序nvcc以及以前缀求和(“扫描”)为代表的基本并行算法,则鲜有涉及。
本书考虑到不同基础的读者,旨在帮助CUDA新手进阶中级水平,同时帮助中级程序员继续提升他们的水平到一个新高度。对于入门性质的书籍,最好从头到尾阅读,而对本书则可以根据需要选读。如果你正准备建立支持CUDA的新平台并在上面进行编程,建议你精读第2章。如果你正纳闷你的应用程序是否将受益于CUDA流带来的额外并发性,你应该查看第6章。其他的章节分别提供了软件架构、GPU的纹理操作和流处理器簇等GPU子系统的详细描述,还有依据不同数据存取模式和在并行算法领域的重要程度而精心挑选的应用案例。尽管不同章之间难免存在交互引用,但每一章的内容都是相对独立的。
本书将披露包括CUDA 5.0在内的最新技术。最近几年,CUDA和它的目标平台得到了长足发展。在《CUDA by Example》出版之际,GeForce GTX 280(GT200)才刚刚面世。迄今,CUDA硬件已历经两代演变。因此,本书除了在如映射锁页内存(mapped pinned memory)的现有特性上不吝笔墨外,还特别关注CUDA支持的新特性,像费米架构的ballot、开普勒架构的shuffle、64位和统一虚拟寻址特性以及动态并行(dynamic parallelism)等。此外,本书还将讨论最近的平台进展,例如英特尔沙桥(Sandy Bridge)CPU上集成的PCIe总线控制器。
尊敬的读者,你可以全篇通读本书,也可以把它放于电脑边随时查阅。但不管怎样,我真诚地希冀你能从中得到乐趣,如同我执笔分享时一样快意。
致谢
借此机会,感谢英伟达公司的朋友们。他们耐心地为我释疑、检视我的作品并反馈建设性意见。特别的谢意送给Mark Harris、Norbert Juffa和Lars Nyland。
本书的审校者在成稿之前审阅了本书,他们付出了大量时间,提供的宝贵意见提高了本书的质量和清晰性,保证了技术的正确性。在此,特别感谢Andre Brodtkorb、Scott Le Grand、Allan MacKinnon、Romelia Salomon-Ferrer和Patrik Tennberg的反馈意见。
本书的写作过程历经了重重困难,如果没有编辑Peter Gordon的超凡耐心和支持,很难最终呈现给大家。Peter的助手Kim Boedigheimer为本项目的顺利完成做了大量工作,帮助我设定了项目的各种专业标准。对她在征求、协调评审意见以及在本书成稿之后把本书上传到Safari网站的整个过程中付出的努力,表示特别感谢。
在本书的写作过程中,我的妻子Robin和我的儿子Benjamin、Samuel和Gregory一直对我支持有加,谢谢他们。
序言
得知本书正在被翻译成瑰丽的汉字,我难抑内心的激动。众核计算对中国读者来说并不陌生。中国已经建造了多个最快的超级计算机,其中很多采用了CUDA技术。我们耳熟能详的天河-1A,建成于2010年10月,配备了7168片特斯拉(Tesla)M2050型号的GPU。本书第4章介绍的亚马逊cg1.4xlarge实例,也采用了同种型号的GPU。天河-1A曾雄霸世界超级计算机500强榜首逾半年之久,即使现在,它仍排在世界最快计算机的前12位。它惊人的高速度源于中国自主研发的互联技术把来自英特尔和英伟达的硬件高效地集成起来了。
当然,CUDA并非只能应用于超级计算机。GPU的出货量巨大,相较其他众核计算技术,它们具有价格优势。因此,支持CUDA的GPU很容易用来搭建经济的计算平台,这对于并行程序设计的教育和教学意义重大。
CUDA技术仍在迅猛发展着。我敢断定,它将继续在并行计算的大潮中扮演重要角色。本书向大家展示了CUDA的内部工作机制,此中译本将推动CUDA在中国的普及和发展。
最后,向承担本书翻译工作的苏博士及其团队,致以诚挚谢意!感谢他们孜孜不倦地致力于GPU计算的推广,特别是把本书带给广大中国读者。
Nicholas Wilt
推荐序
自CPU单核性能在2004年左右停止提升后,功耗的限制及大量并行应用本身的特点决定了多核(CPU)加众核(GPU)的异构架构成为从最快的超级计算机到手机等移动设备上计算芯片的主流架构。所以如果想在现在和未来的任何计算设备上写出性能具有竞争力的程序,所有的开发者都需要学习异构架构下的并行计算技术。CUDA是目前最成熟、使用者最多的异构并行计算技术。本书对开发者更深入地掌握主流异构并行计算技术会有很大帮助。
程序优化的目的是提高整体性能,所以优化时需要做的第一件事就是找出程序的哪个部分需要提高整体性能,即瓶颈分析。这是至关重要而又经常被刚接触优化的开发者忽略的一件事。如果不先进行定量的瓶颈分析,而是立刻优化自己认为是瓶颈的地方,经常会事倍功半。瓶颈分析的第一步是热点分析,即找出哪些部分占程序的大部分运行时间。热点分析可以通过在源代码里加时间测量代码或使用性能分析工具(profiler)进行。当确认整体瓶颈是GPU的函数或数据传输后,读者就可参阅本书对应的GPU优化知识进行优化。
本书第一部分共4章,介绍GPU的架构、系统软件及编程环境。性能优化本质上就是通过理解架构及相应系统软件的特点,并在程序中利用这些特点更高效地完成计算。所以优化的第一步就应该是理解目标平台的架构及系统软件基础。这部分讨论的很多内容是第一次在公开的CUDA书籍中出现。
第二部分共6章,介绍CUDA编程各个方面的具体知识,特别是如何利用GPU特点的很多优化技术。
如果性能分析告诉我们CPU-GPU数据传输是瓶颈,那么可以参考第6章使用流来计算隐藏数据传输;另一方面,如果GPU函数的执行是瓶颈,那么下一步就是分析内核函数的架构瓶颈。此时,定量分析也是至关重要的。如果不先做定量分析找出瓶颈在哪里,而是立刻随机地尝试各种优化技术,往往难以收到成效。这样随机尝试,可能有些优化恰好有效果,有些优化则没有效果,会浪费大量时间在尝试各种技术上。另外,我们也无法明白为什么一种优化有效果而其他的却没有效果。除此之外,如果不做分析,我们也无从得知一个内核函数到底优化到何种程度就可以结束,从而有可能花费大量时间在一个已没有太大优化空间的内核函数上。这些都是优化技术的初学者很容易觉得优化是一件复杂而低效的工作的原因。但其实如果能采用先做定量分析再采用相应的优化技术的方法,优化完全可以变成一种高效、有据可依的技术。
对内核函数做分析,本质就是找出内核函数的性能瓶颈在架构的什么地方。一般情况下,性能瓶颈有三种可能类型。
1. 内存密集型。这种情况是内核函数的大部分时间都花在数据的读写指令上。从硬件的角度看,在这个内核函数运行期间,大部分时间都花在数据在内存总线的传输上并且内存总线的带宽已充分利用。对这种情况,如何优化可以参考第5章及第10章的内容。
2. 指令密集型。这种情况是内核函数的大部分时间都花在各种指令的执行上。从硬件的角度看,在这个内核函数运行期间,大部分时间都花在处理其指令单元的执行上。对这种情况,如何优化可以参考第8章的内容。
3. 延迟密集型。这种情况是内核函数的大部分时间都花在等待高延迟的指令(如内存读写)上。从硬件的角度看,在这个内核函数运行期间,大部分时间都花在数据在内存总线的传输上但内存总线的带宽没有被充分利用。对这种情况,如何优化可以参考第7章占有率的内容。
本书的第三部分共5章,给出了多个领域的具体例子,介绍如何应用各种优化技术。本部分的内容有助于读者学以致用。
虽然本书具体讨论CUDA,但并行优化的技术及想法对几乎任何众核架构都是适用的。所以读者如果在阅读本书了解具体CUDA优化技术之外,也能有意识地体会蕴含其中的并行优化的基本方法,会有更大收获。
王鹏
书摘
基 础 知 识
第1章简介
第2章硬件架构
第3章软件架构
第4章软件环境
Chapter 1 第1章
简介
GPU带给计算领域以巨大变革,这已在历史上留下了浓墨重彩的一笔。我喜欢饶有兴趣地阅读这类文字,因为我很早就参与其中了。在20世纪90年代中期,我任职于微软。当时英特尔和AMD正在引入第一批用以加速浮点计算的多媒体指令集,我领导一个开发小组开发Direct3D产品。英特尔为了阻止移植他们的CPU计算能力到三维栅格化任务,他们尝试跟微软合作出售使用他们多媒体扩展(MMX)指令集的光栅处理器,但最终失败了。当MMX光栅处理器运行在尚未发布的奔腾2处理器上时,我们发现其速度仅是正在出售的不起眼的S3 Virge GX光栅处理器的一半。那时我就知道这种努力注定是要失败的。
就Direct3D 6.0而言,我们与CPU厂商一起将他们的代码集成到我们的几何流水线(geometry pipeline),使开发人员可以以透明的方式使用来自英特尔和AMD的新指令集,并受益于厂商优化的代码执行路径。游戏开发人员接受了新的几何流水线,但由于新的指令集被用来生成GPU硬件的几何流水线所需要的顶点数据,因此,它没能阻止将CPU计算能力输送给GPU的持续迁移。
在那个时期,GPU上的晶体管数量超过了CPU上的数量。转折点在1997~1998年间,当时奔腾2和英伟达RIVA TNT的晶体管数量都约为800万个。随后,GeForce 256(1500万个晶体管)、GeForce 2(2800万个晶体管)和GeForce 3(6300万个晶体管)的晶体管数量均超过了当时的CPU。此外,两种设备之间的差异越来越清楚:大部分的CPU芯片面积是为了支持缓存,而大部分的GPU芯片面积是为了逻辑。英特尔能够添加大量新的扩展指令集(MMX、SSE、SSE2等),而增加的面积代价几乎可以忽略不计。GPU是专为并行吞吐处理而设计的,它们的小规模缓存是为了带来更多的带宽聚合(bandwidth aggregation)而不是为了减少指令延迟。
虽然ATI和英伟达等公司一直在生产越来越快速和越来越强大的GPU,CPU厂商仍然在摩尔定律(Moore’s Law)的指引下追求更高的时钟速率。第一款奔腾处理器(1993年)的时钟速率为60MHz,而启用MMX的奔腾处理器(1997年)的时钟速率为200MHz。到20世纪末,时钟速率已超过1000MHz。但此后不久,计算史上发生了一桩重大事件:摩尔定律碰了钉子。晶体管将继续变小,但时钟速率可能不会再继续增加。
这一事件并非意料之外。英特尔的Pat Gelsinger在2001年美国电气和电子工程师协会(IEEE)举办的固态电路会议上发表主题演讲,曾表示:如果继续目前的设计思路,芯片会在2010年跟核反应堆一样热,而到2015年将达到太阳表面的热度。在未来,性能将来自“同步多线程”(simultaneous multithreading,SMT)技术,可能要通过把多个CPU核心集成到一个芯片上来达到目的。事实上,CPU厂商已经这么做了。今天,很难找到一个只有单个CPU核心的桌面PC。几十年来,摩尔定律带给软件开发人员搭便车(free ride)的机会:提高CPU时钟频率,几乎根本不用软件开发人员操心,就允许程序运行更快。但这种好事将成为过去。多核心CPU需要多线程应用程序。只有当应用程序可以并行化时,众多CPU核心才能带来预期的高性能。
GPU的定位很好地利用了摩尔定律的新趋势。虽然那些未曾考虑并行化的CPU应用程序将需要大量的重构(如果它们有并行化的可能),然而在图形应用程序上已经采用了可以利用各独立像素之间固有的并行模式的思路。对于GPU而言,通过增加执行核心的数量来提高性能是一个很自然的手段。事实上,GPU设计者往往倾向于添加更多的核心而不是更强大的核心。他们摒弃了以最大限度地提高时钟频率(GPU的发展路线从来不是、现在依然不是靠制造接近晶体管电路极限的时钟频率。)、预测执行(speculative execution)、分支预测(branch prediction)和存储转发(store forwarding)等为代表的CPU厂商认为理所当然的策略。为了防止更加强大的处理器受限于I/O速度(I/O bound),GPU设计者结合内存控制器,并与内存厂商一起研制可以远远超过CPU可用带宽很多的GPU内存带宽。
但是,GPU的强劲计算能力对于非图形开发者来说很难利用。一些充满探索精神的程序员借助如Direct3D和OpenGL的图形API,通过迷惑图形硬件来执行非图形的计算任务。这一方法被冠以专门的术语:通用GPU编程(general-purpose GPU programming,GPGPU)。但GPU的大部分计算潜力仍一直处于未发掘状态,直到CUDA的出现改变了这一切。Ian Buck当时在斯坦福大学开展一项名为Brook的项目,意在简化GPGPU应用程序的开发过程。Buck后来进入英伟达并领导开发了一套新的开发工具,这使得GPU上非图形应用程序的开发更容易。这个英伟达的专用工具套装就是CUDA。CUDA允许C语言程序员使用一些简单易用的语言扩展编写GPU并行代码。
自2007年推出以来,CUDA一直深受好评。数以万计使用该技术的研究论文已被发表。它已被用于多个商业软件包,跨度从Adobe的CS5到Manifold的地理信息系统(geographic information system,GIS)。对于适合的工作任务,运行在支持CUDA的GPU上,相比同年代CPU,可以获得5~400倍不等的加速。这些加速的来源各不相同。有的加速是因为GPU有更多的核心;有的是因为有更高的内存带宽;还有一些是因为应用程序可以利用在CPU中不曾有的专门GPU硬件,例如可以更快计算超越函数的纹理硬件或特殊函数单元(SFU)。但并非所有的应用程序都可以采用CUDA实现。更确切地说,并非所有的并行应用程序都可以采用CUDA实现。但CUDA已使用在各种应用中,比任何其他的GPU计算技术的应用更广泛。我希望本书可以帮助有一定CUDA基础的开发者更有效地使用CUDA。
1.1方法
写一本以CUDA为主题的书籍是件困难的事情。并行程序设计需要涉及的因素很多,即使暂不考虑操作系统因素(Windows、Linux和MacOS)、平台因素(特斯拉与费米,集成显卡与独立显卡,多GPU)、CPU/GPU并发因素以及CUDA的特定因素(例如,决定是使用CUDA运行时还是驱动程序API编写代码),也是相当复杂的。当你还需要考虑如何最好地组织CUDA内核程序时,其复杂程度可能让人窒息。
本书为了应对这一复杂性,在介绍多数主题时从不同角度不止一次地进行解释。“纹理映射硬件做哪些事情?”这一问题跟“怎样写一个进行纹理映射操作的内核程序?”是不同的。本书分别在不同章节回答这两个问题。异步内存复制操作可以在几处不同的主题下来解释:软件的抽象(例如,参与的主机内存必须分配为锁页内存)、不同的硬件实现、支持该功能的API以及优化策略之间的相互作用。读者有时不妨查阅索引,然后选取相应主题下的多处文本来阅读。
性能优化指南通常组织得像咨询栏目。很多时候,它们给出的指导缺乏足够的实际应用场景,而且往往前后矛盾。上述观点不是为了斥责它们,它们只是问题复杂性的一个症状而已。优化CPU的金律,是经历了至少20年的持续探索,而GPU是更难进行编写程序的,所以期望CUDA的优化建议很简单就有点不切实际了。