MPI实现fft的迭代算法 源于并行计算——结构。算法。编程中伪码 更新1

对于节点内部传送不通过mpi

 

#include "mpi.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/stat.h>
#include <memory.h>

typedef struct {
	double real;
	double img;
} com;

double PI;

int readBinary(char* file,void *buf,int fsize);//if named read causes override and miscall
int writeBinary(char *file,com *array,int size);
//don't use the omega array,not every node needs a whole copy of omega,not efficient
static inline void cp(com f,com *t);//copy complex
static inline void add(com a,com b,com* r);
static inline void mul(com a,com b,com* r);
static inline void sub(com a,com b,com* r);
int br(int src,int size);//bit reverse
void send(com *c,com *r,int s,int t);
void show(com a) {
	printf("%.4f %.4f \n",a.real,a.img);
}
int main(int argc,char *argv[]) {
	if(argc<3) {
		printf("wtf\n");
		return 1;
	}
	double st,et;
	PI=atan(1)*4;
	int self,size;//process id and total number of processes
	MPI_Init(&argc,&argv);
	st=MPI_Wtime();
	MPI_Comm_rank(MPI_COMM_WORLD,&self);
	MPI_Comm_size(MPI_COMM_WORLD,&size);
	int fsize,n;
	void *buf;
	com *in;
	if(0==self) {
		//printf("start \n");
		struct stat fstat;
		stat(argv[1],&fstat);
		fsize=fstat.st_size;
		buf=malloc(fsize);
		n=readBinary(argv[1],buf,fsize)/2;//n stands for total complex number
		in=(com*)malloc(n*sizeof(com));
		memcpy(in,((int*)buf+1),n*sizeof(com));
		free(buf);
	}
	MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);//every thread should know the total size
	
	if(-1==n) {
		printf("error reading \n");
		MPI_Finalize();
	}
	
	int psize=n/size;
	//mpi communication obj
	MPI_Request isReq[psize];
	MPI_Request reReq[psize];
	MPI_Status s[psize];
	//data
	//com a[psize];//input
	com w;//omega
	com r[psize];//recieve
	//com *r=(com*)malloc(psize*sizeof(com));

	int l=log(n)/log(2);

	com c[psize];//temp
	//com *c=(com*)malloc(psize*sizeof(com));
	
	int off=self*psize;
	for(int h=l-1;h>=0;--h) {
		//initialize data each round
		if(0==self) printf("test scatter ");
		MPI_Scatter(in,psize*2,MPI_DOUBLE,c,psize*2,MPI_DOUBLE,0,MPI_COMM_WORLD);
		if(0==self) printf("done \n");
		//memcpy(c,a,psize*sizeof(com));
		//calculate
		int p=pow(2,h);
		int q=n/p;
		int k;
		for(k=off;k<off+psize;++k) {//post all comunications first
			if(k%p==k%(2*p)) {//tag is always the sending row number
			//printf("self %d row %d dest row %d dest %d \n",self,k+self,k+p,(k+p)/psize);
				if(k+p<(self+1)*psize) {//same node
					r[k-off]=c[k+p-off];
					//if(0==self) printf("inside up s\n");
				} else {
					MPI_Issend(&c[k-off],2,MPI_DOUBLE,(k+p)/psize,k,MPI_COMM_WORLD,&isReq[k-off]);
					MPI_Irecv(&r[k-off],2,MPI_DOUBLE,(k+p)/psize,k+p,MPI_COMM_WORLD,&reReq[k-off]);
				}
			} else {
				if(k-p>=off) {//same node
					r[k-off]=c[k-p-off];
					//if(0==self) printf("inside down s\n");
				} else {
					MPI_Issend(&c[k-off],2,MPI_DOUBLE,(k-p)/psize,k,MPI_COMM_WORLD,&isReq[k-off]);
					MPI_Irecv(&r[k-off],2,MPI_DOUBLE,(k-p)/psize,k-p,MPI_COMM_WORLD,&reReq[k-off]);
				}
			}
		}
		for(k=off;k<off+psize;++k) {//wait and calculate
			if(k%p==k%(2*p)) {
				int time=p*(br(k,l)%q);//compute while recieving and sending
				w.real=cos(2*PI*time/n);
				w.img=sin(2*PI*time/n);
				if(k+p<(self+1)*psize) {//not same node
					//if(0==self) printf("inside up w\n");
				} else {
					MPI_Wait(&reReq[k-off],&s[k-off]);
					MPI_Wait(&isReq[k-off],&s[k-off]);
				}
				mul(r[k-off],w,&r[k-off]);
				add(c[k-off],r[k-off],&c[k-off]);
			} else {
				int time=p*(br(k-p,l)%q);//compute while recieving and sending
				w.real=cos(2*PI*time/n);
				w.img=sin(2*PI*time/n);
				if(k-p>=off) {//not same node
					//if(0==self) printf("inside down w\n");
				} else {
					MPI_Wait(&reReq[k-off],&s[k-off]);
					MPI_Wait(&isReq[k-off],&s[k-off]);
				}
				mul(c[k-off],w,&c[k-off]);//can't modify until sending comes to an end
				sub(r[k-off],c[k-off],&c[k-off]);
			}
		}
		if(0==self) {
			printf("loop %d \n",h);
		}
		MPI_Gather(c,2*psize,MPI_DOUBLE,in,2*psize,MPI_DOUBLE,0,MPI_COMM_WORLD);
		if(0==self) {
			printf("gather done\n");
		}
	}
	MPI_Scatter(in,psize*2,MPI_DOUBLE,c,psize*2,MPI_DOUBLE,0,MPI_COMM_WORLD);
	//MPI_Abort(MPI_COMM_WORLD,1);
	//reverse all data
	int rs=0;
	for(int k=off;k<off+psize;++k) {//post all comunications first
		//tag is always the sending row number
		int brv=br(k,l);
		if(brv>=off&&brv<off+psize) {
			r[k-off]=c[brv-off];
		} else {
			MPI_Issend(&c[k-off],2,MPI_DOUBLE,brv/psize,k,MPI_COMM_WORLD,&isReq[rs]);
			MPI_Irecv(&r[k-off],2,MPI_DOUBLE,brv/psize,brv,MPI_COMM_WORLD,&reReq[rs++]);
		}
	}
	MPI_Waitall(rs,isReq,s);
	MPI_Waitall(rs,reReq,s);
	MPI_Gather(r,psize*2,MPI_DOUBLE,in,psize*2,MPI_DOUBLE,0,MPI_COMM_WORLD);
	if(0==self) {
//		for(int i=0;i<n;++i) {
//			printf("b%d  %d :%.4f %.4f \n",i,br(i,l),in[i].real,in[i].img);
//		}
		writeBinary(argv[2],in,n);
		free(in);
	}
	//free(r);
	//free(c);
	et=MPI_Wtime();
	MPI_Finalize();
	printf("%f \n",et-st);
	return 0;
}

int readBinary(char* file,void *buf,int fsize) {
	FILE *in;
	if(!(in=fopen(file,"r"))) {
		printf("can't open \n");
		return -1;
	}

	fread(buf,sizeof(char),fsize,in);
	int size=((int*)buf)[0];
	fclose(in);
	return size;
}

int writeBinary(char *file,com *array,int size) {
	FILE *out;
	if(!(out=fopen(file,"w"))) {
		printf("can't open \n");
		return -1;
	}
	int bsize=sizeof(int)+size*sizeof(com);
	void *buf=malloc(bsize);
	((int*)buf)[0]=2*size;
	memcpy(((int*)buf+1),array,size*sizeof(com));
	fwrite(buf,sizeof(char),bsize,out);
	free(buf);
	fclose(out);
	return 0;
}
void cp(com f,com *t) {
	t->real=f.real;
	t->img=f.img;
}
void add(com a,com b,com *c)   
{
	c->real=a.real+b.real;   
	c->img=a.img+b.img;   
}   
    
void mul(com a,com b,com *c)   
{   
	c->real=a.real*b.real-a.img*b.img;   
	c->img=a.real*b.img+a.img*b.real;   
}
void sub(com a,com b,com *c)   
{   
	c->real=a.real-b.real;   
	c->img=a.img-b.img;   
}   
int br(int src,int size) {
	int tmp=src;
	int des=0;
	for(int i=size-1;i>=0;--i) {
		des=((tmp&1)<<i)|des;
		tmp=tmp>>1;
	}
	return des;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值