查找素数Eratosthenes筛法的mpi程序

  思路:

  只保留奇数

  (1)由输入的整数n确定存储奇数(不包括1)的数组大小:

       n=(n%2==0)?(n/2-1):((n-1)/2);//n为存储奇数的数组大小,不包括基数1

  (2)由数组大小n、进程号id和进程数p,确定每个进程负责的基数数组的第一个数、最后一个数和数组维度:

         low_value = 3 + 2*(id*(n)/p);//进程的第一个数

     high_value = 3 + 2*((id+1)*(n)/p-1);//进程的最后一个数

     size = (high_value - low_value)/2 + 1;  //进程处理的数组大小

  (3)寻找奇数的第一个倍数的下标,经过反复思考,有如下规律:

     if (prime * prime > low_value)

        first = (prime * prime - low_value)/2;

    else {

        if (!(low_value % prime))

                     first = 0;

        else

                     first=((prime-low_value%prime)%2==0)?((prime-low_value%prime)/2):((prime-low_value%prime+prime)/2);

    }

 

  code:

  1 #include "mpi.h"
  2 #include <math.h>
  3 #include <stdio.h>
  4 #define MIN(a,b)  ((a)<(b)?(a):(b))
  5 
  6 int main (int argc, char *argv[])
  7 {
  8    int    count;        /* Local prime count */
  9    double elapsed_time; /* Parallel execution time */
 10    int    first;        /* Index of first multiple */
 11    int    global_count; /* Global prime count */
 12    int    high_value;   /* Highest value on this proc */
 13    int    i;
 14    int    id;           /* Process ID number */
 15    int    index;        /* Index of current prime */
 16    int    low_value;    /* Lowest value on this proc */
 17    char  *marked;       /* Portion of 2,...,'n' */
 18    int    n,m;            /* Sieving from 2, ..., 'n' */
 19    int    p;            /* Number of processes */
 20    int    proc0_size;   /* Size of proc 0's subarray */
 21    int    prime;        /* Current prime */
 22    int    size;         /* Elements in 'marked' */
 23 
 24    MPI_Init (&argc, &argv);
 25 
 26    /* Start the timer */
 27 
 28    MPI_Comm_rank (MPI_COMM_WORLD, &id);
 29    MPI_Comm_size (MPI_COMM_WORLD, &p);
 30    MPI_Barrier(MPI_COMM_WORLD);
 31    elapsed_time = -MPI_Wtime();
 32 
 33    if (argc != 2) {
 34       if (!id) printf ("Command line: %s <m>\n", argv[0]);
 35       MPI_Finalize();
 36       exit (1);
 37     }
 38 
 39    n = atoi(argv[1]);
 40    m=n;//
 41    n=(n%2==0)?(n/2-1):((n-1)/2);//将输入的整数n转换为存储奇数的数组大小,不包括奇数1
 42    //if (!id) printf ("Number of odd integers:%d    Maximum value of odd integers:%d\n",n+1,3+2*(n-1));
 43    if (n==0) {//输入2时,输出1 prime,结束
 44     if (!id) printf ("There are 1 prime less than or equal to %d\n",m);
 45       MPI_Finalize();
 46       exit (1);
 47     }
 48    /* Figure out this process's share of the array, as
 49       well as the integers represented by the first and
 50       last array elements */
 51 
 52    low_value = 3 + 2*(id*(n)/p);//进程的第一个数
 53    high_value = 3 + 2*((id+1)*(n)/p-1);//进程的最后一个数
 54    size = (high_value - low_value)/2 + 1;    //进程处理的数组大小
 55 
 56 
 57    /* Bail out if all the primes used for sieving are
 58       not all held by process 0 */
 59 
 60    proc0_size = (n-1)/p;
 61 
 62    if ((3 + 2*(proc0_size-1)) < (int) sqrt((double) (3+2*(n-1)))) {//
 63       if (!id) printf ("Too many processes\n");
 64       MPI_Finalize();
 65       exit (1);
 66     }
 67 
 68    /* Allocate this process's share of the array. */
 69 
 70    marked = (char *) malloc (size);
 71 
 72    if (marked == NULL) {
 73       printf ("Cannot allocate enough memory\n");
 74       MPI_Finalize();
 75       exit (1);
 76     }
 77 
 78    for (i = 0; i < size; i++) marked[i] = 0;
 79    if (!id) index = 0;
 80    prime = 3;//从素数3开始
 81    do {
 82     //确定奇数的第一个倍数的下标
 83       if (prime * prime > low_value)
 84          first = (prime * prime - low_value)/2;
 85       else {
 86          if (!(low_value % prime)) 
 87         first = 0;
 88          else 
 89         first=((prime-low_value%prime)%2==0)?((prime-low_value%prime)/2):((prime-low_value%prime+prime)/2);
 90         }
 91 
 92       for (i = first; i < size; i += prime)  marked[i] = 1;
 93       if (!id) {
 94          while (marked[++index]);
 95          prime = 2*index + 3;//下一个未被标记的素数
 96         }
 97       if (p > 1) MPI_Bcast (&prime,  1, MPI_INT, 0, MPI_COMM_WORLD);
 98    } while (prime * prime <= 3+2*(n-1));//
 99 
100    count = 0;
101    for (i = 0; i < size; i++)
102       if (!marked[i])  count++; 
103    if (p > 1) MPI_Reduce (&count, &global_count, 1, MPI_INT, MPI_SUM,
104       0, MPI_COMM_WORLD);
105 
106    /* Stop the timer */
107 
108    elapsed_time += MPI_Wtime();
109 
110 
111    /* Print the results */
112 
113    if (!id) {
114       printf ("There are %d primes less than or equal to %d\n",
115          global_count+1, m);//前面程序是从素数3开始标记,忽略了素数2,所以素数个数要加1
116       printf ("SIEVE (%d) %10.6f\n", p, elapsed_time);
117    }
118    MPI_Finalize ();
119    return 0;
120 }

 

posted @ 2016-10-31 10:56  LC_coding  阅读(2485)  评论(1编辑  收藏  举报