您的位置:首页 > 其它

枚举排序各种并行之MPI

2014-11-09 13:48 309 查看
声明:运行MPI程序之前必须先将mpich配置好,可以参照
http://blog.csdn.net/he_xiang_/article/details/40189257
#include "stdafx.h"
#include "mpi.h"          //mpi.h一定好放到stafx.h后面
#include <Windows.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

/*
* 函数名: GetRank
* 功能: 计算所属部分数据的秩(比该元素小的数的个数)
* 输入: HX_data:指向待排序序列的指针
*        HX_DataSize为待排序序列的长度
MyLength为该处理器要排序的序列的长度
rank:指向秩数组的指针
SumID:总处理器个数
MyID:处理器ID
* 输出:返回1代表程序正常结束
*/
int GetRank(int *data,int DataSize,int MyLength,int *rank,int SumID,int MyID)
{
int i, j;
int start, end;

start=DataSize/SumID*MyID;      /*所属部分数据起始位置*/
end=start+MyLength;             /*所属部分数据结束位置*/

for(j=start;j<end;j++){         /*计算所属部分数据的rank*/
rank[j-start]=0;
for(i=0;i<DataSize;i++){
if((data[j]>data[i]) || ((data[j]==data[i]) && (j>i)))
rank[j-start]++;
}
}
return 1;
}

/*
* 函数名: GetDataSize
* 功能: 读入待排序序列的长度
* 输入: 待排序序列的长度
* 输出: 返回待排序序列的长度
*/
int GetDataSize()
{
int i;

while(1){
fprintf(stderr,"请输入数组的大小:");
fflush(stderr);
scanf("%d",&i);
if(i>0)
break;
}
return i;
}

/*
* 函数名: main
* 功能:   主函数,实现枚举排序
* 输入:argc为命令行参数个数;
*            argv为每个命令行参数组成的字符串数组
* 输出:返回1代表程序正常结束
*/
int main(int argc,char *argv[])
{
int DataSize, MyLength;              /*DataSize:数组长度;MyLength:处理器分配到的数据长度*/
int *data_in, *data_out;             /*输入和输出数组指针*/
int *rank;                           /*秩数组*/
int MyID, SumID;
int i, j;
double starttime,endtime;

MPI_Status status;

MPI_Init(&argc,&argv);                /*MPI 初始化*/
MPI_Comm_rank(MPI_COMM_WORLD,&MyID);  /*每个处理器确定各自ID*/
MPI_Comm_size(MPI_COMM_WORLD,&SumID); /*每个处理器确定总处理器个数*/
fprintf(stderr,"Process %d on %s\n",MyID);
fflush(stderr);

if(MyID==0)                           /*主处理器*/
DataSize=GetDataSize();       /*读入待排序序列的长度*/

MPI_Bcast(&DataSize, 1, MPI_INT, 0, MPI_COMM_WORLD);
/*主处理器广播待排序序列的长度*/

/*在各个处理器间划分任务*/
MyLength=DataSize/SumID;
if(MyID==SumID-1)                     /*每个处理器确定各自要排序的序列长度*/
MyLength=DataSize-MyLength*(SumID-1);

data_in=(int *)malloc(DataSize*sizeof(int)); /*分配待排序序列的空间*/
if(data_in==0) printf("Malloc memory error!");

if(MyID==0){
data_out=(int *)malloc(DataSize*sizeof(int)); /*主处理器分配排序后数组的空间*/
if(data_out==0) printf("Malloc memory error!");

rank=(int *)malloc(DataSize*sizeof(int));     /*分配序号数组的空间*/
if(rank==0) printf("Malloc memory error!");
}
else{
rank=(int *)malloc(MyLength*sizeof(int));     /*分配序号数组的空间*/
if(rank==0) printf("Malloc memory error!");
}

if(MyID==0){
int seed;
fprintf(stderr,"请输入随机数的种子:");
fflush(stderr);
scanf("%d",&seed);                       /*获得随机数的种子*/
srand(seed);           /*srand初始化随机种子*/
printf("获取随机数\n");
fflush(stderr);
for(i=0;i<DataSize;i++){
data_in[i]=((int)rand())%10000;  /*生成随机数,并输出*/
//printf("%10d ",data_in[i]);
}
//printf("\nOutput:");
printf("\n");
}

starttime=MPI_Wtime();
/*向各个处理器播送待排序序列*/
MPI_Bcast(data_in, DataSize, MPI_INT, 0, MPI_COMM_WORLD);

/*各个处理器分别计算所属元素的秩*/
GetRank(data_in,DataSize,MyLength,rank,SumID,MyID);

/*从各个处理器收集已排序好的数据*/
if(MyID==0){
for(i=1;i<SumID;i++){
if(i==SumID-1)
MPI_Recv(rank+MyLength*i,DataSize-MyLength*(SumID-1),MPI_INT,i,0,MPI_COMM_WORLD,&status);
else
MPI_Recv(rank+MyLength*i,MyLength,MPI_INT,i,0,MPI_COMM_WORLD,&status);
}
}
else
MPI_Send(rank,MyLength,MPI_INT,0,0,MPI_COMM_WORLD);

/*根据所获得的秩重新定位各个数据*/
if(MyID==0){
for(i=0;i<DataSize;i++)
data_out[rank[i]]=data_in[i];

printf("已排好序的数据\n");
for(i=0;i<DataSize;i++){
//printf("%10d ",data_out[i]);
}
printf("\n");
endtime=MPI_Wtime();
printf("时间=%f\n",endtime-starttime);
}

MPI_Finalize();
return 0;
}


测试结果正确性:



测试1个进程



测试2个进程



相对加速比:65.7/36..46=1.80
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: