-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsieve1.c
119 lines (96 loc) · 3.03 KB
/
sieve1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
* Sieve of Eratosthenes
*
* Programmed by Michael J. Quinn
*
* Last modification: 7 September 2001
*/
#include "mpi.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define MIN(a,b) ((a)<(b)?(a):(b))
typedef long long LLong;
int main (int argc, char *argv[])
{
LLong count; /* Local prime count */
double elapsed_time; /* Parallel execution time */
LLong first; /* Index of first multiple */
LLong global_count; /* Global prime count */
LLong high_value; /* Highest value on this proc */
LLong i;
int id; /* Process ID number */
int index; /* Index of current prime */
LLong low_value; /* Lowest value on this proc */
char *marked; /* Portion of 2,...,'n' */
LLong n; /* Sieving from 2, ..., 'n' */
int p; /* Number of processes */
LLong proc0_size; /* Size of proc 0's subarray */
LLong prime; /* Current prime */
LLong size; /* Elements in 'marked' */
MPI_Init (&argc, &argv);
/* Start the timer */
MPI_Comm_rank (MPI_COMM_WORLD, &id);
MPI_Comm_size (MPI_COMM_WORLD, &p);
MPI_Barrier(MPI_COMM_WORLD);
elapsed_time = -MPI_Wtime();
if (argc != 2) {
if (!id) printf ("Command line: %s <m>\n", argv[0]);
MPI_Finalize();
exit (1);
}
n = atoll(argv[1]);
/* Figure out this process's share of the array, as
well as the integers represented by the first and
last array elements */
low_value = 2 + id*(n-1)/p;
high_value = 1 + (id+1)*(n-1)/p;
size = high_value - low_value + 1;
/* Bail out if all the primes used for sieving are
not all held by process 0 */
proc0_size = (n-1)/p;
if ((2 + proc0_size) < (long long) sqrt((double) n)) {
if (!id) printf ("Too many processes\n");
MPI_Finalize();
exit (1);
}
/* Allocate this process's share of the array. */
marked = (char *) malloc (size);
if (marked == NULL) {
printf ("Cannot allocate enough memory\n");
MPI_Finalize();
exit (1);
}
for (i = 0; i < size; i++) marked[i] = 0;
if (!id) index = 0;
prime = 2;
do {
if (prime * prime > low_value)
first = prime * prime - low_value;
else {
if (!(low_value % prime)) first = 0;
else first = prime - (low_value % prime);
}
for (i = first; i < size; i += prime) marked[i] = 1;
if (!id) {
while (marked[++index]);
prime = index + 2;
}
if (p > 1) MPI_Bcast (&prime, 1, MPI_INT, 0, MPI_COMM_WORLD);
} while (prime * prime <= n);
count = 0;
for (i = 0; i < size; i++)
if (!marked[i]) count++;
if (p > 1) MPI_Reduce (&count, &global_count, 1, MPI_LONG_LONG, MPI_SUM,
0, MPI_COMM_WORLD);
/* Stop the timer */
elapsed_time += MPI_Wtime();
/* Print the results */
if (!id) {
printf ("There are %lld primes less than or equal to %lld\n",
global_count, n);
printf ("SIEVE (%d) %10.6f\n", p, elapsed_time);
}
MPI_Finalize ();
return 0;
}