📄 pm_separate_rect.cpp
字号:
#include <stdio.h>
#include <stdlib.h>
#include "pmandel.h"
#include "pm_genproc.h"
#include <time.h>
void SplitRect(Flags *flags, rect r);
int SeparateRect_Master(MPE_XGraph graph, Winspecs *winspecs, Flags *flags)
{
bool bWindowClosed = false;
rect *assigList, recvRectBuf[2], tempRect;
/* assigList - list of what rectangles have been assigned to each process */
/* recvRectBuf - when a slave process tells the master that some rectangles
need to be calculated, the rectangle definitions are temporarily stored
here */
int inProgress, nidle, *idleList, splitPt, np,
mesgTag, firstToEnqueue, procNum, i;
/* inProgress - number of rectangles currently under construction */
/* nidle - number of idle processes */
/* idleList - list of process ranks that are idle */
/* splitPt - point at which to split the Mandelbrot set--can't have the
border algorithm enclosing the whole set */
/* np - number of processes */
/* data - one int returned by slave processes; different uses */
/* mesgTag - the tag of the received message */
/* firstToEnqueue - when receiving a bunch of rectangles to enqueue, the
master process may send some off to idle processes right away before
queueing them. firstToEnqueue points to the first one that is actually
queued */
/* procNum - rank of the process that sent the last message */
/* randomPt - index + 1 of the last item in the queue that has not been
placed in random order */
rect_queue rect_q;
/* queue of rectangles to calculate */
MPI_Status mesgStatus;
MPI_Comm_size(MPI_COMM_WORLD, &np);
srand(clock());
/* initialize the random number generator for the -randomize option */
MPE_DESCRIBE_STATE(S_COMPUTE, E_COMPUTE,
"Compute", "blue:gray");
MPE_DESCRIBE_STATE(S_DRAW_BLOCK, E_DRAW_BLOCK,
"Draw block", "yellow:gray3");
MPE_DESCRIBE_STATE(S_DRAW_RECT, E_DRAW_RECT,
"Draw border", "green:light_gray");
MPE_DESCRIBE_STATE(S_WAIT_FOR_MESSAGE, E_WAIT_FOR_MESSAGE,
"Wait for message", "red:boxes");
MPE_DESCRIBE_STATE(S_DRAW_CHUNK, E_DRAW_CHUNK, "Draw Chunk",
"steelBlue:2x2");
assigList = (rect *) malloc((np) * sizeof(rect));
idleList = (int *) malloc((np) * sizeof(rect));
nidle = inProgress = 0;
Q_Create(&rect_q, flags->randomize);
/* create the queue */
if (flags->imin<0 && flags->imax>0)
{ /* might have to split the set */
splitPt = winspecs->height +
NUM2INT(NUM_DIV(NUM_MULT(flags->imin, INT2NUM(winspecs->height)),
NUM_SUB(flags->imax, flags->imin)));
RECT_ASSIGN(tempRect, 0, winspecs->width-1, 0, splitPt-1);
tempRect.length = RectBorderLen(&tempRect);
Q_Enqueue(&rect_q, &tempRect);
RECT_ASSIGN(tempRect, 0, winspecs->width-1, splitPt, winspecs->height-1);
tempRect.length = RectBorderLen(&tempRect);
Q_Enqueue(&rect_q, &tempRect);
}
else
{
RECT_ASSIGN(tempRect, 0, winspecs->width-1, 0, winspecs->height-1);
tempRect.length = RectBorderLen(&tempRect);
Q_Enqueue(&rect_q, &tempRect);
}
int nSlavePoints = 0;
MPE_Point *pSlavePoints = NULL;
MPE_Point p;
rect r;
int wrkOut = 0;
while (!bWindowClosed && (inProgress || !IS_Q_EMPTY(rect_q) || wrkOut))
{ /* while someone's working, and the q is !empty */
MPE_LOG_EVENT(S_WAIT_FOR_MESSAGE, 0, 0);
MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &mesgStatus);
MPE_LOG_RECEIVE(mesgStatus.MPI_SOURCE, mesgStatus.MPI_TAG, 0);
MPE_LOG_EVENT(E_WAIT_FOR_MESSAGE, 0, 0);
procNum = mesgStatus.MPI_SOURCE;
mesgTag = mesgStatus.MPI_TAG;
switch (mesgTag)
{
case READY_TO_START:
inProgress++;
case READY_FOR_MORE:
MPI_Recv(0, 0, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG,
MPI_COMM_WORLD, &mesgStatus);
if (IS_Q_EMPTY(rect_q))
{ /* if the queue is empty, */
idleList[nidle++] = procNum; /* remember this process was left idle */
inProgress--;
}
else
{
Q_Dequeue(&rect_q, &tempRect);
wrkOut++;
MPI_Send(&tempRect, 1, rect_type,
procNum, ASSIGNMENT, MPI_COMM_WORLD);
MPE_LOG_SEND(procNum, ASSIGNMENT, sizeof(rect));
/* otherwise, assign it the next in the queue */
assigList[procNum] = tempRect;
/* remember which rect this process is on */
}
break;
case ADD2Q:
/* slave is posting more rectangles to be queued */
MPI_Recv(recvRectBuf, 2, rect_type, procNum,
ADD2Q, MPI_COMM_WORLD, &mesgStatus);
/* get rect definitions */
firstToEnqueue = 0;
while (nidle && firstToEnqueue < 2)
{
/* if processes are idle, */
nidle--;
assigList[idleList[nidle]] = recvRectBuf[firstToEnqueue];
/* remember which rect this process is on */
wrkOut++;
MPI_Send(recvRectBuf + firstToEnqueue, 1, rect_type,
idleList[nidle], ASSIGNMENT, MPI_COMM_WORLD);
MPE_LOG_SEND(idleList[nidle], ASSIGNMENT, sizeof(rect));
/* give them something to do */
inProgress++; firstToEnqueue++;
}
for (; firstToEnqueue<2; firstToEnqueue++)
{
Q_Enqueue(&rect_q, recvRectBuf + firstToEnqueue);
}
break;
case SENDING_POINTS:
wrkOut--;
/* slave is sending the points that it computed */
MPI_Recv(&nSlavePoints, 1, MPI_INT, procNum, SENDING_POINTS, MPI_COMM_WORLD, &mesgStatus);
if (pSlavePoints)
delete pSlavePoints;
pSlavePoints = new MPE_Point[nSlavePoints];
MPI_Recv(pSlavePoints, nSlavePoints * sizeof(MPE_Point), MPI_BYTE, procNum, SENDING_POINTS, MPI_COMM_WORLD, &mesgStatus);
MPE_Draw_points(graph, pSlavePoints, nSlavePoints);
MPE_Update(graph);
break;
case SENDING_RECTANGLE:
wrkOut--;
/* slave is sending a rectangle to fill with a solid color */
//MPI_Recv(0, 0, MPI_INT, procNum, SENDING_RECTANGLE, MPI_COMM_WORLD, &mesgStatus);
MPI_Recv(&r, sizeof(rect), MPI_BYTE, procNum, SENDING_RECTANGLE, MPI_COMM_WORLD, &mesgStatus);
MPI_Recv(&p, sizeof(MPE_Point), MPI_BYTE, procNum, SENDING_RECTANGLE, MPI_COMM_WORLD, &mesgStatus);
DrawBlock(graph, &p, &r);
MPE_Update(graph);
break;
case WINDOW_CLOSED:
MPI_Recv(0, 0, MPI_INT, procNum, WINDOW_CLOSED, MPI_COMM_WORLD, &mesgStatus);
bWindowClosed = true;
break;
default:
Sleep(0);
/* Give up time slice to minimize effects of busy wait loop */
}
}
for (i = 1; i<np; i++)
{ /* tell everyone to exit */
//printf("telling %d to quit\n", i);fflush(stdout);
MPI_Send(rect_q.r, sizeof(rect), MPI_BYTE, i, ALL_DONE, MPI_COMM_WORLD);
MPE_LOG_SEND(i, ALL_DONE, sizeof(rect));
//*
if (bWindowClosed)
{
//printf("probe called\n");fflush(stdout);
MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &mesgStatus);
//printf("probe returned\n");fflush(stdout);
procNum = mesgStatus.MPI_SOURCE;
mesgTag = mesgStatus.MPI_TAG;
switch (mesgTag)
{
case READY_FOR_MORE:
//printf("ready for more received\n");fflush(stdout);
MPI_Recv(0, 0, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG,
MPI_COMM_WORLD, &mesgStatus);
break;
case ADD2Q:
//printf("add2q received.\n");fflush(stdout);
// slave is posting more rectangles to be queued
MPI_Recv(recvRectBuf, 2, rect_type, procNum,
ADD2Q, MPI_COMM_WORLD, &mesgStatus);
break;
case SENDING_POINTS:
//printf("sending points received\n");fflush(stdout);
// slave is sending the points that it computed
MPI_Recv(&nSlavePoints, 1, MPI_INT, procNum, SENDING_POINTS, MPI_COMM_WORLD, &mesgStatus);
if (pSlavePoints)
delete pSlavePoints;
pSlavePoints = new MPE_Point[nSlavePoints];
MPI_Recv(pSlavePoints, nSlavePoints * sizeof(MPE_Point), MPI_BYTE, procNum, SENDING_POINTS, MPI_COMM_WORLD, &mesgStatus);
MPE_Draw_points(graph, pSlavePoints, nSlavePoints);
MPE_Update(graph);
break;
case SENDING_RECTANGLE:
//printf("sending rectangle received.\n");fflush(stdout);
// slave is sending a rectangle to fill with a solid color
//MPI_Recv(0, 0, MPI_INT, procNum, SENDING_RECTANGLE, MPI_COMM_WORLD, &mesgStatus);
MPI_Recv(&r, sizeof(rect), MPI_BYTE, procNum, SENDING_RECTANGLE, MPI_COMM_WORLD, &mesgStatus);
MPI_Recv(&p, sizeof(MPE_Point), MPI_BYTE, procNum, SENDING_RECTANGLE, MPI_COMM_WORLD, &mesgStatus);
DrawBlock(graph, &p, &r);
MPE_Update(graph);
break;
//default:
//printf("mesgTag: %d\n", mesgTag);fflush(stdout);
}
}
//*/
}
if (bWindowClosed)
return TRUE;
else
return FALSE;
}
void SeparateRect_Slave(MPE_XGraph graph, Winspecs *winspecs, Flags *flags)
{
int x, y, working, isContinuous, mesgTag, myid,
dataSize, *iterData, npoints;
/* x, y - integer counters for the point being calculated */
/* working - whether this process is still working or has been retired */
/* isContinuous - whether the border just computed is one continuous color */
/* borderData - storage for the values calculated */
/* datPtr - pointer into borderData */
/* mesgTag - what type of message was just received */
NUM rstep, istep;
MPE_Point *pointData;
rect r;
/* r - the rectangle being calculated */
MPI_Status mesgStatus;
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
MPI_Send(0, 0, MPI_INT, MASTER_PROC, READY_TO_START, MPI_COMM_WORLD);
MPE_LOG_SEND(MASTER_PROC, READY_TO_START, 0);
working = 1;
NUM_ASSIGN(rstep, NUM_DIV(NUM_SUB(flags->rmax, flags->rmin),
INT2NUM(winspecs->width-1)));
NUM_ASSIGN(istep, NUM_DIV(NUM_SUB(flags->imin, flags->imax),
INT2NUM(winspecs->height-1)));
/* figure out how much data might be stored and allocate space for it */
x = flags->breakout * flags->breakout;
y = 2 * (winspecs->height + winspecs->width);
dataSize = ((y>x) ? y : x);
iterData = (int *) malloc(dataSize * sizeof(int));
pointData = (MPE_Point *) malloc(dataSize * sizeof(MPE_Point));
Fract_SetRegion(flags->rmin, flags->rmax, flags->imin, flags->imax, 0,
winspecs->width-1, 0, winspecs->height-1);
switch (flags->fractal)
{
case MBROT:
Mbrot_Settings(flags->boundary_sq, flags->maxiter);
break;
case JULIA:
Julia_Settings(flags->boundary_sq, flags->maxiter,
flags->julia_r, flags->julia_i);
break;
case NEWTON:
Mbrot_Settings(flags->boundary_sq, flags->maxiter);
break;
}
while (working)
{
MPE_LOG_EVENT(S_WAIT_FOR_MESSAGE, 0, 0);
MPI_Recv(&r, 1, rect_type, MASTER_PROC, MPI_ANY_TAG,
MPI_COMM_WORLD, &mesgStatus);
MPE_LOG_RECEIVE(MASTER_PROC, mesgStatus.MPI_TAG, sizeof(rect));
/* get command from master process */
MPE_LOG_EVENT(E_WAIT_FOR_MESSAGE, 0, 0);
mesgTag = mesgStatus.MPI_TAG;
switch (mesgTag)
{
case ASSIGNMENT: /* new rectangle to compute */
if (r.b-r.t<flags->breakout || r.r-r.l<flags->breakout)
{
/* if smaller than breakout, compute directly */
MPE_LOG_EVENT(S_COMPUTE, 0, 0);
ComputeChunk(flags, &r, pointData, iterData, dataSize, &npoints);
MPE_LOG_EVENT(E_COMPUTE, 0, 0);
MPI_Send(0, 0, MPI_INT, MASTER_PROC, READY_FOR_MORE,
MPI_COMM_WORLD);
MPE_LOG_SEND(MASTER_PROC, READY_FOR_MORE, 0);
MPE_LOG_EVENT(S_DRAW_CHUNK, 0, 0);
//MPE_Draw_points(graph, pointData, npoints);
MPI_Send(&npoints, 1, MPI_INT, MASTER_PROC, SENDING_POINTS, MPI_COMM_WORLD);
MPI_Send(pointData, npoints * sizeof(MPE_Point), MPI_BYTE, MASTER_PROC, SENDING_POINTS, MPI_COMM_WORLD);
//MPE_Update(graph);
MPE_LOG_EVENT(E_DRAW_CHUNK, 0, 0);
}
else
{ /* otherwise, compute the boundary */
MPE_LOG_EVENT(S_COMPUTE, 0, 0);
ComputeBorder(winspecs, flags, &r, pointData,
dataSize, &npoints, &isContinuous);
MPE_LOG_EVENT(E_COMPUTE, 0, 0);
if (!isContinuous)
{
SplitRect(flags, r);
}
MPI_Send(0, 0, MPI_INT, MASTER_PROC, READY_FOR_MORE,
MPI_COMM_WORLD);
MPE_LOG_SEND(MASTER_PROC, READY_FOR_MORE, 0);
if (isContinuous)
{
MPE_LOG_EVENT(S_DRAW_BLOCK, 0, 0);
//DrawBlock(graph, pointData, &r);
//MPI_Send(0, 0, MPI_INT, MASTER_PROC, SENDING_RECTANGLE, MPI_COMM_WORLD);
MPI_Send(&r, sizeof(rect), MPI_BYTE, MASTER_PROC, SENDING_RECTANGLE, MPI_COMM_WORLD);
MPI_Send(pointData, sizeof(MPE_Point), MPI_BYTE, MASTER_PROC, SENDING_RECTANGLE, MPI_COMM_WORLD);
MPE_LOG_EVENT(E_DRAW_BLOCK, 0, 0);
}
else
{
MPE_LOG_EVENT(S_DRAW_RECT, 0, 0);
//MPE_Draw_points(graph, pointData, npoints);
MPI_Send(&npoints, 1, MPI_INT, MASTER_PROC, SENDING_POINTS, MPI_COMM_WORLD);
MPI_Send(pointData, npoints * sizeof(MPE_Point), MPI_BYTE, MASTER_PROC, SENDING_POINTS, MPI_COMM_WORLD);
//MPE_Update(graph);
MPE_LOG_EVENT(E_DRAW_RECT, 0, 0);
}
} /* else !breakout */
break; /* end if case ASSIGNMENT: */
case ALL_DONE:
working = 0;
break;
} /* end of switch */
} /* end of while (working) */
}
void SplitRect(Flags *flags, rect r)
{
int xsplit, ysplit;
rect rectBuf[2];
xsplit = (r.r-r.l)>>1;
ysplit = (r.b-r.t)>>1;
if (xsplit>ysplit)
{
RECT_ASSIGN(rectBuf[0], r.l + 1, r.l + xsplit, r.t + 1, r.b-1);
RECT_ASSIGN(rectBuf[1], r.l + xsplit + 1, r.r-1, r.t + 1, r.b-1);
}
else
{
RECT_ASSIGN(rectBuf[0], r.l + 1, r.r-1, r.t + 1, r.t + ysplit);
RECT_ASSIGN(rectBuf[1], r.l + 1, r.r-1, r.t + ysplit + 1, r.b-1);
}
rectBuf[0].length = RectBorderLen(rectBuf);
rectBuf[1].length = RectBorderLen(rectBuf + 1);
MPI_Send(rectBuf, 2, rect_type, MASTER_PROC,
ADD2Q, MPI_COMM_WORLD);
MPE_LOG_SEND(MASTER_PROC, ADD2Q, sizeof(rect) * 2);
// send the rectangles
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -