Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******************************************************************************
- FILE: pp_p2
- AUTHOR: Edward DeMesa
- INSTRUCTOR: Dr. Ralph M. Butler
- DUE DATE: Sep 30, 2019
- DESCRIPTION:
- This program will solve the hotplate problem. It will conform to the same
- interface as p1, but will have one extra command-line argument--the number of
- threads to use. The expectation is the program will get near-linear speed-ups
- as the number of threads increases. At the end, gettimeofday will be used to
- print the time spent in the iteration loops, including all synchronization
- operations. A one-line message will say:
- TOTAL TIME 11.45 ## if 11.45 is the time for all iterations.
- The original thread is the one that produces the printed output. All threads
- will participate in the work.
- ******************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include <unistd.h>
- #include <sys/time.h>
- #include <pthread.h>
- // Global Variables
- float epsilon = 0.0;
- float maxDiff = -1.0; // value is set to something maxDiff can never be
- int iter = 0;
- int i, j; // variables used for loops
- int rows = 0;
- int cols = 0;
- float update = 0.0;
- float** plate1;
- float** plate2;
- int num_threads = 0;
- float* local_max = NULL; // hold the values of all local max of thread
- // Function prototypes
- void* max_diff(void* arg); // pthread routine function prototype
- void swap(float*** plate1, float*** plate2);
- void printMatrix(float** array, int rows, int cols);
- /******************************************************************************
- * main *
- ******************************************************************************/
- int main(int argc, char** argv)
- {
- alarm(600);
- // Struct that holds time value (whole secs or micro secs)
- struct timeval tv;
- /* Variable Declarations */
- float west = 0;
- float east = 0;
- float north = 0;
- float south = 0;
- float average = 0.0;
- /* Read in the values & convert char to int */
- rows = atoi(argv[1]);
- cols = atoi(argv[2]);
- north = atof (argv[3]);
- west = atof (argv[4]);
- east = atof (argv[5]);
- south = atof (argv[6]);
- epsilon = atof(argv[7]);
- num_threads = atoi(argv[8]);
- // Array that holds all local values
- local_max = (float*) malloc(num_threads * sizeof (float) );
- /* Dynamic 2D array using Malloc (heap memory) x number of rows */
- plate1 = (float**) malloc (rows * sizeof (float*) );
- // This holds the previous values while new values are generated
- plate2 = (float**) malloc (rows * sizeof (float*) );
- for (i = 0; i < rows; i++)
- {
- // Generate X number of columns
- plate1[i] = (float*) malloc (cols * sizeof (float)); // 2d array
- plate2[i] = (float*) malloc (cols * sizeof (float)); // 2d array
- }
- // Generate the edges of matrix of 2D array or matrix
- for (i = 0; i < cols; i++)
- {
- plate1[0][i] = north;
- plate2[0][i] = north;
- }
- for (i = 0; i < rows; i++)
- {
- plate1[i][0] = west;
- plate2[i][0] = west;
- }
- for (i = 0; i < rows; i++)
- {
- plate1[i][cols-1] = east;
- plate2[i][cols-1] = east;
- }
- for (i = 0; i < cols; i++)
- {
- plate1[rows-1][i] = south;
- plate2[rows-1][i] = south;
- }
- /* Get sum of values */
- // Get sum of values for north
- for (i = 0; i < cols; i++)
- average += plate1[0][i];
- // Get sum of values for south
- for (i = 0; i < cols; i++)
- average += plate1[rows-1][i];
- // Get sum of values for west
- for (i = 1; i < (rows-1); i++)
- average += plate1[i][0];
- // Get sum of values for east
- for (i = 1; i < (rows-1); i++)
- average += plate1[i][cols-1];
- /* Get average of values by dividing sum of rows and cols*/
- average /= ((rows * 2) + ((cols -2) * 2));
- // Initialize interior with average values
- for (i = 1; i < (rows-1); i++)
- {
- for (j = 1; j < (cols-1); j++)
- {
- plate1[i][j] = average;
- plate2[i][j] = average;
- }
- }
- // Generate start time
- gettimeofday(&tv, NULL);
- suseconds_t starttime = tv.tv_usec;
- // Pthread id creation (array)
- pthread_t id[num_threads];
- // Generate independent id value for each thread
- int pid[num_threads];
- for (int i=0; i<num_threads; i++)
- pid[i] = i;
- /* Cal diff between 2 matrices, find max difference, & compare to epsilon */
- while((maxDiff > epsilon) || (maxDiff < 0))
- {
- float global_change = -1;
- // Using p instead of i to avoid conflict of changing value of global i
- for (int p = 0; p < num_threads; p++)
- {
- // Create pthreads
- pthread_create(&id[p], NULL, max_diff, &pid[p]);
- // Pthread join
- for (i = 0; i < num_threads; i++)
- {
- pthread_join(id[i], NULL);
- }
- }
- // Assign local_max to global_change
- for (i = 0; i < num_threads; i++)
- {
- if(local_max[i] > global_change)
- {
- global_change = local_max[i];
- }
- //printf("%.6f local max \n", local_max[i]);
- }
- // Assign global_change to maxDiff
- if (maxDiff < 0)
- maxDiff = global_change;
- else if (global_change < maxDiff)
- {
- maxDiff = global_change;
- }
- swap(&plate1, &plate2);
- // Print out last element of iteration before epsilon > max difference
- if(iter != 0 && ((iter & (iter - 1)) == 0))
- {
- printf("\n%d\t %.6f \n", iter, maxDiff);
- }
- //printf("%.6f maxDiff\n ", maxDiff);
- //printf("%.6f GC\n ", global_change);
- //printMatrix(plate1, rows, cols);
- //printf("\n");
- //printMatrix(plate2, rows, cols);
- //sleep(3);
- iter++;
- //break;
- }
- // End time
- gettimeofday(&tv, NULL);
- suseconds_t endtime = tv.tv_usec;
- // Print out last element of iteration before epsilon > max difference
- if(iter != 0 && ((iter & (iter - 1)) != 0))
- {
- printf("\n%d\t %.6f \n", iter, maxDiff);
- }
- printf("%.6f total time\n", ((endtime - starttime) / 1000000.0));
- // Free memory
- for (int i = 0; i < rows; i++)
- {
- free (plate1[i]);
- free (plate2[i]);
- }
- free(plate1);
- free(plate2);
- free(local_max);
- return 0;
- }
- /******************************************************************************
- * max_diff function *
- ******************************************************************************/
- void* max_diff(void* arg)
- {
- // Arg (a void pointer) changed to an id
- int id = *((int*)arg);
- // divide the threads
- // always starting at (id times skip value) so that last thread is less
- // than the previous
- int skip_value = 0;
- if(rows % num_threads == 0) // if even
- skip_value = (rows/num_threads);
- else
- skip_value = ((rows/num_threads) + 1);
- // where threads starts to calculate the rows and modifies below rows
- int start = id * skip_value;
- if(id == 0)
- start++;
- // This is the row that we start modifying
- int end = start + skip_value;
- // Do not touch the last row
- if(id == num_threads - 1)
- end = rows - 1;
- // printf("%d.) Start: %d End: %d\n", id, start, end);
- /* Cal diff between 2 arrays, find max difference, & compare to epsilon */
- float max = -1.0;
- float diff = 0.0;
- // Update interior values ( (adding values of four neighbor)/4 )
- for (i = start; i < end; i++)
- {
- for (j = 1; j < (cols-1); j++)
- {
- update = (plate1[i-1][j] + plate1[i][j+1]
- + plate1[i][j-1] + plate1[i+1][j])/4.0;
- plate2[i][j] = update;
- // Calculate difference
- diff = fabs(update - plate1[i][j]);
- // if diff is negative, change it to positive
- if (diff < 0)
- diff *= -1;
- if(diff > max)
- max = diff;
- }
- }
- // updating local max of its maxDiff
- local_max[id] = max;
- // printf("%d) %.6f max\n ", id, max);
- }
- /******************************************************************************
- * swap function *
- ******************************************************************************/
- void swap(float*** plate1, float*** plate2)
- {
- float** tmp = *plate1;
- *plate1 = *plate2;
- *plate2 = tmp;
- }
- /******************************************************************************
- * printMatrix function *
- ******************************************************************************/
- // Note: only use was for debugging
- void printMatrix(float** array, int rows, int cols)
- {
- int r, c;
- for(r = 0; r < rows; r++)
- {
- for(c = 0; c < cols; c++)
- {
- printf("%.2f ", array[r][c]);
- }
- printf("\n");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement