Advertisement
Guest User

Untitled

a guest
Jun 27th, 2017
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* File:     mpi_prime.c
  2.  * Purpose:  Find all primes less than or equal to an input value.
  3.  *           This version doesn't bother checking even ints.
  4.  *
  5.  * Input:    n:  integer >= 2 (from command line)
  6.  * Output:   Sorted list of primes between 2 and n,
  7.  *
  8.  * Compile:  gcc -g -Wall -o primes1 primes1.c -lm
  9.  * Usage:    ./primes1 <n>
  10.  *              n:  max int to test for primality
  11.  *
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <math.h>
  17. #include <string.h>
  18. #include "mpi.h"
  19.  
  20. //#define DEBUG
  21.  
  22. void Merge(int** all_primes, int *all_count, int* received_primes,
  23.         int received_count, int** temp);
  24.  
  25. /* Helper Functions */
  26. int Is_prime(int i);
  27. int Sum(int A[], int n);
  28. int Get_n(int argc, char* argv[]);
  29. int Smallest_power_two(int p);
  30. void Usage(char prog[]);
  31. void Print_vector(char* title, int y[], int m, int my_rank);
  32.  
  33. int main(int argc, char* argv[]) {
  34.     int n, i, p, my_rank;
  35.     int local_count, my_count, received_count, sum_count;
  36.     int divisor, proc_diff, partner, done, i_send;
  37.     int *local_primes, *received_primes, *all_primes, *all_counts, *temp;
  38.     MPI_Comm comm;
  39.     char title[100];
  40.  
  41.     MPI_Init(&argc, &argv);
  42.     comm = MPI_COMM_WORLD;
  43.     MPI_Comm_size(comm, &p);
  44.     MPI_Comm_rank(comm, &my_rank);
  45.  
  46.     if (my_rank == 0)
  47.         n = Get_n(argc, argv);
  48.  
  49.     MPI_Bcast(&n, 1, MPI_INT, 0, comm);
  50.  
  51.     if (n <= 1) {
  52.         if (my_rank == 0)
  53.             Usage();
  54.         return 0;
  55.     } else if (n == 2) {
  56.         if (my_rank == 0)
  57.             printf("The primes < 2 are: 2");
  58.         return 0;
  59.     }
  60.  
  61.     local_primes = malloc(n / (2 * p) + 2 * sizeof(int));
  62.  
  63.     // logic for getting 'my' primes
  64.     for (i = 2 * my_rank + 3, local_count = 0; i < n; i += 2 * p) {
  65.         if (Is_prime(i)) {
  66.             local_primes[local_count] = i;
  67.             local_count++;
  68.         }
  69.     }
  70.  
  71.     // get the amount of primes
  72.     all_counts = malloc(p * sizeof(int));
  73.     MPI_Allgather(&local_count, 1, MPI_INT, all_counts, 1, MPI_INT, comm);
  74.  
  75.     sum_count = Sum(all_counts, p);
  76.  
  77.     // make three arrays that are big enough to store all primes from all processes
  78.     all_primes = malloc(sum_count * sizeof(int));
  79.     received_primes = malloc(sum_count * sizeof(int));
  80.     temp = malloc(sum_count * sizeof(int));
  81.  
  82.     // copy over my values to beginning of all_primes array
  83.     for (i = 0; i < local_count; i++)
  84.         all_primes[i] = local_primes[i];
  85.     free(local_primes);
  86.  
  87. #   ifdef DEBUG
  88.     MPI_Barrier(comm);
  89.     sprintf(title,"all_primes: only my primes");
  90.     Print_vector(title, all_primes, local_count, my_rank);
  91.     fflush(stdout);
  92. #   endif
  93.  
  94.     divisor = 2;
  95.     proc_diff = 1;
  96.     done = 0;
  97.     my_count = local_count;
  98.  
  99.     while (!done && divisor <= Smallest_power_two(p)) {
  100.         i_send = my_rank % divisor;
  101.         if (i_send) {
  102.             partner = my_rank - proc_diff;
  103. #           ifdef DEBUG
  104.             sprintf(title,"my_count %d | proc_diff %d | snd all_primes to %d: ", my_count, proc_diff, partner);
  105.             Print_vector(title, all_primes, my_count, my_rank);
  106.             fflush(stdout);
  107. #           endif
  108.             // send all my primes over to my partner
  109.             MPI_Send(all_primes, my_count, MPI_INT, partner, 0, comm);
  110.             done = 1;
  111.         } else { /* I'm receiving */
  112.             partner = my_rank + proc_diff;
  113.             if (partner < p) {
  114.                 // calculate how many primes i should be receiving from partner
  115.                 received_count = Sum(&(all_counts[partner]), (partner
  116.                         + proc_diff < p) ? proc_diff : p - partner);
  117.                 // receive primes from my partner
  118.                 MPI_Recv(received_primes, received_count, MPI_INT, partner, 0,
  119.                         comm, MPI_STATUS_IGNORE);
  120. #               ifdef DEBUG
  121.                 sprintf(title,"received_count %d | proc_diff %d | rcv all_primes from %d: ", received_count, proc_diff, partner);
  122.                 Print_vector(title, received_primes, received_count, my_rank);
  123.                 fflush(stdout);
  124. #               endif
  125.  
  126.                 // merge my primes with the ones i just received, updating all_primes
  127.                 Merge(&all_primes, &my_count, received_primes, received_count,
  128.                         &temp);
  129. #               ifdef DEBUG
  130.                 sprintf(title,"my_count %d | proc_diff %d | merged: ", my_count, proc_diff);
  131.                 Print_vector(title, all_primes, my_count, my_rank);
  132.                 fflush(stdout);
  133. #               endif
  134.             }
  135.             divisor *= 2;
  136.             proc_diff *= 2;
  137.         }
  138.     }
  139.  
  140.     // process 0 will print out the final list
  141.     if (my_rank == 0) {
  142.         sprintf(title,"The primes < %d are: 2", n);
  143.         Print_vector(title, all_primes, my_count, my_rank);
  144.     }
  145.  
  146.     free(all_primes);
  147.     free(received_primes);
  148.     free(temp);
  149.  
  150.     MPI_Finalize();
  151.     return 0;
  152. } /* main */
  153.  
  154. /*-------------------------------------------------------------------
  155.  * Function:   Is_prime
  156.  * Purpose:    Determine whether the argument is prime
  157.  * Input arg:  i
  158.  * Return val: true (nonzero) if arg is prime, false (zero) otherwise
  159.  */
  160. int Is_prime(int i) {
  161.     int j;
  162.     int sqrt_i;
  163.  
  164.     sqrt_i = sqrt(i);
  165.     for (j = 2; j <= sqrt_i; j++)
  166.         if (i % j == 0)
  167.             return 0;
  168.     return 1;
  169. } /* Is_prime */
  170.  
  171. /*-------------------------------------------------------------------
  172.  * Function:   Merge
  173.  * Purpose:    Merge the contents of the arrays A and B into array C
  174.  * Input args:
  175.  *    asize:  the number of elements in A
  176.  *    bsize:  the number of elements in B
  177.  *    csize:  the number of elements in C
  178.  *    A, B:  the arrays
  179.  * Output arg:
  180.  *    C:  result array
  181.  */
  182. void Merge(int** all_primes, int *all_count, int* received_primes,
  183.         int received_count, int** temp) {
  184.     int all_i, received_i, temp_i, all_count_t;
  185.     int *all_p, *temp_p;
  186.  
  187.     // set temporary array pointers
  188.     all_p = *all_primes;
  189.     temp_p = *temp;
  190.  
  191.     // save all_primes count and set temp primes count to total
  192.     all_count_t = *all_count;
  193.     *all_count = all_count_t + received_count;
  194.  
  195.     all_i = received_i = temp_i = 0;
  196.  
  197.     // merge lists
  198.     while (all_i < all_count_t && received_i < received_count) {
  199.         if (all_p[all_i] <= received_primes[received_i]) {
  200.             temp_p[temp_i] = all_p[all_i];
  201.             all_i++;
  202.         } else {
  203.             (*temp)[temp_i] = received_primes[received_i];
  204.             received_i++;
  205.         }
  206.         temp_i++;
  207.     }
  208.  
  209.     // fill in the tail end
  210.     if (all_i >= all_count_t)
  211.         for (; temp_i < *all_count; temp_i++, received_i++)
  212.             temp_p[temp_i] = received_primes[received_i];
  213.     else
  214.         for (; temp_i < *all_count; temp_i++, all_i++)
  215.             temp_p[temp_i] = all_p[all_i];
  216.  
  217.     // set all_primes to point to the answer array temp
  218.     *all_primes = temp_p;
  219.     // set temp to point to original all_primes (for re-use)
  220.     *temp = all_p;
  221.  
  222. } /* Merge */
  223.  
  224. /*-------------------------------------------------------------------
  225.  * Function:  Usage
  226.  * Purpose:   Print a brief message explaining how the program is run.
  227.  *            Then quit.
  228.  * In arg:    prog:  name of the executable
  229.  */
  230. void Usage(char prog[]) {
  231.     fprintf(stderr, "usage: %s <n>\n", prog);
  232.     fprintf(stderr, "   n = max integer to test for primality\n");
  233.     exit(0);
  234. } /* Usage */
  235.  
  236. /*-------------------------------------------------------------------
  237.  * Function:    Get_n
  238.  * Purpose:     Get the input value n
  239.  * Input args:  argc:  number of command line args
  240.  *              argv:  array of command line args
  241.  */
  242. int Get_n(int argc, char* argv[]) {
  243.     int n;
  244.  
  245.     if (argc != 2)
  246.         Usage(argv[0]);
  247.  
  248.     /* Convert string to int */
  249.     n = strtol(argv[1], NULL, 10);
  250.  
  251.     return n;
  252. } /* Get_n */
  253.  
  254. /*------------------------------------------------------------------
  255.  * Function:    Smallest_power_two
  256.  * Purpose:     Find the largest power of two smaller than an integer
  257.  * In args:     integer n
  258.  * Return:      the power of two
  259.  */
  260. int Smallest_power_two(int n) {
  261.     int power_two = 1;
  262.  
  263.     while (power_two < n)
  264.         power_two *= 2;
  265.  
  266.     return power_two;
  267. } /* Smallest_power_two */
  268.  
  269. /*------------------------------------------------------------------
  270.  * Function:    Sum
  271.  * Purpose:     Add up all elements of integer vector
  272.  * In args:     array A, size of array n
  273.  * Return:      sum
  274.  */
  275. int Sum(int A[], int n) {
  276.     int i, sum;
  277.  
  278.     for (i = 0, sum = 0; i < n; i++)
  279.         sum += A[i];
  280.  
  281.     return sum;
  282. } /* Sum */
  283.  
  284. /*------------------------------------------------------------------
  285.  * Function:    Print_vector
  286.  * Purpose:     Print a vector
  287.  * In args:     title, A, n, my_rank
  288.  */
  289. void Print_vector(char* title, int A[], int n, int my_rank) {
  290.     int i;
  291.     char buffer[10000];
  292.  
  293.     sprintf(buffer,"%d> %s ", my_rank, title);
  294.     for (i = 0; i < n; i++)
  295.         sprintf(buffer, "%s %d ",buffer, A[i]);
  296.     sprintf(buffer,"%s \n", buffer);
  297.     printf("%s", buffer);
  298. } /* Print_vector */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement