CentOS6中OpenMP的運行時間或運行性能分析


OpenMp作為單機多核心共享內存並行編程的開發工具,具有編碼簡潔等,容易上手等特點。

關於OpenMP的入門,博主飲水思源(見參考資料)有了深入淺出,循序漸進的分析。做並行開發,做性能分析是永遠逃避不開的話題,性能問題的研究一切基於系統的計時。本人參考飲水思源的代碼在雙核與四核機器的操作過程中,發現clock()針對並行運行時間計時不准的問題,運行結果顯示並行方式和串行的時間基本相近,使得並行方式在時間計數上並未有明顯優勢。本文就其運行時間統計做相關分析,通過改進的方式,對時間進行了判斷,首先在For循環中加入打印語句判斷是否多核執行;然后判斷系統確實是多核執行后,在For循環中加入等待函數sleep,運行程序並人工計時,這時的時間在雙核機器並行比串行要快近兩倍,四核機器並行時間比串行快近四倍。所以可知clock()不適合做並行程序的計時工具,需要找到相關的替代。

    for (int i=0;i<10;i++)
    {
        std::cout<<"currend id: "<<omp_get_thread_num()<<std::endl;
        sleep(1);
        test();
    }

 

1、For循環的串行

新建SFor.cpp文件,內容為

 1 #include <iostream>
 2 #include <time.h>
 3 #include <stdio.h>
 4 #include <omp.h>
 5 void test()
 6 {
 7     int a = 0;
 8     for (int i=0;i<100000000;i++)
 9         a++;
10 }
11 int main()
12 {
13     struct timespec time1 = {0, 0};
14     struct timespec time2 = {0, 0};
15     clock_gettime(CLOCK_REALTIME, &time1);
16     std::cout<<"sec num: "<<time1.tv_sec<<"; nsec num:  "<<time1.tv_nsec<<std::endl;
17     //clock_t t1 = clock();
18     for (int i=0;i<10;i++)
19     {
20         //std::cout<<"currend id: "<<omp_get_thread_num()<<std::endl;
21         test();
22     }
23     //clock_t t2 = clock();
24     //std::cout<<"time: "<<t2-t1<<std::endl;
25     clock_gettime(CLOCK_REALTIME, &time2);
26     std::cout<<"sec num: "<<time2.tv_sec<<"; nsec num:  "<<time2.tv_nsec<<std::endl;
27     std::cout<<"time: "<<(time2.tv_sec-time1.tv_sec)*1000+(time2.tv_nsec-time1.tv_nsec)/1000000<<"ms"<<std::endl;
28 }

CentOS6.5 的GCC版本默認4.4.7,原生支持OpenMP編譯

[root@localhost MPDemo]# gcc --version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4)
通過編譯命令編譯源文件為:

g++ -fopenmp SFor.cpp -o sfor.out

[root@localhost MPDemo]# g++ -fopenmp PFor.cpp -o pfor.out
[root@localhost MPDemo]# ./sfor.out
sec num: 1386991744; nsec num:  676508350
sec num: 1386991748; nsec num:  245595277
time: 3570ms

2、For循環的並行

新建PFor.cpp文件,內容為

 1 #include <iostream>
 2 #include <time.h>
 3 #include <stdio.h>
 4 #include <omp.h>
 5 void test()
 6 {
 7     int a = 0;
 8     for (int i=0;i<100000000;i++)
 9         a++;
10 }
11 int main()
12 {
13     int coreNum = omp_get_num_procs();//獲得處理器個數
14     std::cout<<"cpu numbers: "<<coreNum<<std::endl;
15     struct timespec time1 = {0, 0};
16     struct timespec time2 = {0, 0};
17     clock_gettime(CLOCK_REALTIME, &time1);
18     std::cout<<"sec num: "<<time1.tv_sec<<"; nsec num:  "<<time1.tv_nsec<<std::endl;
19     //clock_t t1 = clock();
20     #pragma omp parallel for
21     for (int i=0;i<10;i++)
22     {
23         //std::cout<<"currend id: "<<omp_get_thread_num()<<std::endl;
24         test();
25     }
26     //clock_t t2 = clock();
27     //std::cout<<"time: "<<t2-t1<<std::endl;
28     clock_gettime(CLOCK_REALTIME, &time2);
29     std::cout<<"sec num: "<<time2.tv_sec<<"; nsec num:  "<<time2.tv_nsec<<std::endl;
30     std::cout<<"time: "<<(time2.tv_sec-time1.tv_sec)*1000+(time2.tv_nsec-time1.tv_nsec)/1000000<<"ms"<<std::endl;
31 }

 g++ -fopenmp PFor.cpp -o pfor.out

[root@localhost MPDemo]# ./pfor.out
cpu numbers: 2
sec num: 1386991842; nsec num:  452768086
sec num: 1386991844; nsec num:  527629070
time: 2074

3、分析總結

    clock_gettime能獲得納秒級的精度,1秒=10^9納秒。clock_gettime包含多種計時方式。
    a、CLOCK_REALTIME:系統實時時間,隨系統實時時間改變而改變
    b、CLOCK_MONOTONIC,從系統啟動這一刻起開始計時,不受系統時間被用戶改變的影響
    c、CLOCK_PROCESS_CPUTIME_ID,本進程到當前代碼系統CPU花費的時間
    d、CLOCK_THREAD_CPUTIME_ID,本線程到當前代碼系統CPU花費的時間

    本文默認采用CLOCK_REALTIME,即可實現並行程序的准確計時。示例代碼如下:

1     struct timespec time1 = {0, 0};
2     clock_gettime(CLOCK_REALTIME, &time1);
3     std::cout<<"sec num: "<<time1.tv_sec<<"; nsec num:  "<<time1.tv_nsec<<std::endl;

 

 

 

 

 

參考資料

參考比較好的入門資源:博主飲水思源的openMP的一點使用經驗


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM