本書介紹了在現(xiàn)代計算機系統(tǒng)上充分利用微處理器計算能力以提高軟件性能的主要優(yōu)化方法,共分為七章。
本書闡明了底層技術對軟件性能的主要影響,介紹了豐富的軟件優(yōu)化方法和技巧,可以幫助軟件工程師提升編程水平,充分發(fā)揮現(xiàn)代CPU、GPU、I/O、操作系統(tǒng)、編譯器等底層系統(tǒng)的潛力。
從 2004 年開始,我們在 Intel 公司的支持下開設了“多核軟件設計”課程,開始向本科生和碩士生講述多核處理器上的軟件優(yōu)化技術。在過去十多年中,我們一直在補充這門課程的教學內(nèi)容,逐漸涵蓋了 CPU 的一般軟件優(yōu)化技術、SIMD 軟件設計方法、GPU 體系結構與軟件設計等多個方面。在此過程中,我們發(fā)現(xiàn)現(xiàn)有的教材還有很多需要提升的空間,主要體現(xiàn)在三個方面。
? 在現(xiàn)有計算機科學技術或軟件工程的課程體系中,計算機體系結構(組成原理)、操作系統(tǒng)、編譯原理等底層技術相關課程的理論性很強,且相對孤立,沒有體現(xiàn)出這些底層技術與軟件設計的關聯(lián)以及對軟件優(yōu)化的支持。
? 從計算機專業(yè)或軟件工程專業(yè)學生的編程能力培養(yǎng)角度看,現(xiàn)有的課程往往集中在算法的設計與優(yōu)化、軟件工程規(guī)范性等方面,缺少軟件性能工程方面的基本訓練,使得學生所設計的軟件在性能方面難以滿足實際應用的要求。
? 學生不了解現(xiàn)優(yōu) CPU、內(nèi)存、磁盤、網(wǎng)絡等底層系統(tǒng)硬件參數(shù),難以準確估計系統(tǒng)的實際性能和及時預判可能存在的性能瓶頸,直接制約了軟件總體結構設計及優(yōu)化的能力。
這些問題促使我們撰寫一本將計算機體系結構、操作系統(tǒng)、編譯器、虛擬機等底層技術與軟件優(yōu)化技術相關聯(lián)的教材,讓讀者能夠理解軟件優(yōu)化的基本方法以及這些方法背后的原理,并通過編程實踐掌握提升軟件性能的常見方法。與其他教材相比,本書具有以下特點。
? 融合了底層技術和軟件優(yōu)化技術兩個層面的內(nèi)容。介紹軟件優(yōu)化技術時,分底層技術要點、軟件優(yōu)化基本方法、基于優(yōu)秀開源代碼或者學術論文的綜合實例分析三個部分進行講解。通過這些內(nèi)容,讀者可以理解計算機底層技術對軟件性能的影響,掌握軟件優(yōu)化的基本方法,并學習實際系統(tǒng)中的應用方法。
? 以編程實踐為核心。本書提供了較多的編程習題,核心目標是提升讀者的編程能力。這些習題幾乎都來自計算機或軟件專業(yè)本科的常見算法或者實際工作生活中經(jīng)常遇見的問題,方便讀者理解算法的背景和基本原理。通過對同一個問題使用不同的軟件優(yōu)化技術,讀者還可以對比不同優(yōu)化技術的效果。
本書分為七章,其中第 1 章介紹了軟件性能工程、延遲、吞吐率、加速比等基本概念和性能測試方法,后續(xù)章節(jié)圍繞著 6 個專題展開。每章的內(nèi)容既相對獨立,又相互有聯(lián)系。很多軟件優(yōu)化問題往往需要綜合多章所介紹的技術逐步完成。
教師使用指導
在課程教學中,教師可以根據(jù)課時情況選擇本書的若干章或者專題講述底層技術的基本原理及基本優(yōu)化實例,也可以根據(jù)科研情況,講解其他程序優(yōu)化實例。其中第 1~4 章為本科生的基本教學內(nèi)容,第 5~7 章可以用于工程碩士研究生的知識擴展。
在日常作業(yè)中,教師可以選擇書中的實驗題作為編程作業(yè)。根據(jù)已有的教學實踐經(jīng)驗,本科學生每兩至三周可以完成一個較為復雜的軟件優(yōu)化作業(yè),并根據(jù)編程實驗書寫完整的實驗報告。教師可以聯(lián)系本書作者(chenhu@scut.edu.cn)以獲得本書實驗題的參考程序。
本課程可以不進行書面考試,而是以學生平時的實驗報告作為評分依據(jù)。此外,可以考慮采用程序競賽作為考試的形式,例如對同一個問題(如矩陣乘法),根據(jù)學生所優(yōu)化程序的運行時間長短進行排名和打分。這種方法可以更為有效地激勵學生進行軟件優(yōu)化的熱情。
學生使用指導
在本課程中,學生需要通過大量的編程練習來提升自己的編程能力,加深對計算機底層技術的理解和認識。在此過程中需要注意以下三點。
? 需要預先做好實驗平臺的準備,并充分了解實驗平臺的技術參數(shù)。
? 需要重視實驗報告的寫作。規(guī)范的實驗報告便于交流技術思想,對實驗數(shù)據(jù)的分析更能促進讀者理解多種軟件優(yōu)化技術。
? 需要盡可能閱讀相關的參考文獻,擴展知識面。本書的篇幅有限,難以完整地涵蓋所有的技術細節(jié),需要讀者通過參考文獻進一步提升自我學習的能力。
需要指出的是,由于作者水平和知識面有限,本書所列舉的優(yōu)化方法不一定是最新或者最好的,還需要讀者進一步去探索。
本書的編著工作由本人完成,湯德佑老師和黃敏老師認真審校了本書的主要內(nèi)容。感謝華為“智能基座”項目的支持。
最后,感謝家人的默默付出,感謝陳煥鑫、劉家輝、陳捷瑞、徐燁威等同學為本書所做的工作。
陳 虎
華南理工大學軟件學院
2023年8月
陳 虎
華南理工大學軟件學院副教授,長期從事軟件優(yōu)化設計的科研和教學工作,承擔了國家重點研發(fā)計劃、國家自然科學基金重點項目等多項國家、省部級課題。具有超過十五年的專用高性能計算軟件開發(fā)經(jīng)驗,研制的高性能計算軟件已應用于國內(nèi)主要超級計算機系統(tǒng)。多次擔任“國產(chǎn)CPU并行應用挑戰(zhàn)賽”等軟件優(yōu)化比賽評委。
湯德佑
華南理工大學軟件學院副教授,長期致力于提升數(shù)據(jù)庫引擎和生物信息學軟件性能。深入優(yōu)化ARM和Intel平臺上數(shù)據(jù)庫基礎算子性能,并提交至開源社區(qū);針對Intel高性能計算平臺開發(fā)基因組數(shù)據(jù)分析軟件、HBV病毒整合位點分析等專業(yè)生物信息學軟件。
黃 敏
華南理工大學軟件學院副院長、副教授,主要研究軟件體系結構和軟件性能優(yōu)化技術。近年來承擔和參與國家自然科學基金、廣東省科技攻關、廣東省自然科學基金、產(chǎn)學合作協(xié)同育人、廣東省高等教育改革等多項國家和省部級課題。發(fā)表SCI/EI收錄的高水平研究論文60余篇,并擔任多個國際期刊的編輯和審稿人。
前言
第 1 章 引言 1
1.1 軟件優(yōu)化概述 1
1.1.1 軟件優(yōu)化的主要方法 1
1.1.2 軟件性能工程 3
1.1.3 關于軟件優(yōu)化的一些觀點 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 上的基本優(yōu)化方法 21
2.1 計算機體系結構基礎 21
2.1.1 指令集體系結構 21
2.1.2 指令鐵律 24
2.1.3 流水線及其相關性 26
2.1.4 超標量和亂序執(zhí)行 27
2.1.5 典型微處理器的微結構 29
2.2 針對算術邏輯指令的優(yōu)化 31
2.2.1 現(xiàn)代微處理器的算術邏輯指令延遲與吞吐率 31
2.2.2 選擇合適的數(shù)據(jù)類型 32
2.2.3 使用簡單指令代替復雜指令 33
2.2.4 使用特殊指令 34
2.2.5 查表法 35
2.3 針對條件分支指令的優(yōu)化 36
2.3.1 分支預測 36
2.3.2 消除分支 38
2.3.3 組合多個分支以提高分支預測的準確度 38
2.3.4 使用條件執(zhí)行指令 39
2.3.5 合理使用 switch 語句40
2.4 針對 Cache 的優(yōu)化 41
2.4.1 現(xiàn)代微處理器的Cache 41
2.4.2 數(shù)據(jù)對齊 43
2.4.3 SoA 的結構組織方式 44
2.4.4 數(shù)據(jù)分塊以提升 Cache命中率 45
2.4.5 Cache 預取 46
2.5 針對循環(huán)結構的優(yōu)化 47
2.5.1 消除循環(huán) 47
2.5.2 循環(huán)展開 47
2.6 綜合實例 49
2.6.1 Linux 內(nèi)核中的 ECC 計算 49
2.6.2 Hash 表的構建 53
2.7 擴展閱讀 55
2.8 習題 56
2.9 實驗題 57
參考文獻 59
第 3 章 基于 SIMD 指令系統(tǒng)的優(yōu)化方法 61
3.1 SIMD 指令系統(tǒng)簡介 61
3.1.1 SIMD 指令系統(tǒng)概況 61
3.1.2 軟件系統(tǒng)使用 SIMD 指令的方法 63
3.2 SIMD 內(nèi)嵌原語 64
3.2.1 內(nèi)嵌原語的數(shù)據(jù)類型 64
3.2.2 向量設置操作 65
3.2.3 計算操作 66
3.2.4 比較操作 68
3.2.5 訪存操作 69
3.2.6 數(shù)據(jù)排列操作 71
3.3 基于內(nèi)嵌原語的 SIMD 程序設計 72
3.3.1 數(shù)據(jù)對齊和數(shù)據(jù)寬度 73
3.3.2 SoA 結構 74
3.3.3 數(shù)據(jù)比較 76
3.3.4 特殊指令 77
3.3.5 寄存器數(shù)量 79
3.4 SIMD 程序?qū)嵗 ?1
3.4.1 使用 SSE 指令去除空格 81
3.4.2 基于 SIMD 指令的雙調(diào)排序和歸并排序 82
3.4.3 fftw 的可移植設計 84
3.5 擴展閱讀 88
3.6 習題 88
3.7 實驗題 88
參考文獻 90
第 4 章 基于多線程的優(yōu)化方法 94
4.1 多核處理器體系結構 94
4.1.1 多線程處理器 94
4.1.2 多核處理器系統(tǒng) 96
4.1.3 Cache 一致性協(xié)議 98
4.2 操作系統(tǒng)級線程調(diào)用 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 臨界區(qū) 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 的優(yōu)化方法 135
5.1 GPU 體系結構 135
5.1.1 面向吞吐率優(yōu)化的異構
計算 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 函數(shù)說明 140
5.2.3 存儲器管理以及與主機的數(shù)據(jù)交換 141
5.2.4 GPU 上線程之間的同步 143
5.2.5 OpenCL 的程序?qū)ο蠛蛢?nèi)核對象 144
5.2.6 程序?qū)嵗 ?45
5.3 GPU 程序優(yōu)化方法 148
5.3.1 指令吞吐率 148
5.3.2 資源利用率 149
5.3.3 共享存儲器 150
5.3.4 全局存儲器 152
5.3.5 掩蓋主機和 GPU 之間的數(shù)據(jù)傳輸延遲 152
5.3.6 動態(tài)并行機制 154
5.4 GPU 程序?qū)嵗 ?55
5.4.1 矩陣乘法 155
5.4.2 LU 分解 157
5.5 擴展閱讀 159
5.6 習題 159
5.7 實驗題 160
參考文獻 160
第 6 章 面向?qū)ο蟪绦蛟O計語言的優(yōu)化方法 162
6.1 C++ 的性能優(yōu)化 162
6.1.1 C++ 實現(xiàn)簡介 162
6.1.2 STL 167
6.2 Java 的性能優(yōu)化 168
6.2.1 Java 虛擬機簡介 168
6.2.2 Java 字節(jié)碼的執(zhí)行機制 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 章 系統(tǒng)級軟件優(yōu)化 188
7.1 硬盤系統(tǒng)與文件系統(tǒng)的性能優(yōu)
化 189
7.1.1 硬盤系統(tǒng) 189
7.1.2 文件系統(tǒng) 191
7.1.3 性能優(yōu)化方法 193
7.1.4 實例:外排序 194
7.2 網(wǎng)絡連接的性能優(yōu)化 196
7.2.1 網(wǎng)絡連接硬件 196
7.2.2 網(wǎng)絡編程簡介 197
7.2.3 性能優(yōu)化方法 200
7.2.4 實例:Web 服務器的結構 204
7.3 軟件總體結構的設計考慮 207
7.3.1 用戶友好性設計 207
7.3.2 可移植性設計 208
7.3.3 錯誤處理設計 209
7.3.4 系統(tǒng)可維護性設計 210
7.4 擴展閱讀 211
7.5 習題 212
7.6 實驗題 212
參考文獻 213