1. 程式人生 > >linux 平行計算之 openmp初探

linux 平行計算之 openmp初探

一:簡介

      OpenMP(Open Multi-Processing)是一種共享記憶體程式設計模式,多執行緒並行應用程式介面,使用C,C++和Fortran語言。由兩種形式實現並行功能:編譯指導語句執行時庫函式。編譯指導語句告訴程式何時開始並行,庫函式用來設定執行緒數及實現其它並行功能。

二:兩個小程式

     1. Hello_World.c 的並行

#include <stdio.h>
#include <omp.h>//呼叫Openmp庫函式
#define N 6

int main(int argc, char *argv[])
{
  int i;
  printf ("*Hello World! Thread: %d\n",
         omp_get_thread_num());

  #pragma omp parallel for
    for (i = 0; i < N; ++i)
      printf ("Hello World!  Thread: %d, i: %d\n",
              omp_get_thread_num(), i);
   return 0;
}

其中:#pragma omp parallel for 是編譯指導語句,宣告下面的for語句要並行多執行緒執行。

           omp_get_thread_num()是執行時的庫函式,用來獲取當前的執行緒號。

通過命令列

gcc -fopenmp Hello_World_omp.c -o hw_opmp

編譯,生成可執行檔案。執行程式:

./hw_opmp

結果如下:

$ ./hw_opmp
*Hello World! Thread: 0
Hello World!  Thread: 2, i: 4
Hello World!  Thread: 1, i: 2
Hello World!  Thread: 1, i: 3
Hello World!  Thread: 0, i: 0
Hello World!  Thread: 0, i: 1
Hello World!  Thread: 3, i: 5

可以看到,沒有並行時,預設只有一個執行緒,ID 為0;當並行時,有4個執行緒,即通過4個CPU 來同時處理,我的電腦只有4個CPU 核心。

2. matrix_multiply_openmp.cpp

#include<iostream>
#include<omp.h>
#include<time.h>//記錄程式執行時間
using namespace std;

int  main()
{ 
   int Matrix1[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
   int Matrix2[4][2]={2,3,5,4,7,9,8,0};
   int Matrix[3][2];
   clock_t start, end;//宣告型別為clock_t

   cout<<"Matrix1:\n";
   int i,j,k;
   for(i=0;i<3;i++){
      for(j=0;j<4;j++){
          cout<<Matrix1[i][j]<<'\t';
    }
    cout<<endl;
   }

  cout<<"Matrix2:\n";
  for(i=0;i<4;i++){
      for(j=0;j<2;j++){
          cout<<Matrix2[i][j]<<'\t';
    }
   cout<<endl;
  }

  for(i=0;i<3;i++){
     for(j=0;j<2;j++){
             Matrix[i][j]=0;
      }
  }
   
  omp_set_num_threads(3);
  int pnum=omp_get_num_procs();
  cout<<"Thread_pnum ="<<pnum<<endl;
  
 start=clock();//開始計時
#pragma omp parallel shared(Matrix1, Matrix2, Matrix) private(j,k)
{
#pragma omp for schedule(dynamic)
 for(i=0;i<3;i++){
     cout<<"Thread_num:"<<omp_get_thread_num()<<'\n';
     for(j=0;j<2;j++){
         for(k=0;k<4;k++){
                 Matrix[i][j]=Matrix[i][j]+Matrix1[i][k]*Matrix2[k][j];
         }
      }
  }
}
 end=clock();
 cout<<"Matrix multiply time:"<<(double (end-start))/CLOCKS_PER_SEC<<endl; //CLOCKS_PER_SEC為每秒敲鐘數,end-start是從開始到程式結束的總敲鐘數
 cout<<"The result is:\n";

 for(i=0;i<3;i++){
    for(j=0;j<2;j++){
     cout<<Matrix[i][j]<<'\t';
    }
   cout<<endl;
  }
 
 return 0;
}

其中:omp_set_num_threads(3);  設定程序數為3           omp_get_num_procs();  獲取本機處理器核數,我的是4核。

         #pragma omp parallel shared(Matrix1, Matrix2, Matrix) private(j,k)   編譯指導語句,並設定Matrix1,Matrix2, Matrix為共享,j,k為私有。這是為了讓3個程序都能使用Matrix1,Matrix2, Matrix,但每個程序計算自己的向量運算。          #pragma omp for //schedule(dynamic)  編譯指導語句,宣告下面的for迴圈,即第一個for迴圈進入3執行緒的平行計算。由於Matrix1是3行,故每個執行緒處理一行。schedule(dynamic)動態的為空閒程序分配指定大小的迴圈塊。

注意:並行化for的注意事項:

(1)迴圈語句規範,易於判斷迴圈次數;

(2)迴圈中不能包含允許迴圈提前退出的語句(將改變迴圈次數),如:break, return, exit.

命令列編譯:

g++ -fopenmp matrix_multiply_openmp.cpp -o mm_openmp

c++原始檔的編譯使用g++,  c原始檔的編譯使用gcc。

執行

./mm_openmp

$ ./mm_openmp
Matrix1:
1	2	3	4	
5	6	7	8	
9	10	11	12	
Matrix2:
2	3	
5	4	
7	9	
8	0	
Thread_pnum =4
Thread_num:Thread_num:Thread_num:0
2
3
Matrix multiply time:0.007634
The result is:
65	38	
153	102	
241	166	

可以看到程式使用了ID 為0,2,3的程序來處理第一個for迴圈。