QuickSort (MPI 实现)

  //
  #include "stdafx.h"
  #include"mpi.h"
  #include<iostream>
  #include <stdlib.h>
  #include <stdio.h>
  using namespace std;
  #define TRUE 1
  /*
  * 函数名: Partition
  * 功能:对起止位置为wht_start和wht_end的数组序列,将其分成两个非空子序列,
  * 其中前一个子序列中的任意元素小于后个子序列的元素。
  * 输入:无序数组wht_data[1,n]
  * 返回: 两个非空子序列的分界下标
  */
  double wht_start_time,wht_end_time;
  int Partition(int *wht_data,int wht_start,int wht_end)
  {
  int wht_pivo;
  int wht_i, wht_j;
  int wht_tmp;
  wht_pivo=wht_data[wht_end];
  wht_i=wht_start-1; /*wht_i(活动指针)*/
   
  for(wht_j=wht_start;wht_j<wht_end;wht_j++)
  if(wht_data[wht_j]<=wht_pivo)
  {
  wht_i++; /*wht_i表示比wht_pivo小的元素的个数*/
  wht_tmp=wht_data[wht_i];
  wht_data[wht_i]=wht_data[wht_j];
  wht_data[wht_j]=wht_tmp;
  }
  wht_tmp=wht_data[wht_i+1];
  wht_data[wht_i+1]=wht_data[wht_end];
  wht_data[wht_end]=wht_tmp; /*以wht_pivo为分界,wht_data[wht_i+1]=wht_pivo*/
  return wht_i+1;
  }
  /*
  * 函数名: QuickSort
  * 功能:对起止位置为wht_start和wht_end的数组序列,进行串行快速排序。
  * 输入:无序数组wht_data[1,n]
  * 返回:有序数组wht_data[1,n]
  */
  void QuickSort(int *wht_data,int wht_start,int wht_end)
  {
  int wht_r;
  int wht_i;
  if(wht_start<wht_end)
  {
  wht_r=Partition(wht_data,wht_start,wht_end);
  QuickSort(wht_data,wht_start,wht_r-1);
  QuickSort(wht_data,wht_r+1,wht_end);
  }
  }
  /*
  * 函数名: exp2
  * 功能:求2的wht_num次幂
  * 输入:int型数据wht_num
  * 返回: 2的wht_num次幂
  */
  int exp2(int wht_num)
  {
  int wht_i;
  wht_i=1;
  while(wht_num>0)
  {
  wht_num--;
  wht_i=wht_i*2;
  }
  return wht_i;
  }
  /*
  * 函数名: log2
  * 功能:求以2为底的wht_num的对数
  * 输入:int型数据wht_num
  * 返回: 以2为底的wht_num的对数
  */
  int log2(int wht_num)
  {
  int wht_i, wht_j;
  wht_i=1;
  wht_j=2;
  while(wht_j<wht_num)
  {
  wht_j=wht_j*2;
  wht_i++;
  }
  if(wht_j>wht_num)
  wht_i--;
  return wht_i;
  }
   
  /*
  * 函数名: Getwht_dataSize
  * 功能:读入待排序序列长度
  */
  int Getwht_dataSize()
  {
  double wht_i;
  while(TRUE)
  {
  printf("请输入生成的随机数的个数(范围[900000~1000000]) :");
  fflush(stdout);
  //scanf("%d",&wht_i);
  cin>>wht_i;
  /*读出正确的wht_i,返回;否则,继续要求输入*/
  if((wht_i>=900000) && (wht_i<=1000000))
  break;
  printf("输入错误,数字范围是 [900000~1000000]");
  printf("\n");
  }
  return wht_i;
  }
   
  /*
  * 函数名: para_QuickSort
  * 功能:并行快速排序,对起止位置为wht_start和wht_end的序列,使用2的wht_m次幂个处理器进行排序
  * 输入:无序数组wht_data[1,n],使用的处理器个数2^wht_m
  * 输出:有序数组wht_data[1,n]
  */
  void para_QuickSort(int *wht_data,int wht_start,int wht_end,int wht_m,int id,int MyID)
  {
  int wht_i, wht_j;
  int wht_r;
  int MyLength;
  int *wht_tmp;
  MPI_Status status;
  MyLength=-1;
  /*如果可供选择的处理器只有一个,那么由处理器id调用串行排序,对应于算法13.4步骤(1.1)*/
  /*(1.1) Pid call quicksort(wht_data,wht_i,wht_j) */
  if(wht_m==0)
  {
  wht_start_time=MPI_Wtime();
  if(MyID==id)
  QuickSort(wht_data,wht_start,wht_end);
  return;
  }
  wht_start_time=MPI_Wtime();
  /*由第id号处理器划分数据,并将后一部分数据发送到处理器id+exp2(wht_m-1),对应于算法步骤(1.2,1.3)*/
  /*(1.2) Pid: wht_r=patrition(wht_data,wht_i,wht_j)*/
  if(MyID==id)
  {
  /*将当前的无序区R[1,n]划分成左右两个无序的子区R[1,wht_i-1]和R[wht_i,n](1≤wht_i≤n)*/
  wht_r=Partition(wht_data,wht_start,wht_end);
  MyLength=wht_end-wht_r;
  /*(1.3) Pid swht_end wht_data[wht_r+1,wht_m-1] to P(id+2m-1) */
  /* {MyLength表示发送缓冲区地址;*/
  /* 发送元素数目为1; */
  /* MyID是消息标签 } */
  MPI_Send(&MyLength,1,MPI_INT,id+exp2(wht_m-1),MyID,MPI_COMM_WORLD);
  /*若缓冲区不空,则第id+2m-1号处理器取数据的首址是wht_data[wht_r+1]*/
  if(MyLength!=0)
  MPI_Send(wht_data+wht_r+1,MyLength,MPI_INT,id+exp2(wht_m-1),MyID,MPI_COMM_WORLD);
  }
  /*处理器id+exp2(wht_m-1)接受处理器id发送的消息*/
  if(MyID==id+exp2(wht_m-1))
  {
  MPI_Recv(&MyLength,1,MPI_INT,id,id,MPI_COMM_WORLD,&status);
  if(MyLength!=0)
  {
  wht_tmp=(int *)malloc(MyLength*sizeof(int));
  if(wht_tmp==0) printf("Malloc memory error!");
  MPI_Recv(wht_tmp,MyLength,MPI_INT,id,id,MPI_COMM_WORLD,&status);
  }
  }
  /*递归调用并行排序,对应于算法(1.4,1.5)*/
  /*用2^wht_m-1个处理器对wht_start--(wht_r-1)的数据进行递归排序*/
  wht_j=wht_r-1-wht_start;
  MPI_Bcast(&wht_j,1,MPI_INT,id,MPI_COMM_WORLD);
  /*(1.4) para_quicksort(wht_data,wht_i,wht_r-1,wht_m-1,id)*/
  if(wht_j>0)
  para_QuickSort(wht_data,wht_start,wht_r-1,wht_m-1,id,MyID);
  /*用2^wht_m-1个处理器对(wht_r+1)--wht_end的数据进行递归排序*/
  wht_j=MyLength;
  MPI_Bcast(&wht_j,1,MPI_INT,id,MPI_COMM_WORLD);
  /*(1.5) para_quicksort(wht_data,wht_r+1,wht_j,wht_m-1,id+2m-1)*/
  if(wht_j>0)
  para_QuickSort(wht_tmp,0,MyLength-1,wht_m-1,id+exp2(wht_m-1),MyID);
  /*将排序好的数据由处理器id+exp2(wht_m-1)发回id号处理器,对应于算法/
  /*(1.6) P(id+2m-1) swht_end wht_data[wht_r+1,wht_m-1] back to Pid */
  if((MyID==id+exp2(wht_m-1)) && (MyLength!=0))
  MPI_Send(wht_tmp,MyLength,MPI_INT,id,id+exp2(wht_m-1),MPI_COMM_WORLD);
  if((MyID==id) && (MyLength!=0))
  MPI_Recv(wht_data+wht_r+1,MyLength,MPI_INT,id+exp2(wht_m-1),id+exp2(wht_m-1),MPI_COMM_WORLD,&status);
  }
  /*
  * 函数名: main
  * 功能:实现快速排序的主程序
  * 输入:argc为命令行参数个数;
  * argv为每个命令行参数组成的字符串数组。
  * 输出:返回0代表程序正常结束
  */
  int main(int argc,char *argv[])
  {
  double wht_dataSize;
  int *wht_data;
  /*MyID表示进程标志符;SumID表示组内进程数*/
  int MyID, SumID;
  int wht_i, wht_j;
  int wht_m, wht_r;
  MPI_Status status;
  /*启动MPI计算*/
  MPI_Init(&argc,&argv);
  /*MPI_COMM_WORLD是通信子*/
  /*确定自己的进程标志符MyID*/
  MPI_Comm_rank(MPI_COMM_WORLD,&MyID);
  /*组内进程数是SumID*/
  MPI_Comm_size(MPI_COMM_WORLD,&SumID);
  /*根处理机(MyID=0)获取必要信息,并分配各处理机进行工作*/
  if(MyID==0)
  {
  /*获取待排序数组的长度*/
  wht_dataSize=Getwht_dataSize();
  wht_data=(int *)malloc(wht_dataSize*sizeof(int));
   
  /*内存分配错误*/
  if(wht_data==0)
  printf("Malloc memory error!");
   
  /*动态生成待排序序列*/
  srand(396);
  //printf("排序前的随机数组为 :\n");
  for(wht_i=0;wht_i<wht_dataSize;wht_i++)
  {
  wht_data[wht_i]=(int)rand();
  // printf("%10d",wht_data[wht_i]);
  }
  printf("\n");
  }
  wht_m=log2(SumID);
  /* 从根处理器将数据序列广播到其他处理器*/
  /*{"1"表示传送的输入缓冲中的元素的个数, */
  /* "MPI_INT"表示输入元素的类型, */
  /* "0"表示root processor的ID } */
  MPI_Bcast(&wht_dataSize,1,MPI_INT,0,MPI_COMM_WORLD);
  /*ID号为0的处理器调度执行排序*/
  para_QuickSort(wht_data,0,wht_dataSize-1,wht_m,0,MyID);
  wht_end_time=MPI_Wtime();
  /*ID号为0的处理器打印排序完的有序序列*/
  if(MyID==0)
  {
  //printf("排序后的有序数组为 :\n");
  //for(wht_i=0;wht_i<wht_dataSize;wht_i++)
  //{
  // printf("%10d",wht_data[wht_i]);
  //}
  printf("\n");
  printf("Time=%f\n",wht_end_time-wht_start_time);
  }
   
  MPI_Finalize(); //结束计算
  }
时间: 2024-10-05 11:49:55

QuickSort (MPI 实现)的相关文章

并行归并排序——MPI

并行归并排序在程序开始时,会将n/comm_comm个键值分配给每个进程,程序结束时,所有的键值会按顺序存储在进程0中.为了做到这点,它使用了树形结构通信模式.当进程接收到另一个进程的键值时,它将该键值合并进自己排序的键值列表中.编写一个程序实现归并排序.进程0应该读入n的值,将其广播给其余进程.每个进程需要使用随机数生成器来创建n/comm_sz的局部int型数据列表.每个进程先排序各自的局部列表,然后进程0收集并打印这些局部列表.然后,这些进程使用树形结构通信合并全局列表给进程0,并打印最终

基于 MPI 的快速排序算法的实现

完整代码: #include <iostream> #include <cstdlib> #include <ctime> #include <algorithm> #include <cmath> #include <mpi.h> using namespace std; struct Pair { int left; int right; }; const int MAX_PROCESS = 128; const int NUM

【MPI学习3】MPI并行程序设计模式:不同通信模式MPI并行程序的设计

学习了MPI四种通信模式 及其函数用法: (1)标准通信模式:MPI_SEND (2)缓存通信模式:MPI_BSEND (3)同步通信模式:MPI_SSEND (4)就绪通信模式:MPI_RSEND 四种通信模式的区别都在消息发送端,而消息接收端的操作都是MPI_RECV. 1.标准通信模式 原理图如下 标准通信模式由MPI决定是否用缓存. 如果MPI决定缓存将要发出的数据:发送操作不管接受操作是否执行,都可以进行:而且缓存结束后发送操作就可以返回,不需要等待接受操作收到数据 如果MPI决定不缓

Floyd-Warshall算法及其并行化实现(基于MPI)

Floyd-Warshall算法(或称Floyd算法)是用于寻找加权图中非固定起止点间最短路径的经典算法,它是基于动态规划思想设计的.当前我们所认识的Floyd算法之形式由计算机科学家(同时也是图灵奖得主) Robert Floyd 于 1962 年提出并发表.但在此之前,Bernard Roy(1959)和 Stephen Warshall(1962)也分别独立地提出了类似的算法.本文将主要讨论基于MPI的并行化Floyd算法实现. 欢迎关注白马负金羁的博客 http://blog.csdn.

【MPI学习1】简单MPI程序示例

有了apue的基础,再看mpi程序多进程通信就稍微容易了一些,以下几个简单程序来自都志辉老师的那本MPI的书的第七章. 现在ubuntu上配置了一下mpich的环境: http://www.cnblogs.com/liyanwei/archive/2010/04/26/1721142.html 注意,为了编译运行方便,在~/.bashrc文件中添加mpi的两个环境变量 设置完之后注意执行source ~/.bashrc命令 程序1 计时功能 主要用到的MPI_Wtime()这个函数 1 #inc

有了OpenMP,MPI,为什么还要MapReduce? (转载)

OpenMP和MPI是并行编程的两个手段,对比如下: OpenMP:线程级(并行粒度):共享存储:隐式(数据分配方式):可扩展性差: MPI:进程级:分布式存储:显式:可扩展性好. OpenMP采用共享存储,意味着它只适应于SMP,DSM机器,不适合于集群.MPI虽适合于各种机器,但它的编程模型复杂: 需要分析及划分应用程序问题,并将问题映射到分布式进程集合: 需要解决通信延迟大和负载不平衡两个主要问题: 调试MPI程序麻烦: MPI程序可靠性差,一个进程出问题,整个程序将错误: 其中第2个问题

数组去重算法,quickSort

function removeRepeat(arr) { var arr2 = [] ,obj = {}; for (var i = 0; i<arr.length; i++) { var num = arr[i]; //先把arr的第[i]num if( !obj[num] ){ //如果上面有个true,那么就不要push进数组,否则就push进数组 arr2.push(num); obj[num] = true; //不要忘记push到数组以后把obj上的属性设置为true,那么下次有一样

排序算法四:快速排序(Quicksort)

快速排序(Quicksort),因其排序之快而得名,虽然Ta的平均时间复杂度也是o(nlgn),但是从后续仿真结果看,TA要比归并排序和堆排序都要快. 快速排序也用到了分治思想. (一)算法实现 1 protected void quicksort(int[] array, int first, int last) { 2 3 int pivot = array[first]; 4 int i = first; 5 int j = last - 1; 6 boolean serachBig =

MPI编程简单介绍

第三章MPI编程 3.1 MPI简单介绍 多线程是一种便捷的模型,当中每一个线程都能够訪问其他线程的存储空间.因此,这样的模型仅仅能在共享存储系统之间移植.一般来讲,并行机不一定在各处理器之间共享存储,当面向非共享存储系统开发并行程序时,程序的各部分之间通过来回传递消息的方式通信.要使得消息传递方式可移植,就须要採用标准的消息传递库.这就促成的消息传递接口(Message Passing Interface, MPI)的面世,MPI是一种被广泛採用的消息传递标准[1]. 与OpenMP并行程序不