-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathq3-hybrid.cpp
More file actions
152 lines (125 loc) · 3.5 KB
/
Copy pathq3-hybrid.cpp
File metadata and controls
152 lines (125 loc) · 3.5 KB
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
#include <iostream>
#include <random>
#include <vector>
#include <cmath>
#include <mpi.h>
#include <omp.h>
#define R_MIN 0
#define R_MAX 1000
#define N 1000000000
#define NUM_OMP_THREADS 4
int num_threads = 1;
// Generates sample space and returns mean
std::pair<std::vector<int>, int64_t> generate_sample_space(int rank)
{
int n_per_proc = N / num_threads;
if (rank == num_threads-1) n_per_proc += N - (n_per_proc*(num_threads-1));
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> dist(R_MIN, R_MAX);
// Generate sample space.
std::vector<int> sample_space;
for (int i = 0; i < n_per_proc; ++i)
{
auto r = dist(mt);
sample_space.push_back(r);
}
int64_t sum = 0;
int i;
#pragma omp parallel for private(i) reduction(+: sum)
for (i = 0; i < n_per_proc; ++i)
{
sum += sample_space[i];
}
auto mean = sum / sample_space.size();
return {sample_space, mean};
}
int64_t find_sum_squares(std::pair<std::vector<int>, int64_t> sample_space_pair)
{
int64_t sum_squares = 0;
auto sample_space = sample_space_pair.first;
auto mean = sample_space_pair.second;
auto n_per_proc = sample_space.size();
int i;
#pragma omp parallel for private(i) reduction(+: sum_squares)
for (i = 0; i < n_per_proc; ++i)
{
sum_squares += (sample_space[i] - mean)*(sample_space[i] - mean);
}
return sum_squares;
}
void do_work(int rank)
{
auto sample_space_pair = generate_sample_space(rank);
auto sample_space = sample_space_pair.first;
auto mean = sample_space_pair.second;
// send mean back to server so it can be incorporated with other nodes' results.
MPI_Send(&mean, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
// receive new mean from server.
MPI_Recv(&mean, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
auto sum_squares = find_sum_squares({sample_space, mean});
MPI_Send(&sum_squares, 1, MPI_LONG_LONG, 0, 0, MPI_COMM_WORLD);
}
double myclock() {
static time_t t_start = 0; // Save and subtract off each time
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
if( t_start == 0 ) t_start = ts.tv_sec;
return (double) (ts.tv_sec - t_start) + ts.tv_nsec * 1.0e-9;
}
int main(int argc, char** argv)
{
int rc;
int rank;
double tstart, ttotal;
if ((rc = MPI_Init(&argc, &argv)) != MPI_SUCCESS)
{
std::cout << "error: cannot start mpi" << std::endl;
MPI_Abort(MPI_COMM_WORLD, rc);
}
MPI_Comm_size(MPI_COMM_WORLD,&num_threads);
omp_set_num_threads(NUM_OMP_THREADS);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
if (rank == 0)
{
tstart = myclock();
tstart = myclock();
int64_t sum_squares = 0;
if (num_threads > 1)
{
std::vector<int> means;
for (int i = 1; i < num_threads; ++i)
{
int mean;
MPI_Recv(&mean, 1, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
means.push_back(mean);
}
auto new_mean = std::accumulate(means.begin(), means.end(), 0LL) / means.size();
for (int i = 1; i < num_threads; ++i)
{
MPI_Send(&new_mean, 1, MPI_INT, i, 0, MPI_COMM_WORLD);
}
for (int i = 1; i < num_threads; ++i)
{
int64_t result;
MPI_Recv(&result, 1, MPI_LONG_LONG, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
sum_squares += result;
}
}
else
{
sum_squares = find_sum_squares(generate_sample_space(rank));
}
// Compute standard deviation.
auto sd = std::sqrt(sum_squares / (N-1));
ttotal = myclock() - tstart;
std::cout << "Standard deviation: " << sd << std::endl;
std::cout << "Time: " << ttotal << " seconds" << std::endl;
}
else
{
do_work(rank);
}
MPI_Finalize();
return 0;
}