Advertisement
Guest User

Untitled

a guest
Sep 22nd, 2019
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.95 KB | None | 0 0
  1. /******************************************************************************
  2. FILE:  pp_p2
  3. AUTHOR:  Edward DeMesa
  4. INSTRUCTOR:  Dr. Ralph M. Butler
  5. DUE DATE:  Sep 30, 2019
  6. DESCRIPTION:
  7.  
  8. This program will solve the hotplate problem.  It will conform to the same
  9. interface as p1, but will have one extra command-line argument--the number of
  10. threads to use.  The expectation is the program will get near-linear speed-ups
  11. as the number of threads increases.  At the end, gettimeofday will be used to
  12. print the time spent in the iteration loops, including all synchronization
  13. operations. A one-line message will say:
  14.  
  15.         TOTAL TIME 11.45 ## if 11.45 is the time for all iterations.
  16.  
  17. The original thread is the one that produces the printed output.  All threads
  18. will participate in the work.
  19.  
  20. ******************************************************************************/
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <math.h>
  25. #include <unistd.h>
  26. #include <sys/time.h>
  27. #include <pthread.h>
  28.  
  29. // Global Variables
  30. float epsilon = 0.0;
  31. float maxDiff = -1.0;  // value is set to something maxDiff can never be
  32. int iter = 0;
  33. int i, j; // variables used for loops
  34. int rows = 0;
  35. int cols = 0;
  36. float update = 0.0;
  37. float** plate1;
  38. float** plate2;
  39. int num_threads = 0;
  40. float* local_max = NULL; // hold the values of all local max of thread
  41.  
  42. // Function prototypes
  43. void* max_diff(void* arg); // pthread routine function prototype
  44. void swap(float*** plate1, float*** plate2);
  45. void printMatrix(float** array, int rows, int cols);
  46.  
  47.  
  48. /******************************************************************************
  49. *                                main                                         *
  50. ******************************************************************************/
  51. int main(int argc, char** argv)
  52. {
  53.     alarm(600);
  54.  
  55.         // Struct that holds time value (whole secs or micro secs)
  56.         struct timeval tv;
  57.  
  58.     /* Variable Declarations */
  59.     float west = 0;
  60.     float east = 0;
  61.     float north = 0;
  62.     float south = 0;
  63.     float average = 0.0;
  64.  
  65.     /* Read in the values & convert char to int */
  66.     rows = atoi(argv[1]);
  67.     cols = atoi(argv[2]);
  68.     north = atof (argv[3]);
  69.     west = atof (argv[4]);
  70.     east = atof (argv[5]);
  71.     south = atof (argv[6]);
  72.     epsilon = atof(argv[7]);
  73.     num_threads = atoi(argv[8]);
  74.  
  75.         // Array that holds all local values
  76.         local_max = (float*) malloc(num_threads * sizeof (float) );
  77.  
  78.     /* Dynamic 2D array using  Malloc (heap memory) x number of rows */
  79.     plate1 = (float**) malloc (rows * sizeof (float*) );
  80.  
  81.     // This holds the previous values while new values are generated
  82.     plate2 = (float**) malloc (rows * sizeof (float*) );
  83.  
  84.     for (i = 0; i < rows; i++)
  85.     {
  86.         // Generate X number of columns
  87.         plate1[i] = (float*) malloc (cols * sizeof (float));  // 2d array
  88.         plate2[i] = (float*) malloc (cols * sizeof (float));  // 2d array
  89.     }
  90.  
  91.     // Generate the edges of matrix of 2D array or matrix
  92.     for (i = 0; i < cols; i++)
  93.     {
  94.         plate1[0][i] = north;
  95.         plate2[0][i] = north;
  96.     }
  97.  
  98.     for (i = 0; i < rows; i++)
  99.     {
  100.         plate1[i][0] = west;
  101.         plate2[i][0] = west;
  102.     }
  103.  
  104.         for (i = 0; i < rows; i++)
  105.     {
  106.         plate1[i][cols-1] = east;
  107.         plate2[i][cols-1] = east;
  108.     }
  109.  
  110.     for (i = 0; i < cols; i++)
  111.     {
  112.         plate1[rows-1][i] = south;
  113.         plate2[rows-1][i] = south;
  114.     }
  115.  
  116.     /* Get sum of values */
  117.     // Get sum of values for north
  118.     for (i = 0; i < cols; i++)
  119.         average += plate1[0][i];
  120.     // Get sum of values for south
  121.     for (i = 0; i < cols; i++)
  122.         average += plate1[rows-1][i];
  123.     // Get sum of  values for west
  124.     for (i = 1; i < (rows-1); i++)
  125.         average += plate1[i][0];
  126.     // Get sum of  values for east
  127.     for (i = 1; i < (rows-1); i++)
  128.         average += plate1[i][cols-1];
  129.  
  130.     /* Get average of values by dividing sum of rows and cols*/
  131.     average /= ((rows * 2) + ((cols -2) * 2));
  132.  
  133.     // Initialize interior with average values
  134.     for (i = 1; i < (rows-1); i++)
  135.     {
  136.         for (j = 1; j < (cols-1); j++)
  137.         {
  138.             plate1[i][j] = average;
  139.             plate2[i][j] = average;
  140.         }
  141.     }
  142.  
  143.         // Generate start time
  144.         gettimeofday(&tv, NULL);
  145.         suseconds_t starttime = tv.tv_usec;
  146.  
  147.         // Pthread id creation (array)
  148.         pthread_t id[num_threads];
  149.  
  150.         // Generate independent id value for each thread
  151.         int pid[num_threads];
  152.         for (int i=0; i<num_threads; i++)
  153.                 pid[i] = i;
  154.  
  155.     /* Cal diff between 2 matrices, find max difference, & compare to epsilon */
  156.     while((maxDiff > epsilon) || (maxDiff < 0))
  157.         {
  158.                 float global_change = -1;
  159.                 // Using p instead of i to avoid conflict of changing value of global i
  160.                 for (int p = 0; p < num_threads; p++)
  161.             {
  162.                         // Create pthreads
  163.                     pthread_create(&id[p], NULL, max_diff, &pid[p]);
  164.  
  165.                         // Pthread join
  166.                         for (i = 0; i < num_threads; i++)
  167.                 {
  168.                         pthread_join(id[i], NULL);
  169.                 }
  170.             }
  171.  
  172.                 // Assign local_max to global_change
  173.             for (i = 0; i < num_threads; i++)
  174.                 {
  175.                         if(local_max[i] > global_change)
  176.                         {
  177.                         global_change = local_max[i];
  178.                         }
  179.                         //printf("%.6f local max \n", local_max[i]);
  180.                 }
  181.  
  182.                 // Assign global_change to maxDiff
  183.                 if (maxDiff < 0)
  184.                         maxDiff = global_change;
  185.                 else if (global_change < maxDiff)
  186.                 {
  187.                         maxDiff = global_change;
  188.                 }
  189.  
  190.                 swap(&plate1, &plate2);
  191.  
  192.                 // Print out last element of iteration before epsilon > max difference
  193.                 if(iter != 0 && ((iter & (iter - 1)) == 0))
  194.                 {
  195.                           printf("\n%d\t %.6f \n", iter, maxDiff);
  196.                 }
  197.  
  198.             //printf("%.6f maxDiff\n ", maxDiff);
  199.             //printf("%.6f GC\n ", global_change);
  200.                 //printMatrix(plate1, rows, cols);
  201.                 //printf("\n");
  202.                 //printMatrix(plate2, rows, cols);
  203.                 //sleep(3);
  204.                 iter++;
  205.                 //break;
  206.         }
  207.  
  208.         // End time
  209.         gettimeofday(&tv, NULL);
  210.         suseconds_t endtime = tv.tv_usec;
  211.  
  212.     // Print out last element of iteration before epsilon > max difference
  213.     if(iter != 0 && ((iter & (iter - 1)) != 0))
  214.     {
  215.           printf("\n%d\t %.6f \n", iter, maxDiff);
  216.     }
  217.  
  218.         printf("%.6f total time\n", ((endtime - starttime) / 1000000.0));
  219.  
  220.         // Free memory
  221.         for (int i = 0; i < rows; i++)
  222.         {
  223.                 free (plate1[i]);
  224.                 free (plate2[i]);
  225.         }
  226.         free(plate1);
  227.         free(plate2);
  228.         free(local_max);
  229.  
  230.     return 0;
  231. }
  232.  
  233. /******************************************************************************
  234. *                             max_diff function                               *
  235. ******************************************************************************/
  236. void* max_diff(void* arg)
  237. {
  238.         // Arg (a void pointer) changed to an id
  239.         int id = *((int*)arg);
  240.  
  241.         // divide the threads
  242.         // always starting at (id times skip value) so that last thread is less
  243.         // than the previous
  244.         int skip_value = 0;
  245.         if(rows % num_threads == 0) // if even
  246.                 skip_value = (rows/num_threads);
  247.  
  248.         else
  249.                 skip_value = ((rows/num_threads) + 1);
  250.  
  251.         // where threads starts to calculate the rows and modifies below rows
  252.         int start = id * skip_value;
  253.         if(id == 0)
  254.                 start++;
  255.  
  256.         // This is the row that we start modifying
  257.         int end = start + skip_value;
  258.  
  259.         // Do not touch the last row
  260.         if(id == num_threads - 1)
  261.                 end = rows - 1;
  262.  
  263. //      printf("%d.) Start: %d End: %d\n", id, start, end);
  264.  
  265.     /* Cal diff between 2 arrays, find max difference, & compare to epsilon */
  266.         float max = -1.0;
  267.     float diff = 0.0;
  268.     // Update interior values ( (adding values of four neighbor)/4 )
  269.     for (i = start; i < end; i++)
  270.     {
  271.         for (j = 1; j < (cols-1); j++)
  272.         {
  273.                 update = (plate1[i-1][j] + plate1[i][j+1]
  274.                       + plate1[i][j-1] + plate1[i+1][j])/4.0;
  275.             plate2[i][j] = update;
  276.  
  277.             // Calculate difference
  278.             diff = fabs(update - plate1[i][j]);
  279.                         // if diff is negative, change it to positive
  280.                         if (diff < 0)
  281.                                 diff *= -1;
  282.             if(diff > max)
  283.             max = diff;
  284.          }
  285.     }
  286.         // updating local max of its maxDiff
  287.         local_max[id] = max;
  288. //      printf("%d) %.6f max\n ", id, max);
  289. }
  290.  
  291. /******************************************************************************
  292. *                              swap function                                  *
  293. ******************************************************************************/
  294. void swap(float*** plate1, float*** plate2)
  295. {
  296.         float** tmp = *plate1;
  297.     *plate1 = *plate2;
  298.     *plate2 = tmp;
  299. }
  300.  
  301.  
  302. /******************************************************************************
  303. *                            printMatrix function                             *
  304. ******************************************************************************/
  305. // Note:  only use was for debugging
  306. void printMatrix(float** array, int rows, int cols)
  307. {
  308.     int r, c;
  309.     for(r = 0; r < rows; r++)
  310.     {
  311.         for(c = 0; c < cols; c++)
  312.         {
  313.             printf("%.2f ", array[r][c]);
  314.         }
  315.         printf("\n");
  316.     }
  317. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement