并行程序设计报告(MPI并行计算π,实现mandelbrot集)

代码的github地址

一.熟悉MPI并行程序设计环境

1.硬件
电脑:HP暗夜精灵
内存:4G
处理器:ntel® Core™ i5-6300HQ CPU @ 2.30GHz × 4
显卡:NVIDIA 960M
这里写图片描述
2.软件
系统:Ubuntu 16.04LTS
MPI版本:MPICH2

二.计算 π \pi π

1.问题描述
已知 π \pi π计算公式: π = ∫ 0 1 4 1 + x 2 d x \pi=\int_{0}^{1}{\frac{4}{1+x^2}}dx π=011+x24dx已知有如下两种算法求其数值积分:

  • 1.用梯形面积进行数值计算
            这里写图片描述
  • 2.用矩形面积进行数值计算
             这里写图片描述
    2.程序概要设计(用梯形法计算)
MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);//把n广播给所有进程
        MPI_Barrier(MPI_COMM_WORLD);
        init_size=1.0/n;//把图形分为n个梯形,每个梯形的高为1/n
        for(int i=rank+1;i<=n;i+=proc_num)//每个进程计算n/proc_num个梯形
        {
            x1=init_size*(i);
            x2=init_size*(i-1);
            x1=4/(1+x1*x1);
            x2=4/(1+x2*x2);
            part_sum=part_sum+x1+x2;//把梯形的上底和下底计算到部分和中
        }
        temp_pi=init_size*part_sum/2;//计算该进程所计算的梯形面积和
  //归约函数,对所有进程所计算的面积求和即是pi值 
       MPI_Reduce(&temp_pi,&cal_pi,1,MPI::DOUBLE,MPI::SUM,0,MPI_COMM_WORLD);

3.实验结果及其分析

分割块数50000100000100000010000000100000000
无并行(运行时间 s)0.004290.006200.052380.294422.79347
两个进程并行(运行时间 s)0.000740.001450.013700.137081.38299
三个进程并行(运行时间 s)0.000520.000980.009360.089950.92909
四个进程并行(运行时间 s)0.000400.000740.007430.077310.77368
五个进程并行(运行时间 s)0.028350.031050.054990.129291.19763
六个进程并行(运行时间 s)0.039480.046320.056340.136551.10347

部分结果截图如下:
     这里写图片描述
     这里写图片描述
结果分析: 
         这里写图片描述

分割块数50000100000100000010000000100000000
无并行(加速比)
两个进程并行(加速比)5.794.273.822.142.01
三个进程并行(加速比)8.256.335.593.273.01
四个进程并行(加速比)10.738.387.053.803.61
五个进程并行(加速比)0.150.200.955.352.33
六个进程并行(加速比)0.110.130.922.152.53

从上图可知,在我的计算机上当开四个进程时性能达到最大,因为我的计算机是四核的可以做到四个进程真正的并行 .当数据两较小时,无并行的比并行的更快的主要原因是计算量小的时候MPI通信的时间占了进程时间开销的大部分.
##三.Mandelbrot集##
1.问题描述
曼德勃罗特集是人类有史以来做出的最奇异,最瑰丽的几何图形,曾被称为"上帝的指纹". 这个点集均出自公式 z n + 1 = z n 2 + c z_{n+1}=z_n^2+c zn+1=zn2+c,所有使得无限迭代后的结果能保持有限数值的复数c的集合构成曼德勃罗特集.假定迭代一定次数后的复数即为曼德勃罗特数,计算一定区间的曼德勃罗特集,并根据数字不同的迭代次数给该点设为不同的颜色.滑动鼠标,即可计算一定区域的曼德勃罗特集并显示出来
2.程序概要设计
           这里写图片描述
           把区域分为 n ∗ n n*n nn的区域按顺序依次分给空闲的进程

//定义Zn+1=Zn^2+c的运算
  ComplexNumber f(ComplexNumber z, ComplexNumber c) 
    {   
        ComplexNumber result;   
        result.real=c.real+z.real*z.real-z.imag*z.imag;   
        result.imag=c.imag+z.imag*z.real+z.real*z.imag;   
        return result;  
    }   
//定义曼德勃罗特的计算步骤,并在recv数组中记录该点迭代的次数
 void Mandelbrot(double Xmin,double dx, int xloop, int xfrom, double Ymin,  double dy, int yloop, int yfrom)   
    {   
        int x, y, k;   
        ComplexNumber c, z;   
        for (x=0; x<xloop; x++)   
        {   
            c.real = Xmin+x*dx;   
            for (y=0; y<yloop; y++)   
            {   
                c.imag = Ymin+y*dy;   
                z.real = z.imag = 0.0f;   
                k = 0;   
                while (k<MAX_ITERATE_DEPTH && (z.real*z.real+z.imag*z.imag)<=MAX_MAGNITUDE)   
                {   
                    z = f(z, c);   
                    k++;   
                }   
                recv[xfrom+x][yfrom+y] = k;   
            }   
        }   
    }   
                // 对于一个进程如果接收到了再计算的命令,就计算分配给他的区域的曼德勃罗特集,区域信息存在info结构体中
                if (Redo == status.MPI_TAG)   
                    {   
                        MPI_Recv(&info,1,AreaType,0,Redo,MPI_COMM_WORLD,&status);   
                        int txfrom=(info.xloop%slave_num)*info.sub_xloop;
                        double tymin=(info.xloop/slave_num)*info.Yarea/slave_num+info.Ymin;
                        int tyfrom=(info.xloop/slave_num)*info.sub_yloop; 
                        Mandelbrot(txmin,info.dx,info.sub_xloop,txfrom,tymin,info.dy,info.sub_yloop,tyfrom);
                        MPI_Send(&info.xloop,1,MPI_INT,0,Over,MPI_COMM_WORLD);
                        MPI_Send(recv,PIXEL_NUM,MPI_SHORT,0,Over,MPI_COMM_WORLD);   
                        printf("send from slave %d\n", rank-1);   
                    }   
   //opengl的闲时回调函数,主进程一直再执行该函数,接受子进程的数据,当接受到一个进程发来的数据时,
   主进程判断还有无未计算的区域,如果有就分配给该进程
    void Idle()    
    {   
        //printf("34");
        static int recved = 0;   
        int pos;
        int i, j, x, y;   
        int xfrom, yfrom;   
        int flag, slave_rank;   
        MPI_Status status;   
        MPI_Iprobe(MPI_ANY_SOURCE,Over,MPI_COMM_WORLD, &flag, &status);   
        if (!flag)  return;   
        MPI_Recv(&pos,1,MPI_INT,status.MPI_SOURCE,Over,MPI_COMM_WORLD,&status);
        MPI_Recv(recv,PIXEL_NUM,MPI_SHORT,status.MPI_SOURCE,Over,MPI_COMM_WORLD,&status);   

        if (slave_num*slave_num== ++recved)   
        {   
            recved = 0;   
            end_time = MPI_Wtime();    
            printf("wall clock time = %f\n", end_time-start_time);   
        }   
        slave_rank = status.MPI_SOURCE-1;   
        printf("recieve from slave %d\n", slave_rank);   
        i = slave_rank;   
        xfrom = (pos%slave_num)*info.sub_xloop;   
        yfrom = (pos/slave_num)*info.sub_yloop;       
        for(x=0; x<info.sub_xloop; x++)   
        {   
                for (y=0; y<info.sub_yloop; y++)   
                    indices[xfrom+x][yfrom+y] = recv[xfrom+x][yfrom+y];   
        }
        if(count<slave_num*slave_num)
       {
        MPI_Send(&part[count],1,AreaType,slave_rank+1,Redo,MPI_COMM_WORLD);   
        count++;
        }
        glutPostRedisplay();
    }  

3实验.结果及其分析
  这里写图片描述
  这里写图片描述
  这里写图片描述

  • 6
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值