Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<stdio.h>
- #include<stdlib.h>
- #include <string.h>
- #include <sys/time.h>
- #include <mpi.h>
- #include <omp.h>
- #define X 2000
- #define Y 50000
- #define NUMSTEPS 10
- #define AMBIENTTEMP 20
- #define HEATTEMP 200
- //Array and Column Creation
- double** Make2DdoubleArray(int arraySizeX, int arraySizeY);
- double* makeCol(void);
- //Array and Column Ops
- void initArray(double** sourceArray, int totalCols);
- void initCol(double* col);
- void removeArray(double** sourceArray, int cols);
- void applyHeat(double** sourceArray, int totalCols);
- void printArray(double** sourceArray, int totalCols);
- //Temp Evaluation
- void evalTemp(double** sourceArray, double** resultArray, double* readLeft, double* sendLeft, double* readRight, double* sendRight, int totalCols, int ID, int NoProc);
- int main(int argc, char **argv)
- {
- //Total Processes, Process ID, Remainder of Cols, Cols per Node, Cols Assigned, Start and End Cols, Total Cols with Buf, Switch, Loop Control Vars, Print Sync
- int NoProc, ID, remainder, perNode, colsAssigned, startCol, endCol,totalCols, cycleSwitch, i, j, Num;
- MPI_Status Status;
- //Used for node synchronization
- int go = 0;
- //Pointers for the arrays
- double** sourceArray;
- double** resultArray;
- double* readLeft;
- double* sendLeft;
- double* readRight;
- double* sendRight;
- //Initialise
- MPI_Init(&argc,&argv);
- MPI_Comm_size(MPI_COMM_WORLD,&NoProc);
- MPI_Comm_rank(MPI_COMM_WORLD,&ID);
- ///////////////////////////////////////////////////////////////////////////////////////////////Break up the cols per node //////////////////////////////////////////////////////////
- //Divide up the cols
- remainder = X%NoProc;
- perNode = ((X - remainder)/NoProc);
- if(remainder == 0)
- {
- colsAssigned = perNode;
- //Find the start and end collumn for this nodes range
- if (ID != 0)
- DONE! {
- Total time taken to complete in seconds is 5.901662ID);
- Message from xz015489@compute-0-11.local on pts/5 at 15:02 ...
- }
- else
- {
- startCol = 0;
- endCol = startCol + colsAssigned - 1;
- }
- }
- else
- {
- //Distribute the remaining cols evenly
- if(ID != 0)
- {
- if (ID < remainder)
- {
- colsAssigned = perNode + 1;
- startCol = (colsAssigned * ID);
- endCol = startCol + colsAssigned - 1;
- }
- else
- {
- colsAssigned = perNode;
- startCol = (((perNode + 1) * remainder) + ((ID - remainder) * perNode));
- endCol = startCol + colsAssigned - 1;
- }
- }
- else
- {
- colsAssigned = perNode + 1;
- startCol = 0;
- endCol = startCol + colsAssigned - 1;
- }
- }
- /////////////////////////////////////////////////////////////Done breaking up the columns, making arrays.../////////////////////////////////////////////////////////////////////
- //Is this node one of the ones on the end as they only have one buffer col
- if((ID == 0) || (ID == (NoProc - 1)))
- {
- //Only have a node to the right/left respecticly so only need to be 1 unit bigger
- sourceArray = Make2DdoubleArray((colsAssigned + 2), (Y + 2));
- resultArray = Make2DdoubleArray((colsAssigned + 2), (Y + 2));
- totalCols = colsAssigned + 2;
- }
- else //Give the node 2 buffer cols for left and right
- {
- //These need to be bigger as they are in the middle and have nodes either side
- sourceArray = Make2DdoubleArray((colsAssigned + 2), (Y + 2));
- resultArray = Make2DdoubleArray((colsAssigned + 2), (Y + 2));
- totalCols = colsAssigned + 2;
- }
- //Cols for sending/recieving left/right
- readLeft = makeCol();
- sendLeft = makeCol();
- readRight = makeCol();
- sendRight = makeCol();
- //Initialise the arrays to the ambient temps
- initArray(sourceArray, totalCols);
- initArray(resultArray, totalCols);
- initCol(readLeft);
- initCol(sendLeft);
- initCol(readRight);
- initCol(sendRight);
- //Apply heat to the edges
- applyHeat(sourceArray, totalCols);
- // printArray(sourceArray, totalCols);
- ////////////////////////////////////////////////////////////////////Done Making Arrays, Processing///////////////////////////////////////////////////////////////////////
- // Gets the current time and saves it
- struct timeval stimev;
- struct timeval itimev;
- unsigned long int itaken;
- gettimeofday(&stimev, NULL);
- go = 0;
- if (ID == 0)
- {
- go = 1;
- }
- if(NoProc > 1)
- {
- cycleSwitch = 0;
- for(i = 0; i < NUMSTEPS; i++)
- {
- //Synchronize all nodes
- // MPI_Bcast(&go, 1, MPI_INT, 0, MPI_COMM_WORLD);
- if(ID != 0)
- {
- go = 0;
- if (ID == 0)
- {
- go = 1;
- }
- if(NoProc > 1)
- {
- cycleSwitch = 0;
- for(i = 0; i < NUMSTEPS; i++)
- {
- //Synchronize all nodes
- // MPI_Bcast(&go, 1, MPI_INT, 0, MPI_COMM_WORLD);
- if(ID != 0)
- {
- go = 0;
- if(cycleSwitch == 0)
- {
- evalTemp(sourceArray, resultArray, readLeft, sendLeft, readRight, sendRight, totalCols, ID, NoProc);
- cycleSwitch = 1;
- }
- else
- {
- evalTemp(resultArray, sourceArray, readLeft, sendLeft, readRight, sendRight, totalCols, ID, NoProc);
- cycleSwitch = 0;
- }
- // MPI_Send(&go, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
- continue;
- }
- else
- {
- printf("Entering Step %d\n", i);
- if(cycleSwitch == 0)
- {
- evalTemp(sourceArray, resultArray, readLeft, sendLeft, readRight, sendRight, totalCols, ID, NoProc);
- cycleSwitch = 1;
- }
- else
- {
- evalTemp(resultArray, sourceArray, readLeft, sendLeft, readRight, sendRight, totalCols, ID, NoProc);
- cycleSwitch = 0;
- }
- for(i = 0; i < NUMSTEPS; i++)
- {
- printf("Node 0 entering step %d\n", i);
- if(cycleSwitch == 0)
- {
- evalTemp(sourceArray, resultArray, readLeft, sendLeft, readRight, sendRight, totalCols, ID, NoProc);
- cycleSwitch = 1;
- }
- else
- {
- evalTemp(resultArray, sourceArray, readLeft, sendLeft, readRight, sendRight, totalCols, ID, NoProc);
- cycleSwitch = 0;
- }
- }
- }
- /*
- DONE! //Round Robin Approach to Synchronizing Printing
- Num = ID;
- if(ID == 0)
- {
- printf("###NODE %d ###", ID);
- printArray(sourceArray, totalCols);
- printArray(resultArray, totalCols);
- printf("\n");
- MPI_Send(&Num, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
- MPI_Recv(&Num, 1, MPI_INT, (NoProc - 1), MPI_ANY_TAG, MPI_COMM_WORLD, &Status);
- }
- if((ID >= 1)&& (ID < (NoProc - 1)))
- {
- MPI_Recv(&Num, 1, MPI_INT, (ID - 1), MPI_ANY_TAG, MPI_COMM_WORLD, &Status);
- printf("###NODE %d ###", ID);
- printArray(sourceArray, totalCols);
- printArray(resultArray, totalCols);
- printf("\n");
- MPI_Send(&Num, 1, MPI_INT, (ID + 1), 0, MPI_COMM_WORLD);
- }
- if(ID == (NoProc - 1))
- {
- MPI_Recv(&Num, 1, MPI_INT, (ID - 1), MPI_ANY_TAG, MPI_COMM_WORLD, &Status);
- printf("###NODE %d ###", ID);
- printArray(sourceArray, totalCols);
- printArray(resultArray, totalCols);
- printf("\n");
- MPI_Send(&Num, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
- }
- */
- //Re-Measure The Time and Print It
- gettimeofday(&itimev, NULL);
- itaken = ((itimev.tv_sec * 1000000) + itimev.tv_usec) - ((stimev.tv_sec * 1000000) + stimev.tv_usec);
- printf("Total time taken to complete in seconds is %ld.%06ld by node %d for %d cols\n", itaken / 1000000, itaken % 1000000, ID, totalCols);
- //////////////////////////////////////////////////////////Cleaning Arrays and Finishing////////////////////////////////////////////////////////////////
- removeArray(sourceArray, totalCols);
- removeArray(resultArray, totalCols);
- free(readLeft);
- free(readRight);
- free(sendLeft);
- free(sendRight);
- MPI_Finalize();
- }
- ///////////////////////////////////////////////////////////////////END OF MAIN//////////////////////////////////////////////////////////
- void initArray(double** sourceArray, int totalCols)
- {
- int i = 0;
- int j = 0;
- for (i = 0; i < (Y + 2); i++)
- {
- for (j = 0; j < totalCols; j++)
- {
- sourceArray[j][i] = AMBIENTTEMP;
- }
- DONE! }
- }
- void initCol(double* col)
- {
- int i = 0;
- for(i = 0; i < Y; i++)
- {
- col[i] = AMBIENTTEMP;
- }
- col[0] = HEATTEMP;
- }
- double** Make2DdoubleArray(int arraySizeX, int arraySizeY)
- {
- double** newArray;
- int i = 0;
- newArray = (double**) malloc(arraySizeX*sizeof(double*));
- for (i = 0; i < arraySizeX; i++)
- {
- newArray[i] = (double*) malloc(arraySizeY*sizeof(double));
- }
- return newArray;
- }
- double* makeCol(void)
- {
- double* newArray;
- newArray = (double*)malloc(Y*sizeof(double));
- return newArray;
- }
- void removeArray(double** sourceArray, int cols)
- {
- int i = 0;
- for (i = 0; i < cols; i++)
- {
- free(sourceArray[i]);
- }
- }
- void applyHeat(double** sourceArray, int totalCols)
- {
- int i = 0;
- double val;
- for (i = 1; i < (totalCols - 1); i++)
- {
- sourceArray[i][1] = HEATTEMP;
- }
- }
- void printArray(double** sourceArray, int totalCols)
- {
- int i = 0;
- int j = 0;
- for (i = 0; i < (Y + 2); i++)
- {
- for (j = 0; j < totalCols; j++)
- {
- if (j == 0)
- {
- printf("\n");
- }
- printf("%f ", sourceArray[j][i]);
- }
- }
- printf("\n");
- }
- void evalTemp(double** sourceArray, double** resultArray, double* readLeft, double* sendLeft, double* readRight, double* sendRight, int totalCols, int ID, int NoProc)
- {
- //Used for calculating and sending
- double prevT;
- double prevTup;
- //MPI Values
- MPI_Status Status;
- double prevTdown;
- double prevTleft;
- double prevTright;
- //Values to send to and recieve from
- int sendID;
- int recieveID;
- //Loop control
- int i = 0;
- int j = 0;
- // #pragma omp parallel
- for (i = 1; i < (Y + 1); i++)
- {
- for (j = 1; j < (totalCols - 1); j++)
- {
- {
- resultArray[j][i] = ((sourceArray[j][i] + sourceArray[(j - 1)][i] + sourceArray[(j + 1)][i] + sourceArray[j][(i - 1)] + sourceArray[j][(i + 1)]) / 5);
- }
- }
- }
- //Synced send doesnt return until matching recieve
- if(NoProc > 1)
- {
- if(ID == 0)
- {
- //Send the right hand col right
- MPI_Send(resultArray[(totalCols - 2)],Y, MPI_DOUBLE, ID+1, 0, MPI_COMM_WORLD);
- //Recieve next nodes left hand col
- MPI_Recv(resultArray[(totalCols - 1)],Y, MPI_DOUBLE, ID+1, MPI_ANY_TAG, MPI_COMM_WORLD, &Status);
- }
- else if(ID == NoProc-1)
- {
- //Recieve previous nodes right hand col
- MPI_Recv(resultArray[0],Y, MPI_DOUBLE, ID-1, MPI_ANY_TAG, MPI_COMM_WORLD, &Status);
- //Send the right hand col right
- MPI_Send(resultArray[1],Y, MPI_DOUBLE, ID-1, 0, MPI_COMM_WORLD);
- }
- else
- {
- //Recieve previous nodes right hand col
- MPI_Recv(resultArray[0],Y, MPI_DOUBLE, ID-1, MPI_ANY_TAG, MPI_COMM_WORLD, &Status);
- //Send left hand col to previous node
- MPI_Send(resultArray[1],Y, MPI_DOUBLE, ID-1, 0, MPI_COMM_WORLD);
- //Send right hand col to next node
- MPI_Send(resultArray[(totalCols - 2)],Y, MPI_DOUBLE, ID+1, 0, MPI_COMM_WORLD);
- //Recieve left hand col from next node
- MPI_Recv(resultArray[(totalCols - 1)],Y, MPI_DOUBLE, ID+1, MPI_ANY_TAG, MPI_COMM_WORLD, &Status);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement