并行程序设计报告(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π計算公式:π=∫0141+x2dx\pi=\int_{0}^{1}{\frac{4}{1+x^2}}dxπ=∫01?1+x24?dx已知有如下兩種算法求其數值積分:
- 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/nfor(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.實驗結果及其分析
| 分割塊數 | 50000 | 100000 | 1000000 | 10000000 | 100000000 |
|---|---|---|---|---|---|
| 無并行(運行時間 s) | 0.00429 | 0.00620 | 0.05238 | 0.29442 | 2.79347 |
| 兩個進程并行(運行時間 s) | 0.00074 | 0.00145 | 0.01370 | 0.13708 | 1.38299 |
| 三個進程并行(運行時間 s) | 0.00052 | 0.00098 | 0.00936 | 0.08995 | 0.92909 |
| 四個進程并行(運行時間 s) | 0.00040 | 0.00074 | 0.00743 | 0.07731 | 0.77368 |
| 五個進程并行(運行時間 s) | 0.02835 | 0.03105 | 0.05499 | 0.12929 | 1.19763 |
| 六個進程并行(運行時間 s) | 0.03948 | 0.04632 | 0.05634 | 0.13655 | 1.10347 |
部分結果截圖如下:
結果分析:
| 分割塊數 | 50000 | 100000 | 1000000 | 10000000 | 100000000 |
|---|---|---|---|---|---|
| 無并行(加速比) | 1 | 1 | 1 | 1 | 1 |
| 兩個進程并行(加速比) | 5.79 | 4.27 | 3.82 | 2.14 | 2.01 |
| 三個進程并行(加速比) | 8.25 | 6.33 | 5.59 | 3.27 | 3.01 |
| 四個進程并行(加速比) | 10.73 | 8.38 | 7.05 | 3.80 | 3.61 |
| 五個進程并行(加速比) | 0.15 | 0.20 | 0.95 | 5.35 | 2.33 |
| 六個進程并行(加速比) | 0.11 | 0.13 | 0.92 | 2.15 | 2.53 |
從上圖可知,在我的計算機上當開四個進程時性能達到最大,因為我的計算機是四核的可以做到四個進程真正的并行 .當數據兩較小時,無并行的比并行的更快的主要原因是計算量小的時候MPI通信的時間占了進程時間開銷的大部分.
##三.Mandelbrot集##
1.問題描述
曼德勃羅特集是人類有史以來做出的最奇異,最瑰麗的幾何圖形,曾被稱為"上帝的指紋". 這個點集均出自公式zn+1=zn2+cz_{n+1}=z_n^2+czn+1?=zn2?+c,所有使得無限迭代后的結果能保持有限數值的復數c的集合構成曼德勃羅特集.假定迭代一定次數后的復數即為曼德勃羅特數,計算一定區間的曼德勃羅特集,并根據數字不同的迭代次數給該點設為不同的顏色.滑動鼠標,即可計算一定區域的曼德勃羅特集并顯示出來
2.程序概要設計
把區域分為n?nn*nn?n的區域按順序依次分給空閑的進程
//定義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實驗.結果及其分析
總結
以上是生活随笔為你收集整理的并行程序设计报告(MPI并行计算π,实现mandelbrot集)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《庾楼新岁》是谁的作品?
- 下一篇: 矩阵奇异值分解的几何意义(入门级教程)