前陣子用兩種方法實現(xiàn)了一個算法挨措,第一個方法只用CPU完成計算,第二個方法用到了GPU斩松。被運行結(jié)果嚇了一跳觉既,GPU比我單機(jī)CPU跑的程序快了一百倍。既然并行計算對性能的提升真不是蓋的钧椰,于是決定把CPU的程序也改成并行的演侯。今天簡單介紹一下Linux下用C++開發(fā)并行程序的方法背亥。
使用C++在Linux下開發(fā)并行程序要調(diào)用一個頭文件,它里面提供了很多實現(xiàn)并行運算的函數(shù)狡汉。調(diào)用它的方法就是在文件開頭添加:
#include
有了這個頭文件之后盾戴,就可以開始我們的C++并行化之旅了。
首先橄仆,我覺得有必要看看服務(wù)器上有多少個CPU盆顾。方法很簡單畏梆,pthread.h提供了一個函數(shù)叫sysconf(int),用它可以查看系統(tǒng)配置的參數(shù)。參數(shù)是_SC_NPROCESSORS_CONF的時候表示查看系統(tǒng)的CPU個數(shù)宪巨。于是我們可以寫這樣一個程序
#include”stdio.h”
#include”pthread.h”
int main(int argv, char* argc[])
{
cout<
return 0;
}
運行結(jié)果如下:
可以看出我用的服務(wù)器里面有32個CPU捏卓。給sysconf()傳其他的參數(shù)就可以查看系統(tǒng)相應(yīng)的參數(shù)天吓,有興趣可以網(wǎng)上搜一下各種參數(shù)的介紹。
需要注意一點,使用pthread.h的時候需要在編譯命令后面加–lpthread汤功,否則的話編譯器不能識別pthread.h里面的函數(shù),就像下面這樣:
我以前寫過一篇介紹Linux編程基本知識的帖子色解,如果對上圖中的命令不太理解的話可以參照一下餐茵。
pthread.h是利用函數(shù)實現(xiàn)多線程的:程序猿把需要線程完成的任務(wù)寫成到一個函數(shù)里忿族。如果直接運行這些函數(shù),那么他們?nèi)匀幌褚郧耙粯佣际琼樞驁?zhí)行的错英。但如果用pthread.h提供的方法去調(diào)用這個函數(shù)椭岩,它就會變成一個獨立的線程了璃赡。下面舉個栗子:
我們準(zhǔn)備寫兩個線程,第一個線程顯示十次:“我是一號線程”塌计,另一個線程顯示十次“我是二號線程”夺荒×颊簦可以想象,如果直接調(diào)用兩個函數(shù)剿吻,我們會看到十次“我是一號線程”丽旅,然后看到緊接著的十個“我是二號線程”。如果我們用pthread.h提供的方法調(diào)用他們會有什么效果呢榄笙?直接看運行效果:
多看幾次就更清楚了:
發(fā)現(xiàn)了吧帆卓,兩個線程的執(zhí)行順序是不確定的剑令。這就是并行計算的效果:各各線程之間獨立運行拄查,齊頭并進(jìn)“啵可以想象潮酒,如果能把一個大任務(wù)分解成若干獨立的小任務(wù)躯舔,然后使用并行計算的方法尊浪,運算速度將會大大提高桨螺。
現(xiàn)在解釋一下上面的例子是怎么實現(xiàn)的:
首先定義兩個函數(shù)脐嫂,task1和task2,他們是兩個線程的主體汞贸,然后在main函數(shù)里使用pthread.h提供的方法調(diào)用task1和task2。產(chǎn)生新線程的方法可以被比喻成放風(fēng)箏门驾。在放風(fēng)箏的時候奶是,我們通過一根線來控制風(fēng)箏,以防止它亂飛秆麸。同樣沮趣,我們也不希望產(chǎn)生的線程亂運行豁生,需要一根線來控制新的線程,pthread_t就是pthread.h提供給我們的控制線,它記錄新線程的編號迅脐。顧名思義谴蔑,pthread_create就是產(chǎn)生新線程的過程了。在上面的例子中窃躲,我們使用pthread_create把task1和task2變成了兩個獨立的線程钦睡,并用ThreadA和ThreadB記錄他們的線程號荞怒。pthread_join的意思是main函數(shù)在此等待ThreadA和ThreadB記錄的線程運行結(jié)束。