研究一下如何一起使用mpi和openmp
先上程序:
#include <stdio.h>
#include <stdlib.h>
#ifdef _OPENMP
#include <omp.h>
#endif
#ifdef MPICH_CC
#include <mpi.h>
#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 : %.3fms\n", 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 : %.3fms\n", 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 : %.3fms\n", 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 = %d\n", 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