Ran `indent -linux` on src/global_operations/*.c.
[parallel_computing.git] / src / global_operations / broadcast.c
1 /* simple broadcast logic demonstrations */
2
3 /* Michel Vallieres */
4
5 #include <stdio.h>
6 #include <string.h>
7 #include <stdlib.h>
8 #include <mpi.h>
9
10 #define TAG_BCAST 123
11
12 void my_broadcast(int rank, int size, double *message);
13
14 int main(int argc, char *argv[])
15 {
16         int rank, size;
17         double message;
18
19         MPI_Init(&argc, &argv);
20         MPI_Comm_rank(MPI_COMM_WORLD, &rank);
21         MPI_Comm_size(MPI_COMM_WORLD, &size);
22
23         /* an arbitrary message */
24         message = 0.0;
25         if (rank == 0)
26                 message = 5.6789;
27
28         /* local broadcast */
29         my_broadcast(rank, size, &message);
30
31         /* check that nodes received message */
32         printf("after broadcast -- node %d -- message %f\n", rank, message);
33
34         /* end of code */
35         MPI_Finalize();
36         return EXIT_SUCCESS;
37 }
38
39 void my_broadcast(int rank, int size, double *message)
40 {
41         int level, maxlevel;
42         int shift_ip, n_target;
43         int *target_process;
44         int from_process, target;
45         MPI_Status recv_status;
46
47         /* build transmission tree */
48
49         /* size of binary tree */
50         maxlevel = 0;
51         while (1 << maxlevel + 1 < size)
52                 maxlevel++;
53         /* '<<' is a bitwise shift left, so  1 << b == pow(2, b) */
54
55         /* make space for local branch of tree */
56         target_process = (int *)malloc((unsigned)(size * sizeof(int)));
57
58         /* build the branches */
59         n_target = 0;
60         from_process = -1;
61         n_target = 0;
62         for (level = 0; level <= maxlevel; level++) {
63                 shift_ip = 1 << level;
64                 if (rank >= shift_ip)
65                         from_process = rank - shift_ip;
66                 if (rank < shift_ip) {
67                         target = rank + shift_ip;
68                         if (target < size) {
69                                 target_process[n_target] = target;
70                                 n_target++;
71                         }
72                 }
73         }
74
75         /* debugging output */
76         fprintf(stderr, "process %d -- from_process %d -- %d targets\n",
77                 rank, from_process, n_target);
78         if (n_target > 0) {
79                 for (target = 0; target < n_target; target++)
80                         fprintf(stderr, "process %d -- target %d\n",
81                                 rank, target_process[target]);
82         }
83
84         /* message transmission */
85
86         /* receive message */
87         if (rank > 0) {
88                 fprintf(stderr, "--- receiving %d %d \n", rank, from_process);
89                 fflush(stderr);
90                 MPI_Recv(message, 1, MPI_DOUBLE, from_process, TAG_BCAST,
91                          MPI_COMM_WORLD, &recv_status);
92         }
93
94         /* send message to all target processes */
95         if (n_target > 0) {
96                 fprintf(stderr, "--- sending %d %d \n", rank, n_target);
97                 for (target = 0; target < n_target; target++)
98                         MPI_Ssend(message, 1, MPI_DOUBLE,
99                                   target_process[target], TAG_BCAST,
100                                   MPI_COMM_WORLD);
101         }
102
103         /* free up space */
104         free(target_process);
105 }