📄 lifegame1.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 + -