![]()
目录 第1章 GPU硬件与CUDA程序开发工具 1.1 GPU 硬件简介 1.2 CUDA 程序开发工具 1.3 CUDA 开发环境搭建示例 1.4 用nvidia-smi检查与设置设备 1.5 其他学习资料 第2章 CUDA中的线程组织 2.1 C++语言中的HelloWorld程序 2.2 CUDA中的HelloWorld程序 2.2.1 只有主机函数的CUDA程序 2.2.2 使用核函数的CUDA程序 2.3 CUDA中的线程组织 2.3.1 使用多个线程的核函数 2.3.2 使用线程索引 2.3.3 推广至多维网格 2.3.4 网格与线程块大小的限制 2.4 CUDA中的头文件 2.5 用nvcc编译CUDA程序 第3章 简单CUDA程序的基本框架 3.1 例子:数组相加 3.2 CUDA 程序的基本框架 3.2.1 隐形的设备初始化 3.2.2 设备内存的分配与释放 3.2.3 主机与设备之间数据的传递 3.2.4 核函数中数据与线程的对应 3.2.5 核函数的要求 3.2.6 核函数中if语句的必要性 3.3 自定义设备函数 3.3.1 函数执行空间标识符 3.3.2 例子:为数组相加的核函数定义一个设备函数 第4章 CUDA程序的错误检测 4.1 一个检测CUDA运行时错误的宏函数 4.1.1 检查运行时API函数 4.1.2 检查核函数 4.2 用CUDA-MEMCHECK检查内存错误 第5章 获得GPU加速的关键 5.1 用CUDA事件计时 5.1.1 为C++程序计时 5.1.2 为CUDA程序计时 5.2 几个影响GPU加速的关键因素 5.2.1 数据传输的比例 5.2.2 算术强度 5.2.3 并行规模 5.2.4 总结 5.3 CUDA中的数学函数库 第6章 CUDA的内存组织 6.1 CUDA的内存组织简介 6.2 CUDA中不同类型的内存 6.2.1 全局内存 6.2.2 常量内存 6.2.3 纹理内存和表面内存 6.2.4 寄存器 6.2.5 局部内存 6.2.6 共享内存 6.2.7 L1和L2缓存 6.3 SM及其占有率 6.3.1 SM的构成 6.3.2 SM的占有率 6.4 用CUDA运行时API函数查询设备 第7章 全局内存的合理使用 7.1 全局内存的合并与非合并访问 7.2 例子:矩阵转置 7.2.1 矩阵复制 7.2.2 使用全局内存进行矩阵转置 第8章 共享内存的合理使用 8.1 例子:数组归约计算 8.1.1 仅使用全局内存 8.1.2 使用共享内存 8.1.3 使用动态共享内存 8.2 使用共享内存进行矩阵转置 8.3 避免共享内存的bank冲突 第9章 原子函数的合理使用 9.1 完全在GPU中进行归约 9.2 原子函数 9.3 例子:邻居列表的建立 9.3.1 C++版本的开发 9.3.2 利用原子操作的CUDA版本 9.3.3 不用原子操作的CUDA版本 第10章 线程束基本函数与协作组 10.1 单指令-多线程执行模式 10.2 线程束内的线程同步函数 10.3 更多线程束内的基本函数 10.3.1 介绍 10.3.2 利用线程束洗牌函数进行归约计算 10.4 协作组 10.4.1 线程块级别的协作组 10.4.2 利用协作组进行归约计算 10.5 数组归约程序的进一步优化 10.5.1 提高线程利用率 10.5.2 避免反复分配与释放设备内存 第11章 CUDA流 11.1 CUDA流概述 11.2 在默认流中重叠主机和设备计算 11.3 用非默认CUDA流重叠多个核函数的执行 11.3.1 核函数执行配置中的流参数 11.3.2 重叠多个核函数的例子 11.4 用非默认CUDA流重叠核函数的执行与数据传递 11.4.1 不可分页主机内存与异步的数据传输函数 11.4.2 重叠核函数执行与数据传输的例子 第12章 使用统一内存编程 12.1 统一内存简介 12.1.1 统一内存的基本概念 12.1.2 使用统一内存对硬件的要求 12.1.3 统一内存编程的优势 12.2 统一内存的基本使用方法 12.2.1 动态统一内存 12.2.2 静态统一内存 12.3 使用统一内存申请超量的内存 12.3.1 第一个测试 12.3.2 第二个测试 12.3.3 第三个测试 12.4 优化使用统一内存的程序 第13章 分子动力学模拟的CUDA程序开发 13.1 分子动力学模拟的基本算法和C++实现 13.1.1 程序的整体结构 13.1.2 分子动力学模拟的基本流程 13.1.3 初始条件 13.1.4 边界条件 13.1.5 相互作用 13.1.6 运动方程的数值积分 13.1.7 程序中使用的单位制 13.1.8 程序的编译与运行 13.1.9 能量守恒的测试 13.1.10 C++版本程序运行速度的测试 13.2 CUDA版本的分子动力学模拟程序开发 13.2.1 仅加速求力和能量的部分 13.2.2 加速全部计算 第14章 CUDA标准库的使用 14.1 CUDA标准库简介 14.2 Thrust库 14.2.1 简介 14.2.2 数据结构 14.2.3 算法 14.2.4 例子:前缀和 14.3 cuBLAS库 14.3.1 简介 14.3.2 例子:矩阵乘法 14.4 cuSolver库 14.4.1 精彩页 第1章 GPU硬件与CUDA程序开发工具 1.1 GPU硬件简介 GPU是英文graphics processing unit的首字母缩写,意为图形处理器。GPU也常被称为显卡(graphicscard)。与它对应的一个概念是CPU,即centralprocessingunit(中央处理器)的首字母缩写。 从十多年前起,GPU的浮点数运算峰值就比同时期的CPU高一个量级;GPU的内存带宽峰值也比同时期的CPU高一个量级。CPU和GPU的显著区别如下:一块典型的CPU拥有少数几个快速的计算核心,而一块典型的GPU拥有几百到几千个不那么快速的计算核心。CPU中有更多的晶体管用于数据缓存和流程控制,但GPU中有更多的晶体管用于算术逻辑单元。所以,GPU是靠众多的计算核心来获得相对较高的计算性能的。图1.1形象地说明了(非集成)GPU和CPU在硬件架构上的显著区别。 图1.1CPU和非集成GPU的硬件架构示意图 (a) CPU; (b) GPU CPU和GPU中都有DRAM(dynamicrandomaccessmemory,动态随机存取存储器),它们一般由PCIe总线(peripheralcomponentinterconnectexpressbus)连接。 GPU计算不是指单独的GPU计算,而是指CPU+GPU的异构(heterogen-eous)计算。一块单独的GPU是无法独立地完成所有计算任务的,它必须在CPU CUDA 编程:基础与实践 | 的调度下才能完成特定任务。在由CPU和GPU构成的异构计算平台中,通常将起控制作用的CPU称为主机(host),将起加速作用的GPU称为设备(device)。主机和(非集成)设备都有自己的DRAM,它们之间一般由PCIe总线连接,如图1.1所示。 本书中说的GPU都是指英伟达(Nvidia)公司推出的GPU,因为CUDA编程目前只支持该公司的GPU。以下几个系列的GPU都支持CUDA编程。 (1)Tesla系列:其中的内存为纠错内存(error-correctingcodememory,ECC内存),稳定性好,主要用于高性能、高强度的科学计算。 (2)Quadro系列:支持高速OpenGL(opengraphicslibrary)渲染,主要用于专业绘图设计。 (3)GeForce系列:主要用于游戏与娱乐,但也常用于科学计算。GeForce系列的GPU没有纠错内存,用于科学计算时具有一定的风险。然而,GeForce系列的GPU价格相对低廉、性价比高,用于学习CUDA编程是没有任何问题的。即使是便携式计算机中GeForce系列的GPU也可以用来学习CUDA编程。 (4)Jetson系列:嵌入式设备中的GPU。作者对此无使用经验,本书也不专门讨论。 每一款GPU都有一个用以表示其“计算能力”(computecapability)的版本号。该版本号可以写为形如X.Y的形式。其中,X表示主版本号,Y表示次版本号。版本号决定了GPU硬件所支持的功能,可为应用程序在运行时判断硬件特征Windows中使用MSVC作为C++程序的编译器时,需要单独设置相应的环境变量,或者从Windows的“开始”(start)菜单中找到VisualStudio2019文件夹,然后单击其中的“x64NativeToolsCommandPromptforVS2019”,从而打开一个加载了MSVC环境变量的命令行解释器。在本书的某些章节,需要有管理员的权限来使用nvprof性能分析器。此时,可以右击“x64NativeToolsCommandPromptforVS2019”,在弹出的快捷菜单中选择“更多”→ “以管理员身份运行”。 用命令行解释器编译与运行CUDA程序的方式在Windows和Linux系统几乎没有区别,但为了简洁起见,本书后面主要以Linux开发环境为例进行讲解。虽然如此,Windows和Linux中的CUDA编程功能还是稍有差别。我们将在后续章节中适当的地方指出这些差别。 1.4 用nvidia-smi检查与设置设备 可以通过nvidia-smi(Nvidia’ssystemmanagementinterface)程序检查与设置设备。它包含在CUDA开发工具套装内。该程序最基本的用法就是在命令行解释器中使用不带任何参数的命令nvidia-smi。在作者的计算机中使用该命令,得到如下文本形式的输出: +-----------------------------------------------------------------------------+ | NVIDIA-SMI 426.00 Driver Version: 426.00 CUDA Version: 10.1 | |-------------------------------+----------------------+----------------------+ | GPU Name TCC/WDDM | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | |===============================+======================+======================| | 0 GeForce RTX 207... WDDM | 00000000:01:00.0 Off | N/A | | N/A 38C P8 12W / N/A | 161MiB / 8192MiB | 0% Default | +-------------------------------+----------------------+----------------------+ +-----------------------------------------------------------------------------+ | Processes: GPU Memory | | GPU PID Type Process name Usage | |=============================================================================| | No running processes found | +---------------------- 序言 前言 基于CPU(central processing unit,中央处理 器)和GPU(graphics processing unit,图形处理 器)的异构计算 (heterogeneous computing)已逐步发展为 高性能计算(high performance computing) 领域的主流模式。很多超级 计算机大量使用了GPU。 CUDA(compute unified device architecture)作为 GPU高性能计算的主要开发 工具之一,已经在计算机、 物理、化学、生物、材料等 众多领域发挥了重要作用。 掌握CUDA编程也就意味着 开辟了一条通往高性能计算 的新道路。本书通过大量实 例循序渐进地介绍CUDA编 程的语法知识、优化策略及 程序开发实践。本书所有源 代码都可以通过作者为本书 创建的GitHub仓库 (https:// github.com/brucefan1983/ CUDA-Programming)获得 。读者也可以针对该仓库提 出问题(issues)与作者进 行交流。渤海大学由琪同学 的GitHub仓库 https://github.com/ YouQixiaowu/CUDA- Programming-with-Python 还给出了本书部分程序的 py-CUDA版本。本书中的所 有程序都在Linux平台通过 测试,其中大部分程序也能 在Windows平台通过测试。 我们会在适当的地方指出哪 些程序无法在(作者的) Windows平台通过测试。本 书是一本较理想的学习 CUDA编程的入门读物。在 计算机方面,读者需要掌握 初步的Linux或Windows命 令行操作技能,并具有一定 的C++语言编程基础。第 13章的内容要求读者具有大 学物理或普通物理的知识基 础。第14章的部分内容要求 读者熟悉大学本科理工科的 线性代数知识。本书前12章 需顺序阅读,后两章可选读 ,而且可以按任意次序阅读 。最后要强调的是,本书不 假定读者有并行编程的经验 。本书不是一本CUDA编程 手册,不追求面面俱到,但 力求做到由浅入深、循序渐 进。截至作者交稿之日,最 新版本(10.2)的《CUDA C++ Programming Guide 》和《CUDA C++ Best Practices Guide》加起来有 400多页,再加上CUDA工具 箱中各种应用程序库和编程 开发工具的文档,总页数可 能上万。在本书100多页的 篇幅中想要做到面面俱到是 不可能的。明确地说:本书 只涉及CUDA C++编程,不 涉及其他异构编程语言,如 OpenCL、OpenACC和CUDA Fortran。关于CUDA C++编 程,本书不涉及动态并行( dynamic parallelism)、 CUDA Graph、CUDA与 OpenGL和Direct3D的交互 、纹理和表面内存的使用。 本书不涉及多GPU编程,只 讨论单GPU编程,并且不涉 及OpenMP和MPI。在众多 性能分析器(profiler)中 ,我们将仅偶尔使用nvprof ,不使用其他可视化性能分 析器。本书彩图请扫描右侧 二维码观看。本书的出版受 到国家自然科学基金的支持 ,项目编号为11974059, 名称为《基于石墨烯及其他 两维材料的柔性热电材料的 多尺度模拟》。本书中相关 程序的开发和测试使用了由 Aalto Science-IT project和 Finland’s IT Center for Science(CSC)提供的计 算资源与技术支持。复旦大 学的周麟祥教授于2011年 在厦门大学开设的CUDA编 程讲座让作者有幸较早地接 触CUDA编程。厦门大学的 博士后导师郑金成和王惠琼 教授及芬兰Aalto大学的博 士后导师Ari Harju博士和 Tapio Ala-Nissila教授在作 者学习与使用CUDA的过程 中给予了很大的支持。在此 对以上老师表示由衷的感谢 !特别感谢苏州吉浦讯科技 有限公司的技术团队。该团 队的工程师们为本书的初稿 指出了300多个问题,并为 作者解答了很多有关CUDA 编程的问题。如果没有该团 队的帮助,本书一定有很多 错误。厦门大学的徐克同学 和渤海大学的由琪同学先后 为本书制作了若干插图。中 国科学技术大学的黄翔同学 、潍坊学院高性能计算中心 的李延龙同学及西安理工大 学的范亚东同学帮助审阅了 全部书稿。在此对以上同学 一并表示感谢。本书从构思 到完成大概花了一年半的时 间。在这一年半的时间里, 此书的写作占用了我很多本 应该陪伴家人的时间。所以 ,我将此书献给我的妻子秦 海霞、大女儿樊怀瑾和小女 儿樊婉瑜,以及我的父亲樊 明营与母亲张珍艳。 内容推荐 CUDA是目前较为流行的GPU高性能计算的开发工具之一。本书通过大量实例系统地讲述CUDA编程的重要方面。前12章通过一些简短的例子循序渐进地介绍CUDA编程的基础知识,主要包括GPU硬件与CUDA程序开发工具(第1章)、CUDA中的线程组织(第2章)、CUDA程序的基本框架与错误检测(第3、4章)、获得GPU加速的关键(第5章)、CUDA中的内存组织与各种内存的合理使用(第6~8章)、原子函数的合理使用(第9章)、线程束内的基本函数(第10章)、CUDA流(第11章)、统一内存(第12章)等。后面两章是可选读的内容:第13章综合运用前述章节中的知识,用CUDA开发一个简单的分子动力学模拟程序;第14章介绍若干CUDA库(包括Thrust、cuBLAS、cuSolver和cuRAND)的使用。 本书适合高等院校理工科专业的本科生和研究生及其他任何对CUDA编程感兴趣的人士阅读。 |