OpenMP與MPI聯(lián)合編程
研究一下如何一起使用mpi和openmp
先上程序:
#include#include#ifdef?_OPENMP #include#endif #ifdef?MPICH_CC ??#include#endif #define?SIZE?512 #define?SIZEM?SIZE #define?SIZEN?SIZE #define?SIZEK?SIZE #define?DISPLAYT?1 double?mytic()? { double?result?=?0.0; struct?timeval?tv;? gettimeofday(?&tv,?NULL?); result?=?tv.tv_sec*1e6?+?tv.tv_usec; return?result; } int?main(int?argc,?char**?argv) { #ifdef?MPICH_CC int?mpirank; int?mpisize; MPI_Status?mpistatus; #endif float?*ma; float?*mb; float?*mc; int?m,?n,?k; int?r,?s,?t; float?tsum; double?tstart,?tend; #ifdef?MPICH_CC MPI_Init(&argc,?&argv); MPI_Comm_rank(MPI_COMM_WORLD,?&mpirank); #endif #ifdef?_OPENMP omp_set_num_threads(2); #endif /*Matrx?A,?B,?C?allocation.*/ m?=?SIZEM;?n?=?SIZEN;?k?=?SIZEK; ma?=?(float*)malloc(m*n*sizeof(float)); if?(!ma){return?-1;} mb?=?(float*)malloc(n*k*sizeof(float)); if?(!mb){free(ma);return?-1;} mc?=?(float*)malloc(m*k*sizeof(float)); if?(!mc){free(ma);free(mb);return?-1;} /*Matrx?A,?B,?C?initialization.*/ srand((unsigned?int)time(0)); tstart?=?mytic(); for?(r?=?0;?r?<?m;?r++) { for?(s?=?0;?s?<?n;?s++) { ma[r*n+s]?=?(1.0*rand())/RAND_MAX; } } #if?DISPLAYT? printf("[T]?ma?initialization?time?:?%.3fmsn",?1e-3*(mytic()-tstart)); #endif tstart?=?mytic(); for?(r?=?0;?r?<?n;?r++) { for?(s?=?0;?s?<?k;?s++) { mb[r*k+s]?=?(1.0*rand())/RAND_MAX; } } #if?DISPLAYT? printf("[T]?mb?initialization?time?:?%.3fmsn",?1e-3*(mytic()-tstart)); #endif /*Compute?matrix?C*/ tstart?=?mytic(); #pragma?omp?parallel?for?private(r,t,s,tsum)?shared(m,n,k,ma,mb,mc) for?(r?=?0;?r?<?m;?r++) { for?(t?=?0;?t?<?k;?t++) { tsum?=?0.0f; for?(s?=?0;?s?<?n;?s++) { tsum?+=?ma[r*n+s]*mb[s*k+t]; } mc[r*m+t]?=?tsum; } } #if?DISPLAYT? printf("[T]?mc?computation?time?:?%.3fmsn",?1e-3*(mytic()-tstart)); #endif #ifdef?MPICH_CC printf("[R]?rank?=?%d?with?",?mpirank); #pragma?omp?parallel? { if?(0==omp_get_thread_num()) { printf("omp_size?=?%dn",?omp_get_num_threads()); } } #endif #ifdef?MPICH_CC #endif #ifdef?MPICH_CC printf("MPI?--?parallel?n"); MPI_Finalize(); #else printf("???????serial???n"); #endif free(ma);free(mb);free(mc); return?0; }
使用如下命令編譯這個(gè)代碼
gcc?-DMPICH_CC?-O0?-fopenmp?test.c?`pkg-config?--cflags?--libs?mpich`?-o?mpiomp.exe
執(zhí)行代碼(我用的是mpich)
mpiexec?-n?2??./mpiomp.exe
上面啟動(dòng)了兩個(gè)進(jìn)程來執(zhí)行代碼。
程序中,每個(gè)進(jìn)程做的是一樣的事情,都是計(jì)算兩個(gè)矩陣的乘積,計(jì)算矩陣乘積的時(shí)候,我用openmp將矩陣乘積的計(jì)算分配給幾個(gè)不同的線程來計(jì)算,以增加并行度。
如果你想在執(zhí)行的時(shí)候設(shè)置openmp的線程數(shù),可以把代碼中第50行注釋掉,然后用下面的命令執(zhí)行。我是在ubuntu12.04上測試的,用的gcc-4.6.3,如果先不注釋執(zhí)行的話,再注釋后按下面的命令執(zhí)行的話,可能會(huì)得到跟之前一樣的結(jié)果。這個(gè)原因我不是很清楚。有知道的,煩請(qǐng)告知一下呀。
?mpiexec?-n?2?-env?OMP_NUM_THREADS?4?./mpiomp.exe
注意幾點(diǎn):
因?yàn)橛泻芏嘈率郑赡芤陨蟻韴?zhí)行不出來。所以給出一下幾個(gè)可能出問提的點(diǎn)。
* 是否安裝MPICH? 沒有安裝的話,麻煩先安裝。源碼安裝的看這里?點(diǎn)擊打開鏈接
* pkg-config出問題。 檢查下 mpich.pc是否在pkg-config的搜索路徑,或者man pkg-config研究下pkg-config