-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdebug-tutorial-3-fixed.c
73 lines (59 loc) · 2.64 KB
/
debug-tutorial-3-fixed.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
#include <mpi.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define items (1024*1024)
int array[items]; // Goal of the program: Summing up this array. (Instead use allocated memory in real programs!)
long sum = 0; // The result of the computation
long sum__sequential_reference_implementation() { // Non-parallel reference implementation
long s = 0;
for(int item = 0; item < items; ++item)
s += array[item];
return s;
}
int main(int argc, char** argv) {
MPI_Init(&argc, &argv);
int my_rank; // Number of the node
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
int node_count; // Total number of nodes
MPI_Comm_size(MPI_COMM_WORLD, &node_count);
// The root must load the input data to distribute to the other nodes
if(my_rank == 0) {
// In our case it generates a random array as input data
srand(time(NULL));
for(int item = 0; item < items; ++item)
array[item] = rand();
}
int items_per_rank = items / node_count;
int remainder_items = items % node_count;
int* my_work;
MPI_Alloc_mem(items_per_rank * sizeof(int), MPI_INFO_NULL, &my_work);
// MPI_Scatter is a collective operation which distributes an equal-sized part of the given array to each node.
MPI_Scatter(&array[remainder_items] /* send buffer */, items_per_rank /* send count per node */, MPI_INT /* send type */,
my_work /* receive buffer on each node */, items_per_rank /* receive count */ , MPI_INT /* receive type */,
0 /* send buffer is stored on this rank */, MPI_COMM_WORLD /* communication channel */);
// This is the actual working-loop
long sub_sum = 0;
for(int i=0; i < items_per_rank; i++)
sub_sum += my_work[i];
if(my_rank == 0) { // Scatter cannot deal with a division remainder so we manually deal with it
while(remainder_items > 0)
sub_sum += array[--remainder_items];
}
MPI_Free_mem(my_work);
// MPI_Reduce with op-code MPI_SUM is a collective operation which sums up the input sub_sum of each node
// into single a resulting output sum on the master.
MPI_Reduce(&sub_sum /* input to sum up */, &sum /* output */, 1 /* input count */, MPI_LONG /* input type */,
MPI_SUM /* operation */, 0 /* output is stored on this rank */, MPI_COMM_WORLD /* communication channel */);
if(my_rank == 0) {
// The result of the computation now is available on rank 0.
// We compare it with the sequential reference implementation to test our parallel implementation.
if(sum == sum__sequential_reference_implementation())
fprintf(stderr, "Test OK.\n");
else
fprintf(stderr, "Test FAILED!\n");
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
return EXIT_SUCCESS;
}