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提供 ...
 
随机推荐
- JavaScript的语法规则
			
JavaScript的语法规则 JavaScript区分大小写 JavaScript脚本程序须嵌入在HTML文件中 JavaScript脚本程序中不能包含HTML标记代码 每行写一条脚本语句 语句末尾 ...
 - VS2013编译WEBKIT
			
0,安装VS2013:DXSDK_Jun10.exe:QuickTimeSDK.exe 1,WebKit-r174650.tar.bz2 以管理员解压(非管理员解压最后几下总是报错) 2,设置环境变量 ...
 - Qt学习总结-ui篇(二)
			
qccs定义圆角 border-radius:10px; 如果想给特定位置定义圆角,如: 左上角:border-left-top-radius:10px; 右下角色:border-right-bo ...
 - MSDN 2005 安装问题
			
在安装玩Visual Studio MSDN 2005时,经常会出现这种问题:“无法显示 Microsoft 文档资源管理器,因为指定的帮助集合“ms-help://MS.MSDNQTR.v” 网上 ...
 - ALI OSS RequestTimeTooSkewed
			
php版阿里oss sdk,请求时抛RequestTimeTooSkewed错误,说时间差距太大,搜了一下发现是服务器的时间设置问题. 我们在安装完Centos Linux操作系统之后,点击系统的时间 ...
 - Linux C 程序 字符串函数(12)
			
字符串函数C语言的字符串处理函数1.puts函数 //把一个以'\0'结尾的字符串输出到屏幕 char a[] = "Welcome to"; char *p = "Li ...
 - bootstrap响应式网页设计的9条基本原则!
			
bootstrap响应式网页设计是针对多屏幕问题的一个很好的解决方案,但从印刷的视角来看有点困难.没有固定的页面尺寸,没有毫米或英寸,没有任何的物理限制,无从下手. 为了desktop和mobile单 ...
 - 利用javascript调用摄像头,可以配合socket开发监控系统
			
<html> <head> <meta http-equiv="content-type" content="text/html; char ...
 - [大牛翻译系列]Hadoop(1)MapReduce 连接:重分区连接(Repartition join)
			
4.1 连接(Join) 连接是关系运算,可以用于合并关系(relation).对于数据库中的表连接操作,可能已经广为人知了.在MapReduce中,连接可以用于合并两个或多个数据集.例如,用户基本信 ...
 - python学习之html从0开始(二)
			
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content ...