基於GCC的openMP學習與測試
(一)、openMP簡述
- 隨著CPU速度不再像以前那樣顯著提高,多核系統正變得越來越流行。為了利用這種能力,程序員在並行編程中變得很有知識變得越來越重要——讓程序同時執行多個任務。Open Multiprocessing (OpenMP) 框架是一種功能極為強大的規範,可以幫助您利用 C、C++ 和 Fortran 應用程序中的多個核心帶來的好處,是基於共享內存模式的一種並行編程模型, 使用十分方便, 只需要串行程序中加入OpenMP預處理指令, 就可以實現串行程序的並行化。
- 現在,openMP支持不同的編譯器,GCC、Clang++、Solaris Studio、Intel C Compiler
(二)、openMP簡單使用
1、簡單的HelloWord程序
- 代碼
-
#include <iostream> int main() { #pragma omp parallel { std::cout << "Hello World!\n"; } }
#pragma omp parallel
僅在您指定了-fopenmp
編譯器選項後才會發揮作用。在編譯期間,GCC 會根據硬件和操作系統配置在運行時生成代碼,創建盡可能多的線程。- 只運行 g++ hello.cpp,只會打印出一行Hello world!
- 運行g++ hello.cpp -fopenmp,打印出12個Hello World!(12是因為我用的是linux服務器默認分配的
- 運行結果
-
[email protected] ~/vsworksapce $ g++ hello.cpp [email protected] ~/vsworksapce $ ./a.out Hello World! [email protected]
2、如何自定義線程數量
- num_threads的設置
- omp_set_num_threads()庫函數的設置
- 代碼
-
#include <omp.h> #include <iostream> int main() { int number_threads = 1; omp_set_num_threads(number_threads) //方法二 #pragma omp parallel num_threads(number_threads) //方式一 { std::cout << "Hello World!\n"; } }
- OMP_NUM_THREADS環境變量的設置 (Linux下:export OMP_NUM_THREADS=4)
- 編譯器默認實現(一般而言,默認實現的是總線程數等於處理器的核心數)(不指定具體線程數量的情況下)
3、parallel sections 編譯指示
-
pragma omp sections
和pragma omp parallel
之間的代碼將由所有線程並行運行。pragma omp sections
之後的代碼塊通過pragma omp section
進一步被分為各個子區段。每個pragma omp section
塊將由一個單獨的線程執行。但是,區段塊中的各個指令始終按順序運行。 - 代碼
#include <iostream> int main() { #pragma omp parallel { std::cout << "parallel \n"; #pragma omp sections { #pragma omp section { std::cout << "section1 \n"; } #pragma omp section { std::cout << "sectio2 \n"; std::cout << "after sectio2 \n"; } #pragma omp section { std::cout << "sectio3 \n"; std::cout << "after sectio3 \n"; } } } }
//運行結果
[email protected] ~/vsworksapce $ g++ openMP12.cpp -fopenmp
[email protected] ~/vsworksapce $ ./a.out
parallel
section1
sectio2
after sectio2
sectio3
after sectio3
parallel
parallel
parallel
parallel
parallel
parallel
parallel
parallel
parallel
parallel
parallel
4、還有一些omp_get_wtime、for循環中的並行處理、OpenMP 實現鎖和互斥、以及firstprivate
和lastprivate
指令
等一些openMP的使用可以參考(https://www.ibm.com/developerworks/cn/aix/library/au-aix-openmp-framework/)。
(三)、openMP簡單測試
1、簡單的測試--不限制線程數量
- 代碼
#include <omp.h> #include <time.h> #include <iostream> #include <ctime> int main() { time_t start,end1; time( &start ); int a = 0; #pragma omp parallel for for (int i = 0; i < 100; ++i) { for (int j = 0; j < 1000000000; j++); //std::cout<< a++ << std::endl; } time( &end1 ); double omp_end = omp_get_wtime( ); std::cout<<std::endl; std::cout<<"Time_used " <<((end1 - start))<<"s"<<std::endl; std::cout<<"omp_time: "<<((omp_end - omp_start))<<std::endl; return 0; }
- 使用openMp
- 不使用openMP
- 從代碼的運行時間上可以看出使用openMP的運行時間明顯少於不使用openMP。
2、簡單的測試--限制線程數量
- 代碼
-
#include <omp.h> #include <time.h> #include <iostream> #include <ctime> int main() { time_t start,end1; time( &start ); int a = 0; double omp_start = omp_get_wtime( ); #pragma omp parallel for num_threads(8) for (int i = 0; i < 100; ++i) { for (int j = 0; j < 1000000000; j++); } time( &end1 ); double omp_end = omp_get_wtime( ); std::cout<<std::endl; std::cout<<"Time_used " <<((end1 - start))<<"s"<<std::endl; std::cout<<"omp_time: "<<((omp_end - omp_start))<<std::endl; return 0; }
- 線程數量 = 12
- 線程數量 = 8
-
- 線程數量 = 4
-
- 從線程數量測試結果能看出來,線程數量對程序運行時間也是有一定的影響的,影響的大小和程序運算數據量有關。
3、簡單測試--提升數據量,限制線程數量
- 代碼
-
#include <omp.h> #include <time.h> #include <iostream> #include <ctime> int main() { time_t start,end1; time( &start ); int a = 0; double omp_start = omp_get_wtime( ); #pragma omp parallel for num_threads(12) for (int i = 0; i < 1000; ++i) { for (int j = 0; j < 1000000000; j++); } time( &end1 ); double omp_end = omp_get_wtime( ); std::cout<<std::endl; std::cout<<"Time_used " <<((end1 - start))<<"s"<<std::endl; std::cout<<"omp_time: "<<((omp_end - omp_start))<<std::endl; return 0; }
- 線程數量 = 4 或者,上面的是線程數量 = 4,下面的是線程數量 = 4,下面的是線程數量 = 12,能夠看出來程序運行的時間是有一些差距的,如果繼續提升數據運算量,openMP的實驗效果會更加明顯。
4、簡單測試--降低數據量,限制線程數量
- 代碼
-
#include <omp.h> #include <time.h> #include <iostream> #include <ctime> int main() { time_t start,end1; time( &start ); int a = 0; double omp_start = omp_get_wtime( ); #pragma omp parallel for for (int i = 0; i < 1000; ++i) { for (int j = 0; j < 10000; j++); } time( &end1 ); double omp_end = omp_get_wtime( ); std::cout<<std::endl; std::cout<<"Time_used " <<((end1 - start))<<"s"<<std::endl; std::cout<<"omp_time: "<<((omp_end - omp_start))<<std::endl; return 0; }
- 當數據量很小的時候,使用或者不使用openMP對於程序的運行時間相差無幾
-
(四)、openMP學習參考
- 通過 GCC 學習 OpenMP 框架:https://www.ibm.com/developerworks/cn/aix/library/au-aix-openmp-framework/
-
Guide into OpenMP : http://bisqwit.iki.fi/story/howto/openmp/
基於GCC的openMP學習與測試