-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsieve2.c
132 lines (107 loc) · 3.37 KB
/
sieve2.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
/*
* 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 */
/*
We want to delete Even numbers.
So we only have (n-1)/2 elements.
*/
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;
/* Bail out if all the primes used for sieving are
not all held by process 0 */
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);
}
/* 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 = 3;
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;
if (!id) {
while (marked[++index]);
prime = index * 2 + 3;
}
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) {
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;
}