OpenMP日益增加的復(fù)雜性使其學(xué)習(xí)門檻不斷升高,本書回歸OpenMP zui初的設(shè)計(jì)哲學(xué),提煉出大多數(shù)程序員常用的21項(xiàng)核心知識(shí)——稱為OpenMP“通用核心”,為零基礎(chǔ)讀者搭建了從通用核心到OpenMP多線程編程的高效學(xué)習(xí)階梯。本書由OpenMP技術(shù)專家撰寫,內(nèi)容涵蓋并行計(jì)算的核心設(shè)計(jì)模式、共享工作循環(huán)構(gòu)造、OpenMP數(shù)據(jù)環(huán)境、OpenMP任務(wù)和OpenMP內(nèi)存模型等內(nèi)容,采用編程驅(qū)動(dòng)的方式,借助復(fù)雜性逐漸提高的實(shí)例來逐步引入新概念。此外,本書網(wǎng)站ompcore.com為讀者免費(fèi)提供各類代碼示例和練習(xí)題。
本書不是OpenMP的參考指南,在OpenMP網(wǎng)站上可以找到該語言的參考指南,將其和OpenMP規(guī)范結(jié)合起來就能提供你所需要的信息。此外,也可以將Ruud van der Pas、Eric Stotzer和Christian Terboven[13]所著的Using OpenMP桾he Next Step這本優(yōu)秀的書作為參考指南。
本書是關(guān)于如何學(xué)習(xí)OpenMP的。我們假設(shè)讀者沒有多線程的經(jīng)驗(yàn),也沒有OpenMP的知識(shí)。我們將材料分塊有序引入,以便讀者有效地學(xué)習(xí)這門語言。這與參考指南不同,在參考指南中,你會(huì)通過系統(tǒng)的關(guān)鍵元素來逐一了解每個(gè)元素的完整描述。在本書中,我們介紹了一些想法和支持這些想法的OpenMP構(gòu)造(construct)。然后,在引入更復(fù)雜的想法時(shí),我們會(huì)重新審視OpenMP構(gòu)造,并描述該構(gòu)造的其他方面。對(duì)于任何一個(gè)給定的OpenMP構(gòu)造,關(guān)于能用它做的一切事情的完整描述可能分散在幾個(gè)章節(jié)中。
這樣的安排是不會(huì)出現(xiàn)在參考指南中的。但正如你希望看到的那樣,這對(duì)于學(xué)習(xí)一門新的編程語言來說是非常有益的。例如,在教孩子數(shù)學(xué)函數(shù)的概念時(shí),你永遠(yuǎn)不會(huì)在接近奇點(diǎn)時(shí)引入極限和函數(shù)值的概念。你會(huì)等待,往往是很多年后,當(dāng)孩子掌握了函數(shù)的概念后,而且是通過長(zhǎng)期的練習(xí)掌握后,再引入極限來完成函數(shù)的完整定義。同樣,對(duì)于OpenMP也是如此。在介紹創(chuàng)建線程的并行構(gòu)造(parallel construct)時(shí),解釋所有控制數(shù)據(jù)環(huán)境的機(jī)制會(huì)讓人難以接受。不如先介紹線程的創(chuàng)建以及如何利用線程做有用的工作。然后,在掌握了管理線程的基礎(chǔ)知識(shí)后,再回到線程創(chuàng)建,但此時(shí)擁有了控制數(shù)據(jù)環(huán)境的能力。
使用本書的關(guān)鍵是主動(dòng)地跟隨本書練習(xí)。下載一個(gè)OpenMP編譯器(gcc編譯器和大多數(shù)商業(yè)編譯器一樣支持OpenMP)。隨著每個(gè)OpenMP指令或API例程的引入,編寫程序進(jìn)行實(shí)驗(yàn)。以不同的方式使用它們,理解它們的工作原理,然后再繼續(xù)閱讀。在寫代碼之前,不要只把書從頭到尾讀一遍,暫停一下,邊看書邊寫代碼。
為了支持這種主動(dòng)學(xué)習(xí)的方式,本書網(wǎng)站(http://www.ompcore.com)提供了各種各樣的程序和練習(xí)。請(qǐng)經(jīng)常查閱該網(wǎng)站,我們會(huì)持續(xù)更新,不斷分享關(guān)于OpenMP通用核心的新知識(shí)。
最后說一下編程語言。OpenMP支持C、C++和Fortran,理想的情況是本書應(yīng)該包含這三種語言的例子。然而,這樣做會(huì)大大擴(kuò)大本書的篇幅和范圍,對(duì)讀者來說,這些額外的工作真的沒有什么好處。除了極少數(shù)的例外情況(書中有詳細(xì)說明),OpenMP在三種語言之間基本上是一樣的,知道了一種語言的OpenMP,就會(huì)知道三種語言的OpenMP。因此,我們選擇為C/C++和Fortran定義構(gòu)造,但書中的例子和大部分的討論都以C語言為主。我們認(rèn)為這是一個(gè)正確的折中方案,因?yàn)樵诟咝阅苡?jì)算領(lǐng)域,C語言是程序員要掌握的最基本的知識(shí),即使是主要編寫Fortran代碼的程序員,也要了解C語言的基礎(chǔ)知識(shí)。
為了幫助使用Fortran的讀者,我們?cè)诒緯W(wǎng)站上提供了所有例子的Fortran版本。對(duì)于少數(shù)不懂C語言的Fortran程序員,我們還提供了C語言的簡(jiǎn)短教程。我們相信,本書與這些在線資源對(duì)Fortran程序員來說是重要的學(xué)習(xí)資料。因此,請(qǐng)不要因?yàn)闈M篇的C代碼而使你對(duì)本書望而卻步。如果你想學(xué)習(xí)OpenMP,無論是用C、C++還是Fortran編程,本書都會(huì)對(duì)你有所幫助。
致謝
本書的內(nèi)容是在20年的OpenMP教學(xué)基礎(chǔ)上煞費(fèi)苦心地開發(fā)出來的。例子、材料的組織流程和概念的描述方式等,都是由講師團(tuán)隊(duì)在各種超級(jí)計(jì)算會(huì)議的講座上研究出來的。我們要特別感謝Mark Bull(EPCC)、Sanjiv Shah(Intel)、Barbara Chapman(石溪大學(xué))、Larry Meadows(Intel)、Paul Petersen(Intel)和Simon McIntosh-Smith(布里斯托大學(xué))。內(nèi)存模型的內(nèi)容整合起來特別困難,田新民(Intel)、Michael Klemm(Intel),特別是Deepak Eachempati(Cray)在幫助我們定義這些材料方面發(fā)揮了重要作用。為了開發(fā)內(nèi)存模型的例子,我們需要訪問各種各樣的架構(gòu)。Simon McIntosh-Smith給予我們非常大的幫助,協(xié)助我們?cè)L問布里斯托大學(xué)的Isambard系統(tǒng)。
我們非常感謝MIT出版社的審稿團(tuán)隊(duì)。在從定稿到出版的過程中,他們的反饋對(duì)我們幫助很大。在這個(gè)團(tuán)隊(duì)中,我們特別要提到Ruud van der Pas(Oracle)。Ruud是我們的好朋友,他從一開始就鼓勵(lì)我們參與這個(gè)項(xiàng)目。他對(duì)本書進(jìn)行了非常仔細(xì)的審閱,做出了超出其職責(zé)范圍的貢獻(xiàn)。
我們還要感謝OpenMP架構(gòu)審查委員會(huì)允許我們使用OpenMP規(guī)范和部分示例文檔。最后,我們要感謝整個(gè)OpenMP社區(qū)的人:Bronis de Supinski(LLNL)和他領(lǐng)導(dǎo)的OpenMP語言委員會(huì),與我們合作過的OpenMP程序員,以及過去使用過我們的教程的所有學(xué)生。沒有他們,我們不可能創(chuàng)作出這樣的書。
譯者序
序言
前言
第一部分 做好學(xué)習(xí)OpenMP的準(zhǔn)備
第1章 并行計(jì)算 2
1.1 并行計(jì)算的基本概念 2
1.2 并發(fā)性的興起 4
1.3 并行硬件 5
1.3.1 多處理器系統(tǒng) 5
1.3.2 圖形處理單元 8
1.3.3 分布式內(nèi)存集群 10
1.4 多處理器計(jì)算機(jī)的并行軟件 10
第2章 性能語言 13
2.1 基礎(chǔ):FLOPS、加速比和并行效率 13
2.2 阿姆達(dá)爾定律 16
2.3 并行開銷 17
2.4 強(qiáng)擴(kuò)展與弱擴(kuò)展 19
2.5 負(fù)載均衡 19
2.6 用roofline模型理解硬件 21
第3章 什么是OpenMP 23
3.1 OpenMP的歷史 23
3.2 通用核心 25
3.3 OpenMP的主要組件 26
第二部分 OpenMP通用核心
第4章 線程和OpenMP編程模型 31
4.1 OpenMP概述 31
4.2 OpenMP 程序的結(jié)構(gòu) 31
4.3 線程和fork-join模式 34
4.4 使用線程 38
4.4.1 SPMD設(shè)計(jì)模式 39
4.4.2 偽共享 43
4.4.3 同步 45
4.5 結(jié)束語 49
第5章 并行化循環(huán) 50
5.1 共享工作循環(huán)構(gòu)造 51
5.2 組合式并行共享工作循環(huán)構(gòu)造 53
5.3 歸約 54
5.4 循環(huán)調(diào)度 56
5.4.1 靜態(tài)調(diào)度 56
5.4.2 動(dòng)態(tài)調(diào)度 57
5.4.3 選擇一個(gè)調(diào)度 59
5.5 隱式柵欄和nowait子句 61
5.6 帶有并行循環(huán)共享工作的Pi程序 63
5.7 一種循環(huán)級(jí)并行策略 64
5.8 結(jié)束語 66
第6章 OpenMP數(shù)據(jù)環(huán)境 67
6.1 缺省存儲(chǔ)屬性 68
6.2 修改存儲(chǔ)屬性 70
6.2.1 shared子句 70
6.2.2 private子句 72
6.2.3 firstprivate子句 73
6.2.4 default子句 74
6.3 數(shù)據(jù)環(huán)境的例子 74
6.3.1 數(shù)據(jù)作用域測(cè)試 75
6.3.2 曼德勃羅集的面積 76
6.3.3 重新審視Pi循環(huán)的例子 79
6.4 數(shù)組和指針 80
6.5 結(jié)束語 81
第7章 OpenMP任務(wù) 83
7.1 任務(wù)的必要性 83
7.2 顯式任務(wù) 86
7.3 第一個(gè)例子:薛定諤程序 87
7.4 single構(gòu)造 88
7.5 使用任務(wù) 89
7.5.1 什么時(shí)候任務(wù)完成 90
7.6 任務(wù)的數(shù)據(jù)環(huán)境 91
7.6.1 任務(wù)的缺省數(shù)據(jù)作用域 91
7.6.2 利用任務(wù)重新審視鏈表程序 93
7.7 利用任務(wù)的基礎(chǔ)設(shè)計(jì)模式 93
7.7.1 分而治之模式 95
7.8 結(jié)束語 99
第8章 OpenMP內(nèi)存模型 100
8.1 重新審視內(nèi)存層次結(jié)構(gòu) 101
8.2 OpenMP通用核心內(nèi)存模型 103
8.3 使用共享內(nèi)存 106
8.4 結(jié)束語 108
第9章 通用核心回顧 110
9.1 管理線程 111
9.2 共享工作構(gòu)造 111
9.3 組合式并行共享工作循環(huán)構(gòu)造 113
9.4 OpenMP任務(wù) 113
9.5 同步和內(nèi)存一致性模型 114
9.6 數(shù)據(jù)環(huán)境子句 115
9.7 歸約子句 116
9.8 環(huán)境變量和運(yùn)行時(shí)庫例程 117
第三部分 超越通用核心
第10章 超越通用核心的多線程 121
10.1 用于OpenMP通用核心構(gòu)造的附加子句 121
10.1.1 并行構(gòu)造 122
10.1.2 共享工作循環(huán)構(gòu)造 124
10.1.3 任務(wù)構(gòu)造 129
10.2 通用核心中缺失的多線程功能 133
10.2.1 threadprivate 133
10.2.2 master 135
10.2.3 atomic 136
10.2.4 OMP_STACKSIZE 137
10.2.5 運(yùn)行時(shí)庫例程 138
10.3 結(jié)束語 140
第11章 同步和OpenMP內(nèi)存模型 141
11.1 內(nèi)存一致性模型 142
11.2 成對(duì)同步 146
11.3 鎖以及如何使用它 151
11.4 C++內(nèi)存模型和OpenMP 153
11.5 結(jié)束語 156
第12章 超越OpenMP通用核心的硬件 157
12.1 非統(tǒng)一內(nèi)存訪問系統(tǒng) 158
12.1.1 在NUMA系統(tǒng)上工作 159
12.1.2 嵌套并行構(gòu)造 168
12.1.3 檢查線程親和力 171
12.1.4 小結(jié):線程親和力和數(shù)據(jù)局部性 173
12.2 SIMD 173
12.3 設(shè)備構(gòu)造 180
12.4 結(jié)束語 184
第13章 繼續(xù)OpenMP的學(xué)習(xí) 186
13.1 來自ARB的程序員資源 186
13.2 如何閱讀OpenMP規(guī)范 188
13.2.1 帶有所有正式術(shù)語的OpenMP 188
13.3 OpenMP規(guī)范的結(jié)構(gòu) 191
13.4 結(jié)束語 193
術(shù)語表 194