-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsieve3.c
166 lines (137 loc) · 4.4 KB
/
sieve3.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
* 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' */
char *parent_primes;/* Primes to sieve */
LLong parent_size; /* Parent primes size*/
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 */
/*
We want to delete Even numbers.
So we only have (n-1)/2 elements.
*/
proc0_size = 1+(n-1)/2/p*2;
if ((proc0_size) < (long long) sqrt((double) n)) {
if (!id) printf ("Too many processes\n");
MPI_Finalize();
exit (1);
}
low_value = 3;
high_value = (long long) sqrt((double) n) - ((long long) sqrt((double) n) + 1) % 2;
parent_size = (high_value - low_value)/2 + 1;
/* Allocate parent_primes to seive */
parent_primes = (char *) malloc (parent_size);
if (parent_primes == NULL) {
printf ("Cannot allocate enough memory\n");
MPI_Finalize();
exit (1);
}
for (i = 0; i < parent_size; i++) parent_primes[i] = 0;
/*
Sequentially mark parent_primes
low_value for parent_primes is 3
high_value for parent_primes is (n-1)/2/p*2 + 1
*/
prime = 3;
index = 0;
do{
if (prime * prime > low_value)
first = ((prime * prime) - low_value) / 2;
else {
if ( (prime - (low_value) % prime) % 2 == 0) {
first = (prime - (low_value) % prime) / 2;
} else {
first = (prime * 2 - (low_value) % prime) / 2;
}
}
for (i = first; i < parent_size; i += prime) parent_primes[i] = 1;
while (parent_primes[++index]);
prime = index * 2 + 3;
} while (prime * prime <= high_value);
/* Allocate this process's share of the array. */
low_value = 3 + id*((n-1)/2)/p*2;
high_value = 1 + (id+1)*((n-1)/2)/p*2;
size = (high_value - low_value)/2 + 1;
index = 0;
prime = index * 2 + 3;
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;
do {
if (prime * prime > low_value)
first = (prime * prime - low_value) / 2;
else {
if (!(low_value % prime)) first = 0;
else {
if ( (prime - (low_value) % prime) % 2 == 0) {
first = (prime - (low_value) % prime) / 2;
} else {
first = (prime * 2 - (low_value) % prime) / 2;
}
}
}
for (i = first; i < size; i += prime) marked[i] = 1;
//find next prime to seive
while (parent_primes[++index]);
prime = index * 2 + 3;
} 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) {
global_count++;
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;
}