mpi冒泡排序并行化
一、实验目的与实验要求
1、实验目的
(1)学会将串行程序改为并行程序。
(2)学会mpich2的使用。
(3)学会openmp的配置。
(4)mpi与openmp之间的比较。
2、实验要求
(1)将串行冒泡程序局部并行化,以降低时间消耗。
(2) 理论上求出时间复杂度之比,根据结果得出时间消耗之比,进行比对分析。
二、实验设备(环境)及要求
Vs2013,mpich2
三、实验内容与步骤
1、实验一 mpi并行
(1)实验内容
1、写出一个冒泡排序程序,求出其时间复杂度,并运行得到相应的时间消耗。
2、将冒泡程序改为mpi并行程序:将全部需要排序的数分成4等份,分给四个进程一起冒泡,最后将所得的结果归到一个进程,进行归并排序,得到结果,得到时间消耗。算出时间复杂度。
3、对得出的结果进行讨论与分析。
(2)主要步骤
1、串行冒泡程序
时间复杂度:取所要排序的数的个数为n个,时间复杂度为n*n/2。
代码实现:
// maopao.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "stdlib.h" #include"time.h" ; int main(int argc, char* argv[]) { int zongshu[ARRAY_SIZE]; srand(); time_t now_time, end_time; ; i < ARRAY_SIZE; i++){ zongshu[i]=rand(); } now_time = time(NULL); ; i < ARRAY_SIZE; i++) { ; j > i; j--) { ]) { ]; zongshu[j - ] = zongshu[j]; zongshu[j] = z; } } } end_time = time(NULL); long shijian = end_time - now_time; ; i <ARRAY_SIZE; i++){ printf("%d ", zongshu[i]); } printf("所用时间:%ld",shijian); while (true); }
2、并行程序
时间复杂度:取所要排序的数的个数为n个,进程数为m个。时间复杂度:((n/m)*(n/m)/2)+n+4*n。
代码实现:
// MPITest.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "mpi.h" #include <stdio.h> #include <math.h> #include "stdlib.h" #define SIZE 4//进程数 ;//每个进程分配的个数 int shuzu[SIZE][ARRAY_SIZE]; int zonghanshu[SIZE][ARRAY_SIZE]; double endwtime; void Scatter_1(int); int main(int argc, char *argv[]){ int myid; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myid); Scatter_1(myid); MPI_Finalize(); } void Scatter_1(int myid){ int numtasks; srand(); ; i < SIZE; i++){ ; j < ARRAY_SIZE; j++){ shuzu[i][j] = rand(); } } //随机生成数组 int xiaopaixu[ARRAY_SIZE]; double startwtime = MPI_Wtime(); MPI_Comm_size(MPI_COMM_WORLD, &numtasks); if (numtasks == SIZE){ MPI_Scatter(shuzu, ARRAY_SIZE, MPI_INT, xiaopaixu, ARRAY_SIZE, MPI_INT, , MPI_COMM_WORLD); ; i <ARRAY_SIZE; i++){ ; j > i; j--){ ]){ ]; xiaopaixu[j - ] = xiaopaixu[j]; xiaopaixu[j] = z; } } }//每个进程里的冒泡排序 MPI_Gather(xiaopaixu, ARRAY_SIZE, MPI_INT, zonghanshu, ARRAY_SIZE, MPI_INT, , MPI_COMM_WORLD); int time[SIZE]; ; i < SIZE; i++){ time[i] = ; } int a[SIZE]; int zongpaixu2[ARRAY_SIZE*SIZE]; ; j >= ; j--){ ; k < SIZE; k++){ if (time[k] >= ARRAY_SIZE){ a[k] = ; } else { a[k] = zonghanshu[k][ARRAY_SIZE - time[k] - ]; } } ]; ; i<SIZE; i++){ if (a[i]>x){ x = a[i]; } } ; n < SIZE; n++){ if (x == a[n]){ time[n] = time[n] + ; break; } } zongpaixu2[j] = x; } endwtime = MPI_Wtime(); if (myid); else ; i < SIZE*ARRAY_SIZE; i++){ printf("%d ", zongpaixu2[i]); } } if (myid); else printf("wall clock time=% f\n", endwtime - startwtime); }
2、实验2
在实验一的基础上将程序改为openmp。
代码实现:(水平不高,写的程序通用性不好,只写了四线程的)
// Openmp.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <stdio.h> #include <math.h> #include "stdlib.h" #include"time.h" #include <omp.h> #define SIZE 4 ; int shuzu[SIZE][ARRAY_SIZE]; int xiaopaixu1[ARRAY_SIZE]; int xiaopaixu2[ARRAY_SIZE]; int xiaopaixu3[ARRAY_SIZE]; int xiaopaixu4[ARRAY_SIZE]; int zonghanshu[SIZE][ARRAY_SIZE]; int zongpaixu[ARRAY_SIZE*SIZE]; void xiaohansu(int *A, int l, int u){ for (int i = l; i <u; i++){ ; j > i; j--){ ]){ ]; A[j - ] = A[j]; A[j] = z; } } } } //每个线程排序 int main(int argc, char* argv[]) { int t1, t2; int i; int id; clock_t now_time, end_time; srand(); ; i < SIZE; i++){ ; j < ARRAY_SIZE; j++){ shuzu[i][j] = rand(); } } //随机生成数组 now_time = clock(); #pragma omp parallel default(none) shared(shuzu,xiaopaixu1,xiaopaixu2,xiaopaixu3,xiaopaixu4,ARRAY_SIZE) private(i) { #pragma omp for ; i < ARRAY_SIZE; i++)//这个for循环是并行的,将数组分为四份 { xiaopaixu1[i] = shuzu[][i]; xiaopaixu2[i] = shuzu[][i]; xiaopaixu3[i] = shuzu[][i]; xiaopaixu4[i] = shuzu[][i]; } } #pragma omp parallel default(none) shared(xiaopaixu1,xiaopaixu2,xiaopaixu3,xiaopaixu4,ARRAY_SIZE) { #pragma omp parallel sections { #pragma omp section xiaohansu(xiaopaixu1, , ARRAY_SIZE-);//排序 #pragma omp section xiaohansu(xiaopaixu2, , ARRAY_SIZE); #pragma omp section xiaohansu(xiaopaixu3, , ARRAY_SIZE); #pragma omp section xiaohansu(xiaopaixu4, , ARRAY_SIZE); } } ; i < ARRAY_SIZE; i++)//合到一份 { zonghanshu[][i]=xiaopaixu1[i]; zonghanshu[][i]=xiaopaixu2[i]; zonghanshu[][i]=xiaopaixu3[i]; zonghanshu[][i]=xiaopaixu4[i]; } int time[SIZE]; ; i < SIZE; i++){ time[i] = ; } int a[SIZE]; ; j >= ; j--){ ; k < SIZE; k++){ if (time[k] >= ARRAY_SIZE){ a[k] = ; } else { a[k] = zonghanshu[k][ARRAY_SIZE - time[k] - ]; } } ]; ; i<SIZE; i++){ if (a[i]>x){ x = a[i]; } } ; n < SIZE; n++){ if (x == a[n]){ time[n] = time[n] + ; break; } } zongpaixu[j] = x; } //归并 end_time = clock(); double shijian = end_time - now_time; ; i <SIZE*ARRAY_SIZE; i++){ printf("%d ", zongpaixu[i]); } printf("所用时间:%lf", shijian / CLK_TCK); while (true); }
四:实验结果与分析
Mpi:
串行
Mpi
|
1.2万 |
2.4万 |
3.6万 |
4.8万 |
6.0万 |
7.2万 |
串行(秒) |
0.441 |
1.766 |
3.951 |
6.877 |
10.469 |
14.687 |
6线(秒) |
0.029 |
0.108 |
0.242 |
0.435 |
0.656 |
0.940 |
4线(秒) |
0.035 |
0.151 |
0.339 |
0.615 |
0.969 |
1.409 |
2线(秒) |
0.119 |
0.502 |
1.108 |
2.040 |
3.121 |
4.516 |
从表中可以看出4线程的时候,并行程序的速度是串行程序速度的十倍之多,而理论上大概8倍。这就跟改的程序有关。在并行程序中,最后采用的是归并,由此,发生了这些奇妙的情况:实则本身的算法就比冒泡优一些,但又不能只采用冒泡算法,那样在最后又来个冒泡,其程序就没有意义了。
Openmp:
这是4.8万个数排序的结果,可以看出用了2.876秒,比MPI慢了四倍之多,这可能是程序的不合理,带来了多余的时间消耗(通信)。但比串行还是要快很多。
五:结论(讨论)
1、实验结论
1、就这冒泡排序改为并行的,虽然时间缩短了很多倍,但与快排等排序算法并行相比,其速度又不堪入目。
2、就冒泡排序而言,其mpi并行远远优于openmp(就我写的程序而言。。。),虽然最后都用了并归。
2、讨论
1、这些程序都实现在一台电脑上完成的,还未试过与其他电脑通信,所以其所表现出来的结果并不完全按正确,毕竟并行计算涉及到不同主机之间的通信。
2、由于个人编程能力不高,在这里只讨论了一些时间上的差异,并未对空间上进行比对(不会。。。)。
3、就openmp程序而言,应该还可以改写,增加其通用性和减少通信。
mpi冒泡排序并行化的更多相关文章
- kmeans算法并行化的mpi程序
用c语言写了kmeans算法的串行程序,再用mpi来写并行版的,貌似参照着串行版来写并行版,效果不是很赏心悦目~ 并行化思路: 使用主从模式.由一个节点充当主节点负责数据的划分与分配,其他节点完成本地 ...
- 使用 MPI for Python 并行化遗传算法
前言 本文中作者使用MPI的Python接口mpi4py来将自己的遗传算法框架GAFT进行多进程并行加速.并对加速效果进行了简单测试. 项目链接: GitHub: https://github.com ...
- 方阵行列式并行化计算(OpenMP,MPI),并计算加速比
00][100].在创建方阵时,方阵的阶数N(N<100)由外部输入.然后用两层"for循环"来给方阵 p左上角 N×N个位置赋值.具体实现如下: /* * 定义矩阵阶数N ...
- 大数据并行计算利器之MPI/OpenMP
大数据集群计算利器之MPI/OpenMP ---以连通域标记算法并行化为例 1 背景 图像连通域标记算法是从一幅栅格图像(通常为二值图像)中,将互相邻接(4邻接或8邻接)的具有非背景值的像素集合提取出 ...
- MPI编程简单介绍
第三章MPI编程 3.1 MPI简单介绍 多线程是一种便捷的模型,当中每一个线程都能够訪问其他线程的存储空间.因此,这样的模型仅仅能在共享存储系统之间移植.一般来讲,并行机不一定在各处理器之间共享存储 ...
- MPI编程简述
第三章MPI计划 3.1 MPI简单介绍 多线程是一种便捷的模型,当中每一个线程都能够訪问其他线程的存储空间.因此,这样的模型仅仅能在共享存储系统之间移植. 一般来讲,并行机不一定在各处理器之间共享存 ...
- mpi和cuda混合编程的正确编译
针对大数据的计算,很多程序通过搭建mpi集群进行加速,并取得了很好的效果.算法内部的加速,当前的并行化趋势是利用GPU显卡进行算法加速.针对并行性非常好的算法,GPU加速效果将远大于集群带来的加速效果 ...
- MPI编程简介[转]
原文地址http://blog.csdn.net/qinggebuyao/article/details/8059300 3.1 MPI简介 多线程是一种便捷的模型,其中每个线程都可以访问其它线程的存 ...
- win 10 在vs2017下对mpi的安装以及认识
这里我先对MPI进行一下简单的介绍,MPI的全称是Message Passing Interface,即消息传递接口. 它并不是一门语言,而是一个库,我们可以用Fortran.C.C++结合MPI提供 ...
随机推荐
- Codevs 2296 仪仗队 2008年省队选拔赛山东
2296 仪仗队 2008年省队选拔赛山东 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master 题解 题目描述 Description 作为体育委员,C君负责这次运动 ...
- Contest1065 - 第四届“图灵杯”NEUQ-ACM程序设计竞赛(个人赛)E粉丝与分割平面
题目描述 在一个平面上使用一条直线最多可以将一个平面分割成两个平面,而使用两条直线最多可将平面分割成四份,使用三条直线可将平面分割成七份--这是个经典的平面分割问题,但是too simple,作为一个 ...
- poj 1077 Eight(A*)
经典的八数码问题,用来练习各种搜索=_=.这题我用的A*做的,A*的主要思想就是在广搜的时候加了一个估价函数,用来评估此状态距离最终状态的大概距离.这样就可以省下很多状态不用搜索.对于每个状态设置一个 ...
- Poj 2586 / OpenJudge 2586 Y2K Accounting Bug
1.Link: http://poj.org/problem?id=2586 2.Content: Y2K Accounting Bug Time Limit: 1000MS Memory Lim ...
- 【转】Session与Cookie的比较
最近发现写博客也是提高学习效率的有效途径之一.好记性不如烂笔头,归纳总结时,你会发现总有一些东西你认为很熟了,它却在细微处讽刺你的错误.我学习COOKIE与SESSION时,几乎把社区所有相关的帖子都 ...
- ubuntu后台配置无线网络
一.静态配置: 1.编辑 /etc/network/interfaces: auto loiface lo inet loopback auto wlan0iface wlan0 inet stati ...
- c# 两个数组比较,将重复部分去掉,返回不重复部分
List<string> Ashuzu = new List<string>(); Ashuzu.Add("); Ashuzu.Add("); List&l ...
- MFC的规则DLL与扩展DLL
一.MFC规则DLL MFC规则DLL可以在该dll内部使用MFC,但是与应用程序的接口不能是MFC的.能够被所有支持dll的编程语言所写的应用程序使用,当然也包括使用MFC创建的应用程序.在 ...
- JSON参数解析工具类
/// <summary> /// 解析JSON参数 /// </summary> public class JSONParser { JObject jObj = null; ...
- jQuery实现页内查找相关内容
当需要在页面中查找某个关键字时,一是可以通过浏览器的查找功能实现,二是可以通过前端脚本准确查找定位,本文介绍通过jQuery实现的页面内容查找定位的功能,并可扩展显示查找后的相关信息. 本文以查找车站 ...