- 并行編程方法與優(yōu)化實(shí)踐
- 劉文志
- 4134字
- 2019-01-01 01:08:27
前言
為什么要寫這本書
本書主要是為軟件工程師寫的。在解釋為什么筆者認(rèn)為軟件工程師需要這本書之前,先來介紹并行、并發(fā)和代碼性能優(yōu)化這3個概念,理解這3個概念是閱讀本書的基礎(chǔ)。
·并行對應(yīng)的英文單詞是parallelism,是指在具有多個處理單元的系統(tǒng)上,通過將計(jì)算或數(shù)據(jù)劃分為多個部分,然后將各個部分分配到不同的處理單元上,各處理單元相互協(xié)作,同時運(yùn)行,以達(dá)到加快求解速度或者擴(kuò)大求解問題規(guī)模的目的。
·并發(fā)對應(yīng)的英文單詞是concurrency,是指在一個處理單元上運(yùn)行多個應(yīng)用,各應(yīng)用分時占用處理單元。這是一種微觀上串行、宏觀上并行的模式,有時也稱其為時間上串行、空間上并行。
·代碼性能優(yōu)化是指通過調(diào)整源代碼,使其生成的機(jī)器指令能夠更高效地執(zhí)行。通常高效是指執(zhí)行時間更少、使用的存儲器更少或能夠計(jì)算更大規(guī)模的問題。
從大的方面來說,并行和并發(fā)都是代碼性能優(yōu)化的一種方式。但是今天并行和并發(fā)已經(jīng)變得如此重要,以至于需要“開宗立派”。為了劃清并行、并發(fā)和代碼性能優(yōu)化的界線,在本書中,代碼性能優(yōu)化特指除并行和并發(fā)以外的代碼優(yōu)化方法,比如向量化和提高指令流水線效率。在本書中,筆者將向量化獨(dú)立出來解說。
2003年以前,在摩爾定律的作用下,單核標(biāo)量處理器的性能持續(xù)提升,軟件開發(fā)人員只需要寫好軟件,而性能的提升則等待下次硬件的更新。2003年之前的幾十年里,這種“免費(fèi)午餐”的模式一直在持續(xù)。2003年后,主要由于功耗的原因,這種“免費(fèi)午餐”已經(jīng)不復(fù)存在了。為了生存,各硬件生產(chǎn)商不得不采用各種方式提高硬件的計(jì)算能力。目前最流行的3種方式如下:
1)讓處理器在一個周期處理多條指令,多條指令可相同可不同。如Intel Haswell處理器一個周期可執(zhí)行4條整數(shù)加法指令、2條浮點(diǎn)乘加指令,訪存和運(yùn)算指令也可同時執(zhí)行。
2)使用向量指令,主要是SIMD和VLIW技術(shù)。SIMD技術(shù)將處理器一次能夠處理的數(shù)據(jù)位數(shù)從字長擴(kuò)大到128位或256位,從而提升了計(jì)算能力。
3)在同一個芯片中集成多個處理單元,根據(jù)集成方式的不同,相應(yīng)地稱為多核處理器或多路處理器。多核處理器是如此的重要,以至于現(xiàn)在即使是手機(jī)上的嵌入式ARM處理器都已經(jīng)是四核或八核的了。
目前絕大部分應(yīng)用軟件都是串行的,串行執(zhí)行過程符合人類的思維習(xí)慣,易于理解、分析和驗(yàn)證。由于串行軟件只能在多核處理器中的一個核上運(yùn)行,和2003年以前的CPU沒有多少區(qū)別,這意味著花多核處理器的價(jià)錢買到了單核的性能。通過多核技術(shù),硬件生產(chǎn)商成功地將提高實(shí)際計(jì)算能力的任務(wù)轉(zhuǎn)嫁給了軟件開發(fā)人員,而軟件開發(fā)人員則沒有選擇,只有直面挑戰(zhàn)。
標(biāo)量單核的計(jì)算能力沒有辦法持續(xù)大幅度提升,而應(yīng)用對硬件計(jì)算能力的需求依舊在提升,這是個實(shí)實(shí)在在的矛盾。在可見的將來,要解決這個矛盾,軟件開發(fā)人員只有選擇代碼優(yōu)化和并行。代碼優(yōu)化并不能利用多核CPU的全部計(jì)算能力,它也不要求軟件開發(fā)人員掌握并行開發(fā)技術(shù),另外通常也無須對軟件架構(gòu)做改動,而且串行代碼優(yōu)化有時能夠獲得非常好的性能(如果原來的代碼寫得很差的話)。因此相比采用并行技術(shù),應(yīng)當(dāng)優(yōu)先選擇串行代碼優(yōu)化。一般來說,采用并行技術(shù)獲得的性能加速不超過核數(shù),這是一個非常大的限制,因?yàn)槟壳癈PU硬件生產(chǎn)商最多只能集成幾十個核。
從2006年開始,可編程的GPU越來越為大眾所認(rèn)可。GPU是圖形處理單元(Graphics Processing Unit)的簡稱,最初主要用于圖形渲染。自20世紀(jì)90年代開始,NVIDIA、AMD(ATI)等GPU生產(chǎn)商對硬件和軟件加以改進(jìn),GPU的可編程能力不斷提高,GPGPU(General-Purpose computing on Graphics Processing Units)比以前容易許多。另外,由于GPU具有比CPU更強(qiáng)大的峰值計(jì)算能力,引起了許多科研人員和企業(yè)的興趣。
近兩三年來,在互聯(lián)網(wǎng)企業(yè)中,GPU和并行計(jì)算越來越受到重視。無論是國外的Google、Facebook,還是國內(nèi)的百度、騰訊、阿里和360,都在使用代碼優(yōu)化、并行計(jì)算和GPU來完成以前不能完成的任務(wù)。
10年前,并行計(jì)算還是大實(shí)驗(yàn)室里教授們的研究對象,而今天,多核處理器和GPU的普及已經(jīng)使得普通人就可以研究它們。對于軟件開發(fā)人員來說,如果不掌握并行計(jì)算和代碼性能優(yōu)化技術(shù),在不久的將來就會被淘汰。
為了學(xué)習(xí)如何在X86和ARM平臺上向量化代碼,軟件開發(fā)人員需要了解Intel和ARM提供的參考資料,它們通常細(xì)節(jié)豐富,開發(fā)人員需要從多如牛毛的細(xì)節(jié)上(而且通常沒有示例)了解其概要,可謂難上加難。而本書通過豐富的簡單示例,讓讀者能夠從全局上把握這些擴(kuò)展的特性。
NVIDIA的CUDA和開放的OpenCL標(biāo)準(zhǔn)越來越得到大家的重視,OpenCL和CUDA在概念上有太多相似的地方,在本書中,筆者嘗試將它們放在一起描述,以便于讀者理解。
為了幫助讀者理解,本書使用了大量的示例。開發(fā)人員通常比較忙,因此本書力求簡潔明了,點(diǎn)到為止。
讀者對象
由于多核處理器和GPU已經(jīng)非常便宜,而代碼優(yōu)化、向量化和并行已經(jīng)深入IT行業(yè)的骨髓,所有IT行業(yè)的從業(yè)者都應(yīng)當(dāng)閱讀本書。如果非要列一個清單,筆者認(rèn)為下列人員應(yīng)當(dāng)閱讀:
·互聯(lián)網(wǎng)及傳統(tǒng)行業(yè)的IT從業(yè)者,尤其是希望將應(yīng)用移植到多核向量處理器或GPU上的開發(fā)人員
·對向量化和并行化感興趣的專業(yè)工作者
·高等院校、研究所的學(xué)生及教師
如何閱讀本書
本系列包括3本書,本書是此系列的第二本 。本書的重點(diǎn)在于介紹如何利用目前主流的C語言的各種特定硬件或平臺的向量化擴(kuò)展、并行化庫,來編寫和優(yōu)化串行代碼的性能。而本系列的第一本《并行算法設(shè)計(jì)與性能優(yōu)化》則關(guān)注并行優(yōu)化和并行計(jì)算相關(guān)的理論、算法設(shè)計(jì)及高層次的實(shí)踐經(jīng)驗(yàn)。本書同時關(guān)注C程序設(shè)計(jì)語言的向量化和并行化擴(kuò)展,以及算法到硬件的映射。
本書不但包括如何使用SSE/AVX向量化擴(kuò)展、如何使用OpenMP編譯制導(dǎo)語句優(yōu)化運(yùn)行在X86多核處理器上的代碼的性能,還包括如何使用NEON向量化擴(kuò)展、OpenMP編譯制導(dǎo)語句優(yōu)化運(yùn)行在移動處理器(ARM)上的代碼性能優(yōu)化,以及使用CUDA和OpenCL優(yōu)化運(yùn)行在圖形處理器(GPU)上的代碼性能優(yōu)化及并行。不但有實(shí)際的各個擴(kuò)展解析或語言的介紹說明,還有豐富的算法優(yōu)化實(shí)例。作者希望通過這種方式讓閱讀本書的軟件開發(fā)人員了解、掌握常見的向量化庫、并行編程語言,學(xué)會如何使用這些語言或庫,將常見算法映射到具體硬件上以獲得高性能,以及這些庫和語言的優(yōu)缺點(diǎn)。
整體而言,本書分為如下幾個部分:
·代碼向量化優(yōu)化,主要介紹常見的C語言的向量化庫,主要是X86平臺和ARM平臺的向量化擴(kuò)展。主要內(nèi)容見第1章和第2章。
·并行程序設(shè)計(jì)語言,主要介紹目前主流的并行程序設(shè)計(jì)語言O(shè)penMP、CUDA、OpenCL及OpenACC。主要內(nèi)容見第3~5章。
·主流的向量化和并行化硬件平臺,以及OpenCL程序如何映射到這些平臺上。主要介紹Intel Haswell、ARM A15、AMD GCN GPU和NVIDIA Kepler/Maxwell GPU的架構(gòu),及OpenCL程序如何在這些硬件上執(zhí)行。主要內(nèi)容見第6章。
·常見簡單應(yīng)用的向量化和并行化,主要介紹如何使用前面提到的向量化擴(kuò)展和并行語言來優(yōu)化圖像處理、線性代數(shù)應(yīng)用的性能。主要內(nèi)容見第7章和第8章。
第1章 主要介紹Intel SSE/AVX的C語言向量化擴(kuò)展(內(nèi)置函數(shù))的相關(guān)細(xì)節(jié),如支持哪些操作,使用AVX/SSE向量化時需要注意哪些問題。另外還介紹了如何在Intel X86上測得峰值,及如何使用SSE/AVX優(yōu)化一些實(shí)例代碼(這些示例由高洋提供)。
第2章 介紹了ARM A15高性能處理器的特性,及ARM提供的向量化擴(kuò)展(內(nèi)置函數(shù))NEON的細(xì)節(jié)。另外介紹了如何在ARM A15處理器上優(yōu)化彩色圖轉(zhuǎn)灰度圖、矩陣轉(zhuǎn)置和矩陣乘法等。
第3章 介紹了OpenMP程序設(shè)計(jì)的細(xì)節(jié)內(nèi)容。主要包括OpenMP的環(huán)境變量、函數(shù)和編譯制導(dǎo)語句。本章提供了許多OpenMP編譯制導(dǎo)語句構(gòu)造和子句的編程實(shí)例,以幫助讀者理解。本章還簡單介紹了OpenMP 4.0標(biāo)準(zhǔn)引入的異構(gòu)并行計(jì)算的內(nèi)容。并以如何使用OpenMP計(jì)算圓周率為例,介紹了OpenMP的互斥同步支持,并比較了這些不同同步方式的性能。
第4章 介紹了目前用于異構(gòu)并行計(jì)算平臺(主要是GPU)的CUDA和OpenCL的細(xì)節(jié)。首先介紹了基于GPU的異構(gòu)并行計(jì)算的歷史與現(xiàn)狀,及GPU和CPU的優(yōu)缺點(diǎn)。然后介紹了CUDA和OpenCL編程的細(xì)節(jié),并展示了如何使用CUDA和OpenCL來計(jì)算圓周率。接著介紹了如何基于GPU優(yōu)化CUDA和OpenCL程序性能。最后以矩陣轉(zhuǎn)置和矩陣乘法為例介紹了如何在GPU上優(yōu)化程序性能。
第5章 簡單介紹了用于異構(gòu)平臺的OpenACC標(biāo)準(zhǔn)。介紹了常見的OpenACC編譯制導(dǎo)語句,然后介紹了CUDA和OpenACC如何通過共享存儲器指針實(shí)現(xiàn)通信。最后以一個簡單的迭代算法為例,介紹了如何優(yōu)化OpenACC程序。
第6章 介紹了常見的并行編程硬件平臺的架構(gòu)及OpenCL程序如何映射到這些平臺上執(zhí)行。簡略介紹了Intel Haswell、ARM A15、AMD GCN GPU和NVIDIA Kepler/Maxwell GPU的架構(gòu)。然后介紹了OpenCL程序如何映射到Intel Haswell處理器、AMD GCN GPU和NVIDIA Kepler/Maxwell GPU上執(zhí)行。
第7章 詳細(xì)介紹了如何使用SSE/AVX、ARM NEON、OpenMP和CUDA來優(yōu)化常見的圖像處理應(yīng)用,比如均值濾波和中值濾波、圖像直方圖和曼德勃羅集。
第8章 詳細(xì)介紹了如何使用SSE/AVX、ARM NEON、OpenMP和CUDA來優(yōu)化兩向量距離和稠密矩陣向量乘法。
本書希望通過這種方式讓讀者漸進(jìn)地、踏實(shí)地?fù)碛胁⑿兴季S,了解各個向量化和并行化編程庫的優(yōu)缺點(diǎn),并且能夠?qū)懗鰞?yōu)良的向量化、并行代碼。
對并行和代碼優(yōu)化不太了解的人員,筆者希望你們按章節(jié)順序仔細(xì)閱讀本書;對并行或代碼優(yōu)化非常了解的人員,可按照需求選擇章節(jié)閱讀。
勘誤和支持
筆者的水平有限,工作繁忙,編寫時間倉促,而向量化、并行和代碼優(yōu)化又是一個正在高速發(fā)展、與硬件及算法密切相關(guān)、影響因素非常多、博大精深、又具有個人特色的領(lǐng)域,許多問題還沒有統(tǒng)一的解決方案。雖然筆者已經(jīng)努力確認(rèn)很多細(xì)節(jié),但書中難免會出現(xiàn)一些不準(zhǔn)確的地方,甚至是錯誤,懇請讀者批評指正。你可以將書中的錯誤或?qū)懙貌缓玫牡胤酵ㄟ^郵件發(fā)送到ly152832912@163.com,或微信聯(lián)系“風(fēng)辰”,以便再版時修正,筆者會盡快回復(fù)郵件。如果你有更多的寶貴意見,也歡迎發(fā)送郵件,期待能夠得到你們的真摯反饋。
致謝
首先要感謝我的老婆,她改變了我的人生軌跡,讓我意識到人生有如此多的樂趣。
感謝中國地質(zhì)大學(xué)(武漢)圖書館,那是使我對并行計(jì)算產(chǎn)生興趣的地方。感謝中國科學(xué)院研究生院和中國科學(xué)院圖書館,那里為我奠定了從事并行計(jì)算事業(yè)的基礎(chǔ)。
感謝我的朋友陳實(shí)富、賴俊杰、高洋、李修宇等,如果沒有你們,我會需要更多時間來提升水平。感謝我的領(lǐng)導(dǎo)王鵬、吳韌和湯曉歐,在這些“技術(shù)大佬”和“人生贏家”的指導(dǎo)下,我才會成長得如此迅速。
感謝機(jī)械工業(yè)出版社華章公司的高婧雅和楊福川,我本無意出版此書,是你們鼓勵我將它付梓成書;是你們幫我修改書稿,讓它變得可讀可理解;是你們幫我修正錯誤,是你們的鼓勵和幫助使得我順利完成全部書稿。
最后感謝我的爸爸、媽媽、姥姥、姥爺、奶奶、爺爺,感謝你們將我培養(yǎng)成人,并時時刻刻為我提供精神力量!
謹(jǐn)以此書獻(xiàn)給我最愛的家人,以及眾多熱愛代碼優(yōu)化、向量化、并行計(jì)算的朋友們!愿你們快樂地閱讀本書!
風(fēng)辰
- Python科學(xué)計(jì)算(第2版)
- 體驗(yàn)設(shè)計(jì)原理:行為、情感和細(xì)節(jié)
- Hadoop+Spark大數(shù)據(jù)分析實(shí)戰(zhàn)
- Java Web基礎(chǔ)與實(shí)例教程
- Monitoring Elasticsearch
- Learning AngularJS for .NET Developers
- 軟件供應(yīng)鏈安全:源代碼缺陷實(shí)例剖析
- 零基礎(chǔ)學(xué)C語言程序設(shè)計(jì)
- 軟件體系結(jié)構(gòu)
- Parallel Programming with Python
- Laravel 5.x Cookbook
- jQuery Essentials
- Spring Microservices
- Python程序設(shè)計(jì)案例教程
- 像程序員一樣使用MySQL