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