-
Notifications
You must be signed in to change notification settings - Fork 0
/
lab3_validate.c
196 lines (179 loc) · 6.36 KB
/
lab3_validate.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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <math.h>
// Synopsis
// int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag,
// MPI_Comm comm)
// Input Parameters
// buf
// initial address of send buffer (choice)
// count
// number of elements in send buffer (nonnegative integer)
// datatype
// datatype of each send buffer element (handle)
// dest
// rank of destination (integer)
// tag
// message tag (integer)
// comm
// communicator (handle)
// Synopsis
//
// int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag,
// MPI_Comm comm, MPI_Status *status)
// Output Parameters
//
// buf
// initial address of receive buffer (choice)
// status
// status object (Status)
// Input Parameters
//
// count
// maximum number of elements in receive buffer (integer)
// datatype
// datatype of each receive buffer element (handle)
// source
// rank of source (integer)
// tag
// message tag (integer)
// comm
// communicator (handle)
#define VECSIZE 8
//#define ITERATIONS 10000
#define ITERATIONS 1
typedef struct nodeElement {
double val;
int rank;
} NodeElement;
// Broadcast vector to all nodes
void broadcast(int numdim, int rank, NodeElement * vector, int vectorSize, MPI_Datatype datatype) {
MPI_Status status;
int notparticipating = pow(2,numdim-1)-1;
int bitmask = pow(2,numdim-1);
int curdim = 0;
for(curdim = 0; curdim < numdim; curdim++) {
if ((rank & notparticipating) == 0) {
if ((rank & bitmask) == 0) {
int msg_dest = rank ^ bitmask;
MPI_Send(vector, vectorSize, datatype, msg_dest, 0, MPI_COMM_WORLD);
}
else {
int msg_src = rank ^ bitmask;
MPI_Recv(vector, vectorSize, datatype, msg_src, 0, MPI_COMM_WORLD, &status);
}
}
notparticipating >>= 1;
bitmask >>=1;
}
}
// Reduce values to one node
void maxReduce(int numdim, int rank, NodeElement * vector, int vectorSize, MPI_Datatype datatype)
{
MPI_Status status;
int notparticipating = 0;
int curdim = 0;
int bitmask = 1;
// allocate a new array to hold received values
NodeElement * newValues = malloc(vectorSize * sizeof(NodeElement));
for(curdim = 0; curdim < numdim; curdim++) {
if ((rank & notparticipating) == 0) {
if ((rank & bitmask) != 0) {
int msg_dest = rank ^ bitmask;
MPI_Send(vector, vectorSize, datatype, msg_dest, 0, MPI_COMM_WORLD);
}
else {
int msg_src = rank ^ bitmask;
MPI_Recv(newValues, vectorSize, datatype, msg_src, 0, MPI_COMM_WORLD, &status);
int i;
for (i = 0; i < vectorSize; i++) {
if ((*(newValues + i)).val > (*(vector + i)).val) {
*(vector + i) = *(newValues + i);
}
}
}
}
notparticipating = notparticipating ^ bitmask;
bitmask <<=1;
}
}
double When() {
struct timeval tp;
gettimeofday(&tp, NULL);
return ((double) tp.tv_sec + (double) tp.tv_usec * 1e-6);
}
main(int argc, char *argv[]) {
int iproc, nproc,i, iter;
char host[255], message[55];
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nproc);
MPI_Comm_rank(MPI_COMM_WORLD, &iproc);
gethostname(host,253);
printf("I am proc %d of %d running on %s\n", iproc, nproc,host);
// each process has an array of VECSIZE double: ain[VECSIZE]
double ain[VECSIZE], aout[VECSIZE];
int ind[VECSIZE];
NodeElement in[VECSIZE], out[VECSIZE];
int myrank, root = 0;
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
// Start time here
srand(myrank+5);
double start = When();
for(iter = 0; iter < ITERATIONS; iter++) {
for(i = 0; i < VECSIZE; i++) {
ain[i] = rand();
printf("init proc %d [%d]=%f\n",myrank,i,ain[i]);
}
for (i=0; i<VECSIZE; ++i) {
in[i].val = ain[i];
in[i].rank = myrank;
}
NodeElement inCopy[VECSIZE], outCopy[VECSIZE];
memcpy(inCopy, in, sizeof(NodeElement) * VECSIZE);
memcpy(outCopy, out, sizeof(NodeElement) * VECSIZE);
printf("starting max reduce.\n");
maxReduce(3, myrank, in, VECSIZE, MPI_DOUBLE_INT);
memcpy(out, in, sizeof(NodeElement) * VECSIZE);
// MPI_Reduce( in, out, VECSIZE, MPI_DOUBLE_INT, MPI_MAXLOC, root, MPI_COMM_WORLD);
// At this point, the answer resides on process root
if (myrank == root) {
/* read ranks out
*/
for (i=0; i<VECSIZE; ++i) {
printf("root out[%d] = %f from %d\n",i,out[i].val,out[i].rank);
aout[i] = out[i].val;
ind[i] = out[i].rank;
}
}
// Now broadcast this max vector to everyone else.
printf("Starting broadcast.\n");
broadcast(3, myrank, in, VECSIZE, MPI_DOUBLE_INT);
memcpy(out, in, sizeof(NodeElement) * VECSIZE);
// MPI_Bcast(out, VECSIZE, MPI_DOUBLE_INT, root, MPI_COMM_WORLD);
for(i = 0; i < VECSIZE; i++) {
printf("final proc %d [%d]=%f from %d\n",myrank,i,out[i].val,out[i].rank);
}
MPI_Reduce(inCopy, outCopy, VECSIZE, MPI_DOUBLE_INT, MPI_MAXLOC, root, MPI_COMM_WORLD);
//check to make sure that the answer matches the copy given by the root process
if (myrank == root) {
for (i = 0; i < VECSIZE; i++) {
if (outCopy[i].val == out[i].val && outCopy[i].rank == out[i].rank) printf("Good\n");
else printf("ERROR: process %d, outcopy[%d].val = %f, out[%d].val=%f, outCopy[%d].rank = %d, out[%d].rank = %d\n", myrank, i, outCopy[i].val, i, out[i].val, i, outCopy[i].rank, i, out[i].rank);
}
}
// do the vector broadcast of the reduced vector
MPI_Bcast(outCopy, VECSIZE, MPI_DOUBLE_INT, root, MPI_COMM_WORLD);
// ccheck to make sure the received vector matches
for (i = 0; i < VECSIZE; i++) {
if (outCopy[i].val == out[i].val) printf("Good\n");
else printf("ERROR: process %d, outcopy[%d].val = %f, out[%d].val = %f\n", myrank, i, outCopy[i].val, i, out[i].val);
}
}
MPI_Finalize();
double end = When();
if(myrank == root) {
printf("Time %f\n",end-start);
}
}