枚举排序各种并行之MPI

声明:运行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;  
}  


测试结果正确性:

枚举排序各种并行之MPI_第1张图片

测试1个进程

枚举排序各种并行之MPI_第2张图片

测试2个进程

枚举排序各种并行之MPI_第3张图片

相对加速比:65.7/36..46=1.80

你可能感兴趣的:(枚举排序各种并行之MPI)