1. 程式人生 > >基於GCC的openMP學習與測試

基於GCC的openMP學習與測試

分配 exp -s 模式 after intel tel soft double

(一)、openMP簡述

  • 隨著CPU速度不再像以前那樣顯著提高,多核系統正變得越來越流行。為了利用這種能力,程序員在並行編程中變得很有知識變得越來越重要——讓程序同時執行多個任務。Open Multiprocessing (OpenMP) 框架是一種功能極為強大的規範,可以幫助您利用 C、C++ 和 Fortran 應用程序中的多個核心帶來的好處,是基於共享內存模式的一種並行編程模型, 使用十分方便, 只需要串行程序中加入OpenMP預處理指令, 就可以實現串行程序的並行化。
  • 現在,openMP支持不同的編譯器,GCCClang++Solaris StudioIntel C Compiler
    Microsoft Visual C++等。程序員在編程時,只需要在特定的源代碼片段的前面加入OpenMP專用的 #pargma omp 預編譯指令,就可以“通知”編譯器將該段程序自動進行並行化處理,並且在必要的時候加入線程同步及通信機制。當編譯器選擇忽略#pargma omp預處理指令時,或者編譯器不支持OpenMP時,程序又退化為一般的通用串行程序,此時,代碼依然可以正常運作,只是不能利用多線程和多核CPU來加速程序的執行而已。

(二)、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]
/* */ ~/vsworksapce $ g++ hello.cpp -fopenmp [email protected] ~/vsworksapce $ ./a.out Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!

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 sectionspragma 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 實現鎖和互斥、以及firstprivatelastprivate指令

等一些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學習與測試