一、并行編程
多線程和多進程編程,在早期一般是并發編程,現在基本是并行編程的基礎。或者干脆就叫并行編程也沒有什么可糾結的。但實際上并發編程和并行編程還是有著很大的不同。在前面的“多核和多CPU編程”系列中,已經對并發和并行的概念以及其不同進行了較深入的分析。如果有不太明白的,可以移步那個系列的文章。
這里之所以再次談起,主要是在寫線程的過程中,其實并發和并行往往是不分家的。一些常見的高并發處理的場景中,為了更好的利用多核和多CPU的優勢,往往會引入一些并行庫進行處理,目的只有一個,就是最大程度的壓榨CPU的潛力。
可是,并行庫的引入有利也有弊。最典型的就是一旦出現了線程間的問題,查找和定位問題就成了一個非常頭疼的故事。這個就需要非常有經驗的開發者不斷的進行各種分析和調度,甚至可以深入到庫內部進行查看問題的場景的發生路徑(前提是開源庫)。
二、并行庫和應用
這里不對并行的模式進行分析,只是介紹一下目前比較常見的并行庫:
1、OpenMp
這個可能是最常見的并行庫了,估計一般寫過并行程序的開發者或多或少都接觸過。簡單,易用。但功能上有一些限制,比如對非共享內存就有點不適應。
2、Intel TBB
TBB的應用因為有Intel背書,應用還是比較廣泛的,類似于圖的調度方式,更加靈活方便。抽象做的不錯。但可能和硬件關聯較強,畢竟誰家父母不喜歡自己家的孩子。
3、STL和Boost提供的并行庫
其實在這類庫提供的并行方式大多是基于函數接口方面的,更方便組合使用。特別是在c++11后提供了更多的并行算法如std::copy,std::find等等。
4、CUDA和OpenCL
這兩種比較偏向于GPU,當然OpenCL也支持CPU、FPGA等。OpenCL做為一種跨平臺的并行框架,支持的力度還需要加強。
其它并行庫還有,但多是比較專業了。
并行庫的應用,一般是對處理效率有著比較強的要求下才應用的。最常見的一般在大數據處理分析、圖像處理、音視頻處理以及一些科學計算等計算密集型與IO密集型緊密協調的情況下較多。
舉一個最常見的例子,需要對十張圖像進行灰度、編碼、壓縮等多道工序進行處理。那么并行庫的優勢就可以發揮出來。特別是當這個十張圖像的大小不一,壓縮的算法也要根據不同的情況進行壓縮時,那么處理時序就可以亂序(非輸入順序)進行處理。如果最終要求恢復時序,再做時序處理即可,如果不要求,則可以直接吐出結果。那么此時,對線程的處理就已經比較復雜了。那么如果增加到一百張、一千張甚至更多的圖像呢?
這樣做的結果,理論上講,單張處理最大的耗費時長即為十張圖像總處理的時長。這對于一些圖像處理算法,特別現在AI訓練時的意義可想而知。
三、例程
這里舉一個TBB的例子:
int main(){int ret = 0;broadcast_node<int> bNode(g);graph g;function_node< int, int > Sqr( g, 2, [](const int &data) {return data*data;} );function_node< int, int > Mul( g, 2, [](const int &data) {return data*3;} );function_node< int, int > Sum( g, 1, [&](const int &data ) -> int {return ret += v;} );make_edge( Sqr, Sum );make_edge( Mul, Sum );make_edge( bNode, Sqr );make_edge( bNode, Mul );for ( int i = 1; i < 20; ++i ) {bNode.try_put(i);}g.wait_for_all();std::cout << "result is " << ret << std::endl;return 0;
}
使用這種抽象的圖方式來組織并行線程間的數據流動非常有益,特別是在這些數據節點傳送時,需要動態切換的情況下,可以達到設計上的開閉原則而又不失靈活性。在Github上有不少使用TBB進行更高層的抽象應用的例子,推薦大家去學習一下。這些抽象的思想也可以應用在自己的多線程的應用上。
四、總結
古人說:“工欲善其事,必先利其器”,牛頓說要站在巨人的肩膀上,道理都是想通的。程序的設計開發也是如此,前人做過了很多非常有益的工作,后來者不必非再重復造一個輪子。但說這話得有一個前提,你得知道怎么造輪子,并且明白其內部的貓膩。
學以致用,用而后思。不斷總結推進自己的編程水平和提高自己的編程思想,這才是王道。
并行編程并不是本系列文章的目的,這里把并行編程的相關進行基礎的分析介紹,主要目的是讓開發者明白,所謂并行框架的基石,仍然是多線(進)程編程。只要掌握了這些基礎,那么在后期的學習和應用中,就會游刃有余!