MPI 堆排序

堆排是串行排序中最适合并行化的排序之一

1/分为主线程和从线程

2/主线程分发数据,使用大小与从线程个数相同的堆作为私有堆,进行最后整理用

3/从线程维护一个堆,每次返回给主线程堆顶元素

4/主线程 提取堆顶元素 通知相应从线程提交新的堆顶元素

5/主从线程并行进行重建堆(heapify)的动作

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>

#define ROOT 0
#define TAG 0
#define NEXT 1
#define END -1
typedef struct node {
	int v;
	int r;
} Node;

static inline int left(int i) {
	return i*2+1;
}
static inline int right(int i) {
	return left(i)+1;
}
void defineIntVector(MPI_Datatype* type,int length) {
	MPI_Type_vector(length,1,1,MPI_INT,type);
	MPI_Type_commit(type);
}
//for slaves
void heapifyI(int *a,int root,int size) {
	int l=left(root);
	int r=right(root);
	int m=root;
	if(l<size&&a[l]<a[m]) {
		m=l;
	}
	if(r<size&&a[r]<a[m]) {
		m=r;
	}
	if(m!=root) {
		int t=a[root];
		a[root]=a[m];
		a[m]=t;
		heapifyI(a,m,size);
	}
}
void buildHeapI(int *a,int size) {
	for(int i=(size-1)/2;i>=0;--i) {
		heapifyI(a,i,size);
	}
}
//for root
void heapifyN(Node *a,int root,int size) {
	int l=left(root);
	int r=right(root);
	int m=root;
	if(l<size&&a[l].v<a[m].v) {
		m=l;
	}
	if(r<size&&a[r].v<a[m].v) {
		m=r;
	}
	if(m!=root) {
		Node t=a[root];
		a[root]=a[m];
		a[m]=t;
		heapifyN(a,m,size);
	}
}
void buildHeapN(Node *a,int size) {
	for(int i=(size-1)/2;i>=0;--i) {
		heapifyN(a,i,size);
	}
}
int main(int argc,char *argv[]) {
	int self,size;
	int part;//threshold
	MPI_Init(&argc,&argv);
	MPI_Comm_rank(MPI_COMM_WORLD,&self);
	MPI_Comm_size(MPI_COMM_WORLD,&size);
	MPI_Status status;
	MPI_Datatype MPI_VEC;
	if(ROOT==self) {
		//all data
		int values[]={1,5,3,8,4,2,9,6,7,54,34,6,13,63,32,14,53,21,65,33,24,213,23,14,21,65,32};
		int length=27;
		//for each process
		part=length/(size-1);
		MPI_Bcast(&part,1,MPI_INT,ROOT,MPI_COMM_WORLD);
		defineIntVector(&MPI_VEC,part);
		//heap for min value from each process
		Node *nodes=(Node*)malloc((size-1)*sizeof(Node));
		for(int i=0;i<size-1;++i) {
			nodes[i].r=i+1;
		}
		//send out all the data
		for(int i=1;i<size;++i) {
			MPI_Ssend(&values[(i-1)*part],1,MPI_VEC,i,TAG,MPI_COMM_WORLD);
		}
		for(int i=1;i<size;++i) {
			MPI_Recv(&(nodes[i-1].v),1,MPI_INT,i,TAG,MPI_COMM_WORLD,&status);
		}
		//end flag
		part=size-1;
		//build a heap representing process
		buildHeapN(nodes,part);
		int p=0;
		while(part>0) {
			values[p++]=nodes[0].v;
//similar to the message passing system of select sort
			MPI_Ssend(&p,1,MPI_INT,nodes[0].r,NEXT,MPI_COMM_WORLD);
			MPI_Recv(&(nodes[0].v),1,MPI_INT,nodes[0].r,TAG,MPI_COMM_WORLD,&status);
			if(END==nodes[0].v) {
				nodes[0]=nodes[--part];
			}
			heapifyN(nodes,0,part);
		}
		for(int i=0;i<length;++i) 
			printf("%d ",values[i]);
		free(nodes);
	} else {
		MPI_Bcast(&part,1,MPI_INT,ROOT,MPI_COMM_WORLD);
		defineIntVector(&MPI_VEC,part);
		int *values=(int*)malloc(part*sizeof(int));
		MPI_Recv(values,1,MPI_VEC,ROOT,TAG,MPI_COMM_WORLD,&status);
		buildHeapI(values,part);
		//send the smallest
		MPI_Ssend(&values[0],1,MPI_INT,ROOT,TAG,MPI_COMM_WORLD);
		//pop out one
		values[0]=values[--part];
		//rebuild heap
		heapifyI(values,0,part);
		while(part>0) {
			MPI_Recv(&values[part],1,MPI_INT,ROOT,NEXT,MPI_COMM_WORLD,&status);
			MPI_Ssend(&values[0],1,MPI_INT,ROOT,TAG,MPI_COMM_WORLD);
			values[0]=values[--part];
			heapifyI(values,0,part);
		}
		MPI_Recv(&values[part],1,MPI_INT,ROOT,NEXT,MPI_COMM_WORLD,&status);
		values[0]=END;
		MPI_Ssend(&values[0],1,MPI_INT,ROOT,TAG,MPI_COMM_WORLD);
		free(values);
	}
	MPI_Finalize();
	return 0;
}


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值