本书介绍了在现代计算机系统上充分利用微处理器计算能力以提高软件性能的主要优化方法,共分为七章。
本书阐明了底层技术对软件性能的主要影响,介绍了丰富的软件优化方法和技巧,可以帮助软件工程师提升编程水平,充分发挥现代CPU、GPU、I/O、操作系统、编译器等底层系统的潜力。
从 2004 年开始,我们在 Intel 公司的支持下开设了“多核软件设计”课程,开始向本科生和硕士生讲述多核处理器上的软件优化技术。在过去十多年中,我们一直在补充这门课程的教学内容,逐渐涵盖了 CPU 的一般软件优化技术、SIMD 软件设计方法、GPU 体系结构与软件设计等多个方面。在此过程中,我们发现现有的教材还有很多需要提升的空间,主要体现在三个方面。
? 在现有计算机科学技术或软件工程的课程体系中,计算机体系结构(组成原理)、操作系统、编译原理等底层技术相关课程的理论性很强,且相对孤立,没有体现出这些底层技术与软件设计的关联以及对软件优化的支持。
? 从计算机专业或软件工程专业学生的编程能力培养角度看,现有的课程往往集中在算法的设计与优化、软件工程规范性等方面,缺少软件性能工程方面的基本训练,使得学生所设计的软件在性能方面难以满足实际应用的要求。
? 学生不了解现优 CPU、内存、磁盘、网络等底层系统硬件参数,难以准确估计系统的实际性能和及时预判可能存在的性能瓶颈,直接制约了软件总体结构设计及优化的能力。
这些问题促使我们撰写一本将计算机体系结构、操作系统、编译器、虚拟机等底层技术与软件优化技术相关联的教材,让读者能够理解软件优化的基本方法以及这些方法背后的原理,并通过编程实践掌握提升软件性能的常见方法。与其他教材相比,本书具有以下特点。
? 融合了底层技术和软件优化技术两个层面的内容。介绍软件优化技术时,分底层技术要点、软件优化基本方法、基于优秀开源代码或者学术论文的综合实例分析三个部分进行讲解。通过这些内容,读者可以理解计算机底层技术对软件性能的影响,掌握软件优化的基本方法,并学习实际系统中的应用方法。
? 以编程实践为核心。本书提供了较多的编程习题,核心目标是提升读者的编程能力。这些习题几乎都来自计算机或软件专业本科的常见算法或者实际工作生活中经常遇见的问题,方便读者理解算法的背景和基本原理。通过对同一个问题使用不同的软件优化技术,读者还可以对比不同优化技术的效果。
本书分为七章,其中第 1 章介绍了软件性能工程、延迟、吞吐率、加速比等基本概念和性能测试方法,后续章节围绕着 6 个专题展开。每章的内容既相对独立,又相互有联系。很多软件优化问题往往需要综合多章所介绍的技术逐步完成。
教师使用指导
在课程教学中,教师可以根据课时情况选择本书的若干章或者专题讲述底层技术的基本原理及基本优化实例,也可以根据科研情况,讲解其他程序优化实例。其中第 1~4 章为本科生的基本教学内容,第 5~7 章可以用于工程硕士研究生的知识扩展。
在日常作业中,教师可以选择书中的实验题作为编程作业。根据已有的教学实践经验,本科学生每两至三周可以完成一个较为复杂的软件优化作业,并根据编程实验书写完整的实验报告。教师可以联系本书作者(chenhu@scut.edu.cn)以获得本书实验题的参考程序。
本课程可以不进行书面考试,而是以学生平时的实验报告作为评分依据。此外,可以考虑采用程序竞赛作为考试的形式,例如对同一个问题(如矩阵乘法),根据学生所优化程序的运行时间长短进行排名和打分。这种方法可以更为有效地激励学生进行软件优化的热情。
学生使用指导
在本课程中,学生需要通过大量的编程练习来提升自己的编程能力,加深对计算机底层技术的理解和认识。在此过程中需要注意以下三点。
? 需要预先做好实验平台的准备,并充分了解实验平台的技术参数。
? 需要重视实验报告的写作。规范的实验报告便于交流技术思想,对实验数据的分析更能促进读者理解多种软件优化技术。
? 需要尽可能阅读相关的参考文献,扩展知识面。本书的篇幅有限,难以完整地涵盖所有的技术细节,需要读者通过参考文献进一步提升自我学习的能力。
需要指出的是,由于作者水平和知识面有限,本书所列举的优化方法不一定是最新或者最好的,还需要读者进一步去探索。
本书的编著工作由本人完成,汤德佑老师和黄敏老师认真审校了本书的主要内容。感谢华为“智能基座”项目的支持。
最后,感谢家人的默默付出,感谢陈焕鑫、刘家辉、陈捷瑞、徐烨威等同学为本书所做的工作。
陈 虎
华南理工大学软件学院
2023年8月
陈 虎
华南理工大学软件学院副教授,长期从事软件优化设计的科研和教学工作,承担了国家重点研发计划、国家自然科学基金重点项目等多项国家、省部级课题。具有超过十五年的专用高性能计算软件开发经验,研制的高性能计算软件已应用于国内主要超级计算机系统。多次担任“国产CPU并行应用挑战赛”等软件优化比赛评委。
汤德佑
华南理工大学软件学院副教授,长期致力于提升数据库引擎和生物信息学软件性能。深入优化ARM和Intel平台上数据库基础算子性能,并提交至开源社区;针对Intel高性能计算平台开发基因组数据分析软件、HBV病毒整合位点分析等专业生物信息学软件。
黄 敏
华南理工大学软件学院副院长、副教授,主要研究软件体系结构和软件性能优化技术。近年来承担和参与国家自然科学基金、广东省科技攻关、广东省自然科学基金、产学合作协同育人、广东省高等教育改革等多项国家和省部级课题。发表SCI/EI收录的高水平研究论文60余篇,并担任多个国际期刊的编辑和审稿人。
前言
第 1 章 引言 1
1.1 软件优化概述 1
1.1.1 软件优化的主要方法 1
1.1.2 软件性能工程 3
1.1.3 关于软件优化的一些观点 4
1.2 评价软件性能的指标和方法 6
1.2.1 延迟和吞吐率 6
1.2.2 加速比和效率 7
1.2.3 Amdahl 定理 8
1.2.4 M/M/k 模型 9
1.3 常用软件工具和时间测量方法 10
1.3.1 常用软件工具 10
1.3.2 时间测量 13
1.4 一个程序性能分析的实例 15
1.5 扩展阅读 16
1.6 习题 17
1.7 实验题 18
参考文献 20
第 2 章 CPU 上的基本优化方法 21
2.1 计算机体系结构基础 21
2.1.1 指令集体系结构 21
2.1.2 指令铁律 24
2.1.3 流水线及其相关性 26
2.1.4 超标量和乱序执行 27
2.1.5 典型微处理器的微结构 29
2.2 针对算术逻辑指令的优化 31
2.2.1 现代微处理器的算术逻辑指令延迟与吞吐率 31
2.2.2 选择合适的数据类型 32
2.2.3 使用简单指令代替复杂指令 33
2.2.4 使用特殊指令 34
2.2.5 查表法 35
2.3 针对条件分支指令的优化 36
2.3.1 分支预测 36
2.3.2 消除分支 38
2.3.3 组合多个分支以提高分支预测的准确度 38
2.3.4 使用条件执行指令 39
2.3.5 合理使用 switch 语句40
2.4 针对 Cache 的优化 41
2.4.1 现代微处理器的Cache 41
2.4.2 数据对齐 43
2.4.3 SoA 的结构组织方式 44
2.4.4 数据分块以提升 Cache命中率 45
2.4.5 Cache 预取 46
2.5 针对循环结构的优化 47
2.5.1 消除循环 47
2.5.2 循环展开 47
2.6 综合实例 49
2.6.1 Linux 内核中的 ECC 计算 49
2.6.2 Hash 表的构建 53
2.7 扩展阅读 55
2.8 习题 56
2.9 实验题 57
参考文献 59
第 3 章 基于 SIMD 指令系统的优化方法 61
3.1 SIMD 指令系统简介 61
3.1.1 SIMD 指令系统概况 61
3.1.2 软件系统使用 SIMD 指令的方法 63
3.2 SIMD 内嵌原语 64
3.2.1 内嵌原语的数据类型 64
3.2.2 向量设置操作 65
3.2.3 计算操作 66
3.2.4 比较操作 68
3.2.5 访存操作 69
3.2.6 数据排列操作 71
3.3 基于内嵌原语的 SIMD 程序设计 72
3.3.1 数据对齐和数据宽度 73
3.3.2 SoA 结构 74
3.3.3 数据比较 76
3.3.4 特殊指令 77
3.3.5 寄存器数量 79
3.4 SIMD 程序实例 81
3.4.1 使用 SSE 指令去除空格 81
3.4.2 基于 SIMD 指令的双调排序和归并排序 82
3.4.3 fftw 的可移植设计 84
3.5 扩展阅读 88
3.6 习题 88
3.7 实验题 88
参考文献 90
第 4 章 基于多线程的优化方法 94
4.1 多核处理器体系结构 94
4.1.1 多线程处理器 94
4.1.2 多核处理器系统 96
4.1.3 Cache 一致性协议 98
4.2 操作系统级线程调用 100
4.2.1 线程 100
4.2.2 线程基本 API 102
4.2.3 Linux 的线程同步和互斥 105
4.2.4 Windows 的线程同步和互斥 110
4.3 OpenMP 113
4.3.1 for 编译制导语句 114
4.3.2 共享变量和私有变量 115
4.3.3 归约子句 116
4.3.4 nowait 子句 117
4.3.5 single 制导指令 118
4.3.6 critical 子句 119
4.3.7 barrier 子句 119
4.3.8 其他子句 120
4.4 多线程程序的一些问题 120
4.4.1 临界区 120
4.4.2 Cache 伪共享 123
4.4.3 多线程的并行化设计方法 124
4.5 多线程并行化实例 125
4.5.1 Horner算法的并行化 125
4.5.2 构建 Hash 表 126
4.5.3 归并排序 127
4.6 扩展阅读 129
4.7 习题 130
4.8 实验题 131
参考文献 133
第 5 章 GPU 的优化方法 135
5.1 GPU 体系结构 135
5.1.1 面向吞吐率优化的异构
计算 135
5.1.2 GPU 总体结构 136
5.1.3 SIMT 机制 136
5.1.4 存储器结构 139
5.2 GPU 基本编程方法 139
5.2.1 线程的组织结构 139
5.2.2 GPU 函数说明 140
5.2.3 存储器管理以及与主机的数据交换 141
5.2.4 GPU 上线程之间的同步 143
5.2.5 OpenCL 的程序对象和内核对象 144
5.2.6 程序实例 145
5.3 GPU 程序优化方法 148
5.3.1 指令吞吐率 148
5.3.2 资源利用率 149
5.3.3 共享存储器 150
5.3.4 全局存储器 152
5.3.5 掩盖主机和 GPU 之间的数据传输延迟 152
5.3.6 动态并行机制 154
5.4 GPU 程序实例 155
5.4.1 矩阵乘法 155
5.4.2 LU 分解 157
5.5 扩展阅读 159
5.6 习题 159
5.7 实验题 160
参考文献 160
第 6 章 面向对象程序设计语言的优化方法 162
6.1 C++ 的性能优化 162
6.1.1 C++ 实现简介 162
6.1.2 STL 167
6.2 Java 的性能优化 168
6.2.1 Java 虚拟机简介 168
6.2.2 Java 字节码的执行机制 170
6.2.3 Java 本地接口 172
6.2.4 Java 的多线程机制 174
6.3 垃圾回收 176
6.3.1 垃圾回收基本技术 176
6.3.2 HotSpot JVM 中的垃圾回收 181
6.4 扩展阅读 183
6.5 习题 184
6.6 实验题 184
参考文献 186
第 7 章 系统级软件优化 188
7.1 硬盘系统与文件系统的性能优
化 189
7.1.1 硬盘系统 189
7.1.2 文件系统 191
7.1.3 性能优化方法 193
7.1.4 实例:外排序 194
7.2 网络连接的性能优化 196
7.2.1 网络连接硬件 196
7.2.2 网络编程简介 197
7.2.3 性能优化方法 200
7.2.4 实例:Web 服务器的结构 204
7.3 软件总体结构的设计考虑 207
7.3.1 用户友好性设计 207
7.3.2 可移植性设计 208
7.3.3 错误处理设计 209
7.3.4 系统可维护性设计 210
7.4 扩展阅读 211
7.5 习题 212
7.6 实验题 212
参考文献 213