C   28
average parallel
Guest on 14th March 2023 12:07:17 AM


  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <mpi.h>
  5.  
  6. #define TAG_NUMBER     100
  7. #define TAG_DATA       101
  8. #define TAG_SUM        102
  9. #define TAG_AVERAGE    103
  10. #define TAG_STD_DEV    104
  11.  
  12.  
  13. int master(int argc, char *argv[], int rank, int size);
  14. int slave(int rank);
  15.  
  16. int main(int argc, char *argv[])
  17. {
  18.   int rank, size;
  19.  
  20.   MPI_Init(&argc, &argv);
  21.   MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  22.   MPI_Comm_size(MPI_COMM_WORLD, &size);
  23.  
  24.   if (size == 1)
  25.     {
  26.       fprintf(stderr, "%s requires more than one node\n", argv[0]);
  27.       return EXIT_FAILURE;
  28.     }
  29.        
  30.   if (rank == 0)
  31.     master(argc, argv, rank, size);
  32.   else
  33.     slave(rank);
  34.  
  35.   MPI_Finalize();
  36.   return EXIT_SUCCESS;
  37. }
  38.  
  39. int master(int argc, char *argv[], int rank, int size)
  40. {
  41.   FILE        *fp;
  42.   char        *file_name = "data";
  43.   int         N, N_local, N_local_residual, process, i, err;
  44.   double      *data, x, average, diff, std_dev, local_sum;
  45.   MPI_Status  recv_status;
  46.  
  47.   // parse arguments
  48.   if (argc > 1)
  49.     file_name = argv[1];
  50.  
  51.   // setup
  52.  
  53.   // open the file
  54.   if ((fp = fopen(file_name, "r")) == NULL)
  55.     {
  56.       fprintf(stderr, "error in opening data file %s\n", file_name);
  57.       return EXIT_FAILURE;
  58.     }
  59.  
  60.   // read the size of the data file
  61.   fscanf(fp, "# %d", &N);
  62.   printf("reading %d points\n", N);
  63.  
  64.   N_local = N / size;           // size of data chunks on each node
  65.   N_local_residual = N % size;  // extra points for the master node
  66.  
  67.   // allocate memory to hold a data chunk
  68.   data = (double *)malloc(sizeof(double) * (N_local+N_local_residual));
  69.   if (data == NULL)
  70.     {
  71.       fprintf(stderr, "could not allocate %d bytes\n", sizeof(double)* N_local);
  72.       return EXIT_FAILURE;
  73.     }
  74.  
  75.   for (process=1 ; process < size ; process++)
  76.     {
  77.       // send # of numbers to node
  78.       MPI_Ssend(&N_local, 1, MPI_INT, process, TAG_NUMBER, MPI_COMM_WORLD);
  79.  
  80.       // read in the data
  81.       for (i=0; i < N_local; i++)
  82.         fscanf(fp, "%lf %lf", &x, &data[i]);
  83.  
  84.       // send data to the node
  85.       MPI_Ssend(data, N_local, MPI_DOUBLE, process, TAG_DATA, MPI_COMM_WORLD);
  86.     }
  87.  
  88.   N_local += N_local_residual;
  89.  
  90.   // read in data for the master
  91.   for (i=0; i < N_local; i++)
  92.     fscanf(fp, "%lf %lf", &x, &data[i]);
  93.  
  94.   // close file
  95.   fclose(fp);
  96.  
  97.   printf("computing\n");
  98.   average = 0;
  99.   for (i=0; i < N_local; i++)
  100.     average += data[i];
  101.   printf(" node %d - N %d, average %f\n",
  102.          rank, N_local, average/N_local);
  103.  
  104.   // collect sums from other nodes
  105.   for (process=1; process < size; process++)
  106.     {
  107.       err = MPI_Recv(&local_sum, 1, MPI_DOUBLE, MPI_ANY_SOURCE, TAG_SUM,
  108.                      MPI_COMM_WORLD, &recv_status);
  109.       average += local_sum;
  110.     }
  111.  
  112.   printf("sum: %f\n", average);
  113.   average /= N;
  114.   printf("average: %f\n", average);
  115.  
  116.   // distribute average to nodes
  117.   for (process=1; process < size; process++)
  118.     {
  119.       MPI_Ssend(&average, 1, MPI_DOUBLE, process, TAG_AVERAGE,
  120.                 MPI_COMM_WORLD);
  121.     }
  122.  
  123.   // standard deviation
  124.   std_dev = 0.0;
  125.   for (i=0; i < N_local; i++) {
  126.     diff = data[i] - average;
  127.     std_dev += diff * diff;
  128.   }
  129.   printf(" node %d - std dev %f\n", rank, std_dev/N_local);
  130.  
  131.   // collect sums from other nodes
  132.   for (process=1; process<size; process++)
  133.     {
  134.       MPI_Recv(&local_sum, 1, MPI_DOUBLE, MPI_ANY_SOURCE, TAG_STD_DEV,
  135.                MPI_COMM_WORLD, &recv_status);
  136.       std_dev = std_dev + local_sum;
  137.     }
  138.  
  139.   std_dev = sqrt(std_dev / (N-1));
  140.   printf("standard deviation: %f\n", std_dev);
  141.  
  142.   // cleanup and exit
  143.   free(data);
  144.   return EXIT_SUCCESS;
  145. }
  146.  
  147. int slave(int rank)
  148. {
  149.   int        master=0, N, i, err;
  150.   double     *data, average, sum, diff;
  151.   MPI_Status recv_status;
  152.  
  153.   // get the number of numbers to analyze locally
  154.   err = MPI_Recv(&N, 1, MPI_INT, master, TAG_NUMBER, MPI_COMM_WORLD,
  155.                  &recv_status);
  156.  
  157.   // allocate memory to hold a data chunk
  158.   data = (double *)malloc(sizeof(double)*N);
  159.   if (data == NULL)
  160.     {
  161.       fprintf(stderr, "could not allocate %d bytes\n", sizeof(double)* N);
  162.       return EXIT_FAILURE;
  163.     }
  164.  
  165.   // get the data
  166.   err = MPI_Recv(data, N, MPI_DOUBLE, master, TAG_DATA, MPI_COMM_WORLD,
  167.                  &recv_status);
  168.  
  169.   // average (local sum)
  170.   sum = 0.0;
  171.   for (i=0; i < N; i++)
  172.     sum = sum + data[i];
  173.   printf(" node %d - N %d, average %f\n", rank, N, sum/N);
  174.  
  175.   // send local sum to master
  176.   MPI_Ssend(&sum, 1, MPI_DOUBLE, master, TAG_SUM, MPI_COMM_WORLD);
  177.  
  178.   // get the average
  179.   MPI_Recv(&average, 1, MPI_DOUBLE, master, TAG_AVERAGE, MPI_COMM_WORLD,
  180.            &recv_status);
  181.  
  182.   //standard deviation
  183.   sum = 0.0;
  184.   for (i=0; i < N; i++)
  185.     {
  186.       diff = data[i] - average;
  187.       sum += diff * diff;
  188.     }
  189.   printf(" node %d - std dev sum %f\n", rank, sum/N);
  190.  
  191.   // send local sum to master
  192.   MPI_Ssend(&sum, 1, MPI_DOUBLE, master, TAG_STD_DEV, MPI_COMM_WORLD);
  193.  
  194.   // cleanup and exit
  195.   free(data);
  196.   return EXIT_SUCCESS;
  197. }

Raw Paste

Login or Register to edit or fork this paste. It's free.