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

📄 life.cpp

📁 使用VC。NET2005串行实现著名的细胞自动机程序:生命游戏
💻 CPP
字号:
/** CopyRight YangTao of BJUT  */ 
/** Email : i_am_ytao@126.com  */

#include "Life.h"

void main(int argc, char *argv[])
{
	double StartTime,EndTime;//定义起始终止时间
	Cell Sea[ROW][COLUMN];  //定义海域矩阵
	Msg msg; //定义进程消息
    int rank,size,workAmount,finishCounter=0;  //定义进程号,进程总数,每个进程的工作量,完工计数器
	MPI_Datatype CellType;//定义传输新类型
	MPI_Datatype MsgType;
	MPI_Status status;//定义进程状态
	int lengtharray[3],msg_lengtharray[2];           /* Array of lengths *///新类型的分量长度
    MPI_Aint disparray[3],msg_disparray[2];        /* Array of displacements *///新类型的分量偏移量
    MPI_Datatype typearray[3],msg_typearray[2];    /* Array of MPI datatypes *///新类型的分量数据类型
    MPI_Aint startaddress, address,msg_startaddress, msg_address;   /* Variables used to calculate displacements *///计算偏移量
	MPI_Init(&argc, &argv);//初始化
		
    lengtharray[0] = lengtharray[1] =lengtharray[2] =1;//分量为1个长度单位
	msg_lengtharray[0]=msg_lengtharray[1]=1;
	typearray[0] = typearray[1] =typearray[2] =MPI_INT;//分量为整数类型
	msg_typearray[0]=msg_typearray[1]=MPI_INT;
	disparray[0] = 0;//第一个分量偏移量
	msg_disparray[0]=0;
	///////////////////////////////////////////////////////////////////////////////////////////////////////
	MPI_Address(&Sea[0][0].Type, &startaddress);//获得第一个分量偏移
	MPI_Address(&Sea[0][0].Age, &address);//获得第二个分量偏移
	disparray[1] = address-startaddress;     /* Displacement of second element, b *///计算第二个分量偏移
	MPI_Address(&Sea[0][0].StarvationTime, &address);//获得第三个分量偏移
	disparray[2] = address-startaddress;     /* Displacement of third element, n *///计算第三个分量偏移
	/* Build the data structure my_type *///创建新的变量
	MPI_Type_struct(3, lengtharray, disparray, typearray, &CellType);
	MPI_Type_commit(&CellType);
    ///////////////////////////////////////////////////////////////////////////////////////////////////////
	MPI_Address(&msg.Type, &msg_startaddress);//获得第一个分量偏移
	MPI_Address(&msg.Source, &msg_address);//获得第二个分量偏移
	msg_disparray[1] = msg_address-msg_startaddress;     /* Displacement of second element, b *///计算第二个分量偏移
	/* Build the data structure my_type *///创建新的变量
	MPI_Type_struct(2, msg_lengtharray, msg_disparray, msg_typearray, &MsgType);
	MPI_Type_commit(&MsgType);
	///////////////////////////////////////////////////////////////////////////////////////////////////////

	MPI_Comm_rank(MPI_COMM_WORLD, &rank);//获得进程号
    MPI_Comm_size(MPI_COMM_WORLD, &size);//获得进程总数
	
    workAmount=(int)((double)ROW/(size-1)+.5); //平均分配子进程工作量(均分上取整)
	if(rank==0)
	{
		StartTime=MPI_Wtime();//起始时间
	    srand( (unsigned)time( NULL ) );    //设置随机种子
		SeaInit(Sea[0][0],ROW,COLUMN);   //初始化海域生物信息
        OutPutSea(Sea[0][0],ROW,COLUMN); //输出海域生物信息
	}
for(int z=0;z<100;z++)
	{
    if(rank==0)  //0号进程(主进程)
	{	
        int sendLast=ROW;  //初始化剩余分配任务
		for(int i=1;i<size;i++)  //将任务分配给子进程
		{  
            MPI_Send(&Sea[((i-1)*workAmount-1+ROW)%ROW][0],COLUMN,CellType,i,i,MPI_COMM_WORLD);//传送上边界数据

			if(sendLast>=workAmount)  //如果剩余的任务大于平均任务量
			{
				MPI_Send(&Sea[(i-1)*workAmount][0],workAmount*COLUMN,CellType,i,i,MPI_COMM_WORLD);//传送结构数据
                if(i!=size-1)  //非最后一行
				    MPI_Send(&Sea[i*workAmount][0],COLUMN,CellType,i,i,MPI_COMM_WORLD);//传送下边界数据
				else  //整数倍分配数据的情况下的最后一行处理
				    MPI_Send(&Sea[0][0],COLUMN,CellType,i,i,MPI_COMM_WORLD);//传送最后一个进程的下边界数据(数据的第一行)
			}
			else   //剩余的任务小于平均任务量(最后一行)
			{			
				MPI_Send(&Sea[(i-1)*workAmount][0],sendLast*COLUMN,CellType,i,i,MPI_COMM_WORLD);//传送结构数据
			    
				MPI_Send(&Sea[0][0],COLUMN,CellType,i,i,MPI_COMM_WORLD);//传送最后一个进程的下边界数据(数据的第一行)
			}
			sendLast-=workAmount;  //计算剩余的任务量
		}	

		while(finishCounter<size-1) //在所有进程都完成工作前处理各进程的消息(消息循环)
		{
             MPI_Recv(&msg,1,MsgType,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&status); //接收子进程的消息
             switch(msg.Type)
			 {
				 case MSG_FINISH://如果收到的消息是子进程结束工作信息
				 if(msg.Source==size-1)
				 {
					  MPI_Recv(&Sea[(msg.Source-1)*workAmount][0],(ROW-(size-2)*workAmount)*COLUMN,CellType,msg.Source,msg.Source,MPI_COMM_WORLD,&status); 
				 }
				 else
				 {
					  MPI_Recv(&Sea[(msg.Source-1)*workAmount][0],(workAmount)*COLUMN,CellType,msg.Source,msg.Source,MPI_COMM_WORLD,&status); 
				 }

					 finishCounter++;  //完工计数器递增 
					 break;
			 }
		}
	//	OutPutSea(Sea[0][0],ROW,COLUMN); //输出海域生物信息
	//	fflush(stdout);
		MPI_Barrier(MPI_COMM_WORLD);
	

	}
	else   //子进程
	{
		int SubRow,WorkRow;//定义收到的子块的行数和实际操作的行数
		Cell* revWork,*WorkField;  //定义收到的子块和实际操作的子块
		struct CellNode* SharkList=NULL;  //定义鲨鱼链表
		struct CellNode* FishList=NULL;   //定义小鱼链表
        
	//	cout<<"<"<<rank<<">"<<endl;
		if(rank!=size-1)  //如果不是最后一个子进程
		{   
            SubRow=workAmount+2; //收到的子块比实际操作的子块多了上下两行
			revWork=(struct Cell *)malloc((workAmount+2)*COLUMN*sizeof(Cell));  //给接收缓冲区分配空间
			MPI_Recv(revWork,COLUMN,CellType,0,rank,MPI_COMM_WORLD,&status);  //从主进程接收任务
			MPI_Recv(revWork+COLUMN,workAmount*COLUMN,CellType,0,rank,MPI_COMM_WORLD,&status);  //从主进程接收任务
			MPI_Recv(revWork+COLUMN+workAmount*COLUMN,COLUMN,CellType,0,rank,MPI_COMM_WORLD,&status);  //从主进程接收任务
		}
		else  //对最后一个子进程进行特殊处理
		{
			SubRow=ROW-(size-2)*workAmount+2; //收到的子块比实际操作的子块多了上下两行
			revWork=(struct Cell *)malloc((ROW-(size-2)*workAmount+2)*COLUMN*sizeof(Cell));  //给接收缓冲区分配空间
			MPI_Recv(revWork,COLUMN,CellType,0,rank,MPI_COMM_WORLD,&status);  //从主进程接收任务
			MPI_Recv(revWork+COLUMN,(ROW-(size-2)*workAmount)*COLUMN,CellType,0,rank,MPI_COMM_WORLD,&status);  //从主进程接收任务
			MPI_Recv(revWork+COLUMN+(ROW-(size-2)*workAmount)*COLUMN,COLUMN,CellType,0,rank,MPI_COMM_WORLD,&status);  //从主进程接收任务
		}
        WorkField=revWork+COLUMN; //计算获得操作区域的首地址
        WorkRow=SubRow-2; //计算获得操作区域的行数
		SharkList=CreatCellList(SharkList,*WorkField,WorkRow,COLUMN,SHARK_TYPE);  //创建鲨鱼链表(在工作区域中)
		FishList=CreatCellList(FishList,*WorkField,WorkRow,COLUMN,FISH_TYPE);     //创建小鱼链表
		Action(SharkList,*revWork,SubRow,COLUMN,SHARK_TYPE,MsgType,CellType);   //鲨鱼的动作(在获得的全部区域中)
		Action(FishList,*revWork,SubRow,COLUMN,FISH_TYPE,MsgType,CellType);     //小鱼的动作
       
        int UpProcess,DownProcess;
		if(rank!=1||rank!=size-1)
		{
           UpProcess=rank-1;
           DownProcess=rank+1;
		}
		if(rank==1)
		{
		   UpProcess=size-1;
           DownProcess=rank+1;
		}
		if(rank==size-1)
		{
		   UpProcess=rank-1;
           DownProcess=1;
		}
		
        if(rank==1)
		{
             MPI_Send(revWork+(SubRow-2)*COLUMN,COLUMN,CellType,DownProcess,rank,MPI_COMM_WORLD);
             MPI_Recv(revWork,COLUMN,CellType,UpProcess,UpProcess,MPI_COMM_WORLD,&status);
		}
		else
		{
             MPI_Recv(revWork,COLUMN,CellType,UpProcess,UpProcess,MPI_COMM_WORLD,&status);
		     MPI_Send(revWork+(SubRow-2)*COLUMN,COLUMN,CellType,DownProcess,rank,MPI_COMM_WORLD);
		}

        if(rank==1)
		{
             MPI_Send(revWork+COLUMN,COLUMN,CellType,UpProcess,rank,MPI_COMM_WORLD);
             MPI_Recv(revWork+(SubRow-1)*COLUMN,COLUMN,CellType,DownProcess,DownProcess,MPI_COMM_WORLD,&status);
		}
		else
		{
             MPI_Recv(revWork+(SubRow-1)*COLUMN,COLUMN,CellType,DownProcess,DownProcess,MPI_COMM_WORLD,&status);
		     MPI_Send(revWork+COLUMN,COLUMN,CellType,UpProcess,rank,MPI_COMM_WORLD);
		}
  //      int x=0;
		//if(rank==1)
		//{
		//     OutPutSea(*WorkField,WorkRow,COLUMN);
	 //        fflush(stdout);
		//     MPI_Send(&x,1,MPI_INT,DownProcess,rank,MPI_COMM_WORLD);
		//}
		//else if(rank!=size-1)
		//{
  //           MPI_Recv(&x,1,MPI_INT,UpProcess,UpProcess,MPI_COMM_WORLD,&status);
		//     OutPutSea(*WorkField,WorkRow,COLUMN);
	 //        fflush(stdout);
		//     MPI_Send(&x,1,MPI_INT,DownProcess,rank,MPI_COMM_WORLD);
		//}
		//else
		//{
  //           MPI_Recv(&x,1,MPI_INT,UpProcess,UpProcess,MPI_COMM_WORLD,&status);
		//     OutPutSea(*WorkField,WorkRow,COLUMN);
	 //        fflush(stdout);
		//}

        OutPutSea(*WorkField,WorkRow,COLUMN);
		    fflush(stdout);
		msg.Type=MSG_FINISH;  //子进程完成工作向主进程发送完工消息
		msg.Source=rank;
		MPI_Send(&msg,1,MsgType,0,rank,MPI_COMM_WORLD);

        MPI_Send(WorkField,WorkRow*COLUMN,CellType,0,rank,MPI_COMM_WORLD);
		MPI_Barrier(MPI_COMM_WORLD);
	}
	//cout<<z<<endl;
}

	cout<<"Finish all !"<<endl;
	EndTime=MPI_Wtime();//结束时间
	cout<<"程序执行时间:"<<EndTime-StartTime<<"秒"<<endl;
    fflush(stdout);

	MPI_Finalize();	//终止MPI
}

⌨️ 快捷键说明

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