基於GCC的openMP學習與測試


(一)、openMP簡述

  •   Open Multiprocessing (OpenMP) 框架是一種功能極為強大的規范,可以幫助您利用 C、C++ 和 Fortran 應用程序中的多個核心帶來的好處,是基於共享內存模式的一種並行編程模型, 使用十分方便, 只需要串行程序中加入OpenMP預處理指令, 就可以實現串行程序的並行化。

(二)、openMP簡單使用

   1、簡單的HelloWord程序

  • #include <iostream>
    int main()
    {
      #pragma omp parallel
      {
        std::cout << "Hello World!\n";
      }
    }
    View Code
  • #pragma omp parallel 僅在您指定了 -fopenmp 編譯器選項后才會發揮作用。在編譯期間,GCC 會根據硬件和操作系統配置在運行時生成代碼,創建盡可能多的線程。
  • 只運行 g++ hello.cpp,只會打印出一行Hello world!
  • 運行g++ hello.cpp -fopenmp,打印出12個Hello World!(12個是因為我用的是linux服務器默認分配的)
  • 運行結果
  • user@NLP ~/vsworksapce $ g++ hello.cpp 
    user@NLP ~/vsworksapce $ ./a.out 
    Hello World!
    user@NLP ~/vsworksapce $ g++ hello.cpp -fopenmp 
    user@NLP ~/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!
    View Code

    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";
      }
    }
    View Code
  • 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";
          }
        }
      }
    }
    
    //運行結果
    user@NLP ~/vsworksapce $ g++ openMP12.cpp -fopenmp
    user@NLP ~/vsworksapce $ ./a.out 
    parallel 
    section1 
    sectio2 
    after sectio2 
    sectio3 
    after sectio3 
    parallel 
    parallel 
    parallel 
    parallel 
    parallel 
    parallel 
    parallel 
    parallel 
    parallel 
    parallel 
    parallel
    View Code

  4還有一些omp_get_wtime、for、while循環中的並行處理、OpenMP critical section、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;
    }
     
    View Code
  • 從下面的圖表可以看出使用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;
    }
    View Code
  • 從下面的圖表能夠看出,線程數量對程序運行時間也是有一定的影響的,影響的大小和程序運算數據量有關。

  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;
    }
    View Code
  • 線程數量對程序的運行時間是有影響的,如果繼續提升數據運算量,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;
    }
    View Code
  • 當數據量很小的時候,使用或者不使用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/

 


免責聲明!

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



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