⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lifegame1.cpp

📁 并行计算
💻 CPP
字号:
// lifegame.cpp : Defines the entry point for the console application.
//

//#include "stdafx.h"
#include "mpi.h"
#include <stdio.h>
#include <memory.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
	int x_dim,y_dim,z_dim,generation,i,j,k,count,token,Neighbour;
	int myid,numprocs,front,next,startlayer,pdim,cubesize,areasize,flag=0;
	MPI_Status status;
	int *** cell,*** celltemp,*** temp;
	double startwtime,endwtime;
	FILE *fp;

	MPI_Init(&argc,&argv);
	MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
	MPI_Comm_rank(MPI_COMM_WORLD,&myid);
	
	if(argc!=3)
	{
		printf("The number of arguments of the program must be 2\n");
		exit(0);
	}

	if((fp=fopen(argv[1],"r"))==NULL)
	{
		printf("Cannot open file %s\n",argv[1]);
		exit(0);
	}
	if(myid==numprocs-1)
		startwtime=MPI_Wtime();
	generation=atoi(argv[2]);
	/*if(generation<=0)
	{
		printf("Generation must more than 1\n");
		exit(0);
	}*/
	fscanf(fp,"%d %d %d\n",&x_dim,&y_dim,&z_dim);
	//分层办法是把立方体按层连续平均分配,如果有剩余则前面层数多,后面少
	//计算每一进程所要计算部分的开始层号startlayer,和层数pdim		
	pdim=x_dim/numprocs+1;
	//因为按层分配,进程数必须不大于x_dim
	if(pdim==1)
	{
		printf("The layers of the cube must be more than the number of processes!!!\n");
		exit(0);
	}		
	flag=x_dim%numprocs;//拥有的层数多的进程(0,1,...,flag-1)和少的进程(flag,flag+1,...,numprocs-1)的分界处
	if(myid<flag)
		startlayer=myid*pdim;
	else
		startlayer=flag*pdim+(myid-flag)*(--pdim);
	areasize=(y_dim+2)*(z_dim+2);
	cubesize=(pdim+2)*(y_dim+2)*(z_dim+2);
	//生命状态数组
	cell=(int*** )malloc((pdim+2)*sizeof(int**));
	cell[0]=(int**)malloc((pdim+2)*(y_dim+2)*sizeof(int*));
	for(i=1;i<(pdim+2);i++)
		cell[i]=cell[0]+i*(y_dim+2);
	cell[0][0]=(int*)malloc(cubesize*sizeof(int));
	for(i=0;i<(pdim+2);i++)
		for(j=0;j<(y_dim+2);j++)
			cell[i][j]=cell[0][0]+i*areasize+j*(z_dim+2);
	if(!cell||!cell[0]||!cell[0][0])
	{
		printf("Can not allcate cell!\n");
		exit(0);
	}
	//生命状态暂存数组	
	celltemp=(int*** )malloc((pdim+2)*sizeof(int**));
	celltemp[0]=(int**)malloc((pdim+2)*(y_dim+2)*sizeof(int*));
	for(i=1;i<(pdim+2);i++)
		celltemp[i]=celltemp[0]+i*(y_dim+2);
	celltemp[0][0]=(int*)malloc(cubesize*sizeof(int));
	for(i=0;i<(pdim+2);i++)
		for(j=0;j<(y_dim+2);j++)
			celltemp[i][j]=celltemp[0][0]+i*areasize+j*(z_dim+2);
	if(!celltemp||!celltemp[0]||!celltemp[0][0])
	{
		printf("Can not allcate cell!\n");
		exit(0);
	}
	//数组初始化
	memset(cell[0][0],0,cubesize*sizeof(int));
	memset(celltemp[0][0],0,cubesize*sizeof(int));
	//读文件
	while(!feof(fp))
	{
		fscanf(fp,"%d %d %d\n",&i,&j,&k);
		if(i<startlayer||i>=startlayer+pdim)
			continue;
		cell[i-startlayer+1][j+1][k+1]=1;
	}
	fclose(fp);
			
	front=myid-1;
	next=myid+1;
	if(front<0) front=MPI_PROC_NULL;
	if(next>numprocs-1) next=MPI_PROC_NULL;
	for(count=1;count<=generation;count++)
	{
		//交界面通信
		MPI_Sendrecv(cell[pdim][0],areasize,MPI_INT,next,1,cell[0][0],areasize,MPI_INT,front,1,MPI_COMM_WORLD,&status);
		MPI_Sendrecv(cell[1][0],areasize,MPI_INT,front,1,cell[pdim+1][0],areasize,MPI_INT,next,1,MPI_COMM_WORLD,&status);
		//计算邻居值并将新生命值存入celltemp
		for(i=1;i<=pdim;i++)
			for(j=1;j<=y_dim;j++)
				for(k=1;k<=z_dim;k++)
				{
					Neighbour=0;
					//不用循环可以使运算时间更短
					Neighbour=cell[i-1][j-1][k-1]+cell[i-1][j-1][k]+cell[i-1][j-1][k+1]+cell[i-1][j][k-1]+cell[i-1][j][k]+cell[i-1][j][k+1]+cell[i-1][j+1][k-1]+cell[i-1][j+1][k]+cell[i-1][j+1][k+1]
						     +cell[i][j-1][k-1]+cell[i][j-1][k]+cell[i][j-1][k+1]+cell[i][j][k-1]+cell[i][j][k+1]+cell[i][j+1][k-1]+cell[i][j+1][k]+cell[i][j+1][k+1]
							 +cell[i+1][j-1][k-1]+cell[i+1][j-1][k]+cell[i+1][j-1][k+1]+cell[i+1][j][k-1]+cell[i+1][j][k]+cell[i+1][j][k+1]+cell[i+1][j+1][k-1]+cell[i+1][j+1][k]+cell[i+1][j+1][k+1];

					celltemp[i][j][k]=cell[i][j][k];
					if(cell[i][j][k]==0&&(Neighbour==3||Neighbour==4))
							celltemp[i][j][k]=1;
					if(cell[i][j][k]==1&&(Neighbour!=2&&Neighbour!=3))
							celltemp[i][j][k]=0;
				}
		//更新生命状态值
		temp=cell;
		cell=celltemp;
		celltemp=temp;
	}								
	//按序输出
	
	
	MPI_Recv(&token,1,MPI_INT,front,1,MPI_COMM_WORLD,&status);
	if(myid==0)
	{	
		if((fp=fopen("tmpfile","w"))==NULL)
		{
			printf("Can not creat tmpfile\n");
			exit(0);
		}
		fprintf(fp,"%d %d %d\n",x_dim,y_dim,z_dim);
	}
	else
	{
		if((fp=fopen("tmpfile","a+"))==NULL)
		{
			printf("Can not open tmpfile\n");
			exit(0);
		}
	}
	for(i=1;i<=pdim;i++)
		for(j=1;j<=y_dim;j++)
			for(k=1;k<=z_dim;k++)
				if(cell[i][j][k]==1)
					fprintf(fp,"%d %d %d\n",i-1+startlayer,j-1,k-1);
						
	fclose(fp);					
	MPI_Send(&token,1,MPI_INT,next,1,MPI_COMM_WORLD);

	//每个进程释放分配的空间
	free(cell[0][0]);
	free(cell[0]);
	free(cell);
	free(celltemp[0][0]);
	free(celltemp[0]);
	free(celltemp);
	if(myid==numprocs-1)
	{
		if((fp=fopen("tmpfile","r"))==NULL)
		{
			printf("Can not open tmpfile\n");
			exit(0);
		}
		while(!feof(fp))
		{
			fscanf(fp,"%d %d %d\n",&i,&j,&k);
			printf("%d %d %d\n",i,j,k);
		}
		fclose(fp);
		system("rm tmpfile");
		endwtime=MPI_Wtime();
		printf("The total time if %f\n",endwtime-startwtime);
	}
	MPI_Finalize();
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -