MPI及并行化积分运算

参考:1. MPI编程 – http://blog.csdn.net/gexplore/article/details/7078832
2. MPI 实现梯形积分法 – http://blog.csdn.net/u012417189/article/details/25717263
1. MPI简介
多线程是一种便捷的模型,其中每个线程都可以访问其它线程的存储空间。因此,这种模型只能在共享存储系统之间移植。一般来讲,并行机不一定在各处理 器之间共享存储,当面向非共享存储系统开发并行程序时,程序的各部分之间通过来回传递消息的方式通信。要使得消息传递方式可移植,就需要采用标准的消息传 递库。这就促成的消息传递接口(Message Passing Interface, MPI)的面世,MPI是一种被广泛采用的消息传递标准。
与OpenMP并行程序不同,MPI是一种基于消息传递的并行编程技术。消息传递接口是一种编程接口标准,而不是一种具体的编程语言。简而言之,MPI标准定义了一组具有可移植性的编程接口。各个厂商或组织遵循这些标准实现自己的MPI软件包,典型的实现包括开放源代码的MPICH、LAM MPI以及不开放源代码的Intel MPI。由于MPI提供了统一的编程接口,程序员只需要设计好并行算法,使用相应的MPI库就可以实现基于消息传递的并行计算。MPI支持多种操作系统,包括大多数的类UNIX和Windows系统。

2. 基本接口函数

  1. int _t main(int argc, _TCHAR* argv[]){      
  2.     int rank, size;   
  3.     MPI_Init(&argc, &argv);   
  4.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);   
  5.     MPI_Comm_size(MPI_COMM_WORLD, &size);   
  6.     printf(“Hello World from thread %d of %d\n”, rank, size);   
  7.     MPI_Finalize();   
  8.     return 0;   
  9. }  

这个程序比较简单,在函数MPI_Init()和MPI_Finalize()之间是程序并行执行的地方
MPI_Init()、MPI_Comm_rank()、MPI_Comm_size()和MPI_Finalize(),这四个函数是MPI中最重要和最常用的函数。

(1) MPI_Init和MPI_Finalize
MPI_Init用来初始化MPI执行环境,建立多个MPI进程之间的联系,为后续通信做准备。而MPI_Finalize则是结束MPI执行环境。这两个函数就是定义MPI程序的并行区的,除了检测是否初始化的函数之外,不应该在这两个函数定义的区域外调用其它MPI函数。这两个函数都返回整型值,标识函数是否调用成功。

(2) MPI_Comm_rank
MPI_Comm_rank函数就是用来标识各个MPI进程的,给出调用该函数的进程的进程号。MPI_Comm_rank返回整型的错误值,需要提供两个参数:
l MPI_Comm类型的通信域,标识参与计算的MPI进程组。上面例子中使用的是MPI_COMM_WORLD,这个进程组是MPI实现预先定义好的进程组,指的是所有MPI进程所在的进程组。如果想要申请自己的特殊的进程组,则需要通过MPI_Comm定义并通过其它MPI函数生成。
l &rank返回调用进程中的标识号。
MPI还定义了另一个进程组MPI_COMM_SELF,只包含各个进程自己的进程组。

(3) MPI_Comm_size
这个函数则用来标识相应进程组中有多少个进程,它也有两个参数:
l MPI_Comm类型的通信域,标识参与计算的MPI进程组。上面的例子中用的是MPI_COMM_WORLD。
l &size返回相应进程组中的进程数。
运行这个程序, 按照并行执行的方式,上面程序运行结果应该打印两行文字信息,为:
Hello World from thread 0 of 2
Hello World from thread 1 of 2

3. 为了验证程序并行化后的效果,MPI提供了两个用于统计时间的函数 MPI_Wtime和MPI_Wtick。其中MPI_Wtime返回一个双精度数,表示从过去某点的时刻到当前时刻所消耗的时间秒数。而函数MPI_Wtick则返回MPI_Wtime结果的精度。

4. 并行化梯形积分运算
梯形面积和 = h * ( f(x0)/2 + f(x1) + ……. + f(xn)/2) h = (b-a)/n;

  1. // 正常版伪代码   
  2. h= (b-a)/n;   
  3. approx = (f(a)+f(b))/2.0;   
  4. for (int i=1;i<n;i++){   
  5.     x_i = a + i*h;   
  6.     approx += f(x_i);   
  7. }   
  8. approx = h*approx;  

并行化需要考虑这几个步骤 1.将问题的解决方案划分为多个任务 2.在任务间识别出需要的通信信道 3.将任务聚合成符合任务 4.在核上分配复合任务

计算每一个小梯形的面积 和 计算这些梯形的面积和

  1. Get a,b,n;   
  2. h = (b-a)/n;   
  3. local_n = n/comm_sz;   
  4. local_a = a + my_rank*local_n*h;   
  5. local_b = local_a +  local_n*h;   
  6. local_integral = Trap(local_a,local_b,local_n,h);  // 面积的串行实现   
  7. if(my_rank !=0){   
  8. send local_intergral to process 0;   
  9. }   
  10. else  
  11.  total_intergral = local_intergral;   
  12. for(proc = 1; proc<comm_sz;proc++){   
  13. receive local_intergal from proc;   
  14. total_intergral += local_intergral;   
  15. }   
  16. if(my_rank == 0)   
  17.  print result  

完整程序,n是comm_sz的整数倍

  1. int main(){   
  2.     int my_rank,comm_sz,n=1024,local_n;   
  3.     double a = 0.0, b = 3.0,h,local_a,local_b,local_int,total_int;   
  4.     int source;   
  5.     MPI_Init(NULL,NULL);   
  6.     MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);   
  7.     MPI_Comm_size(MPI_COMM_WORLD,&comm_sz);   
  8.     h = (b-a)/n; //间隔   
  9.     local_n = n / comm_sz; // 分为local_n个梯形, 每个梯形有comm_sz 个子问题   
  10.     local_a = a + my_rank*local_n*h;   
  11.     local_b = local_a + local_n*h;   
  12.     local_int = Trap(local_a,local_b,local_n,h);   
  13.     if (my_rank!=0)   
  14.     {   
  15.         MPI_Send(&local_int,1,MPI_DOUBLE,0,0,MPI_COMM_WORLD);   
  16.     }   
  17.     else{   
  18.         total_int = local_int;   
  19.         for (source =1;source<comm_sz;source++)   
  20.         {   
  21.             MPI_Recv(&local_int,1,MPI_DOUBLE,source,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE);   
  22.             total_int += local_int;   
  23.         }   
  24.   
  25.     }   
  26.     if (my_rank ==0)   
  27.     {   
  28.         printf(“With n = %d trapezoids, our estimation\n”,n);   
  29.         printf(“of the integral from %f to %f = %.15e\n”,a,b,total_int);   
  30.     }   
  31.     MPI_Finalize();   
  32.     return 0;   
  33. }  

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>