OpenMP与MPI联合编程
扫描二维码
随时随地手机看文章
研究一下如何一起使用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; }
使用如下命令编译这个代码
gcc -DMPICH_CC -O0 -fopenmp test.c `pkg-config --cflags --libs mpich` -o mpiomp.exe
执行代码(我用的是mpich)
mpiexec -n 2 ./mpiomp.exe
上面启动了两个进程来执行代码。
程序中,每个进程做的是一样的事情,都是计算两个矩阵的乘积,计算矩阵乘积的时候,我用openmp将矩阵乘积的计算分配给几个不同的线程来计算,以增加并行度。
如果你想在执行的时候设置openmp的线程数,可以把代码中第50行注释掉,然后用下面的命令执行。我是在ubuntu12.04上测试的,用的gcc-4.6.3,如果先不注释执行的话,再注释后按下面的命令执行的话,可能会得到跟之前一样的结果。这个原因我不是很清楚。有知道的,烦请告知一下呀。
mpiexec -n 2 -env OMP_NUM_THREADS 4 ./mpiomp.exe
注意几点:
因为有很多新手,可能以上来执行不出来。所以给出一下几个可能出问提的点。
* 是否安装MPICH? 没有安装的话,麻烦先安装。源码安装的看这里 点击打开链接
* pkg-config出问题。 检查下 mpich.pc是否在pkg-config的搜索路径,或者man pkg-config研究下pkg-config