1
+ #include <mpi.h>
2
+ #include <iostream>
3
+ #include <fstream>
4
+ #include <vector>
5
+
6
+ using namespace std ;
7
+
8
+ //Read numbers from file as vector of ints
9
+ bool getNumbersFromFile (vector < int > * numbers ) {
10
+ int number ;
11
+ fstream myFile ;
12
+ myFile .open ("numbers" , ios ::in );
13
+
14
+ if (!myFile .is_open ())
15
+ {
16
+ cerr << "File could not be opened" << endl ;
17
+ return false;
18
+ }
19
+
20
+ while (myFile .good ()){
21
+ number = myFile .get ();
22
+
23
+ if (!myFile .good ())
24
+ break ;
25
+
26
+ numbers -> push_back (number );
27
+ }
28
+ myFile .close ();
29
+ return true;
30
+ }
31
+
32
+ int main (int argc , char * argv []) {
33
+ //Initializations--------------------------------------------------------------------------------
34
+ int size , rank ;
35
+ int midian = 0 ;
36
+ vector < int > numbers ;
37
+
38
+ MPI_Init (& argc , & argv );
39
+ MPI_Comm_size (MPI_COMM_WORLD , & size );
40
+ MPI_Comm_rank (MPI_COMM_WORLD , & rank );
41
+ //check if there is enough processes
42
+ if (size < 2 ) {
43
+ cerr << "Not enough processes" << endl ;
44
+ MPI_Abort (MPI_COMM_WORLD , 1 );
45
+ }
46
+ //Getting numbers and scattering--------------------------------------------------------------------------------
47
+
48
+ //rank 0 reads numbers from the file and calculates midian and size of numbers
49
+ int * numbersArray = nullptr ;
50
+ int numbersSize = 0 ;
51
+ if (rank == 0 ) {
52
+ getNumbersFromFile (& numbers );
53
+ numbersSize = numbers .size ();
54
+
55
+ //check if size of numbers is divisible by number of processes
56
+ if (numbersSize % size != 0 ) {
57
+ cerr << "Size of numbers can not be divisible by number of processes" << endl ;
58
+ MPI_Abort (MPI_COMM_WORLD , 1 );
59
+ }
60
+
61
+ //copy vector to array
62
+ numbersArray = new int [numbersSize ];
63
+ for (int i = 0 ; i < numbersSize ; i ++ ) {
64
+ numbersArray [i ] = numbers [i ];
65
+ }
66
+ //broadcast size of numbers to all processes
67
+ MPI_Bcast (& numbersSize , 1 , MPI_INT , 0 , MPI_COMM_WORLD );
68
+
69
+ //find midian
70
+ if (numbersSize % 2 == 0 ) {
71
+ midian = numbers [numbersSize / 2 - 1 ];
72
+ } else {
73
+ midian = numbers [numbersSize / 2 ];
74
+ }
75
+ //broadcast midian to all processes
76
+ MPI_Bcast (& midian , 1 , MPI_INT , 0 , MPI_COMM_WORLD );
77
+
78
+ }
79
+ //receive size of numbers from process 0
80
+ MPI_Bcast (& numbersSize , 1 , MPI_INT , 0 , MPI_COMM_WORLD );
81
+ //receive midian from process 0
82
+ MPI_Bcast (& midian , 1 , MPI_INT , 0 , MPI_COMM_WORLD );
83
+
84
+ // Allocate space for a portion of the array on each process
85
+ int localRecieveCount = numbersSize / size ;
86
+ int * localNumbersArray = new int [localRecieveCount ];
87
+ // Scatter the array to all processes
88
+ MPI_Scatter (numbersArray , localRecieveCount , MPI_INT , localNumbersArray , localRecieveCount , MPI_INT , 0 , MPI_COMM_WORLD );
89
+
90
+ //LESS--------------------------------------------------------------------------------
91
+
92
+ //get all numbers smaller than midian and add them to local array
93
+ int * localLesser = new int [localRecieveCount ];
94
+ int localLesserCount = 0 ;
95
+ for (int i = 0 ; i < localRecieveCount ; i ++ ) {
96
+ if (localNumbersArray [i ] < midian ) {
97
+ localLesser [localLesserCount ] = localNumbersArray [i ];
98
+ localLesserCount ++ ;
99
+ }
100
+ }
101
+
102
+ //Gathar size of numbers smaller than midian to process 0
103
+ int * recvCountsLesser = NULL ;
104
+ if (rank == 0 ){
105
+ recvCountsLesser = (int * ) malloc ( size * sizeof (int )) ;
106
+ }
107
+ MPI_Gather (& localLesserCount , 1 , MPI_INT ,
108
+ recvCountsLesser , 1 , MPI_INT ,
109
+ 0 , MPI_COMM_WORLD );
110
+ //Gathar all numbers smaller than midian to process 0
111
+ int totalLenLesser = 0 ;
112
+ int * displs = NULL ;
113
+ int * allLesser = NULL ;
114
+ if (rank == 0 ) {
115
+ displs = (int * ) malloc ( size * sizeof (int )) ;
116
+ displs [0 ] = 0 ;
117
+ for (int i = 1 ; i < size ; i ++ ) {
118
+ displs [i ] = displs [i - 1 ] + recvCountsLesser [i - 1 ];
119
+ }
120
+ totalLenLesser = displs [size - 1 ] + recvCountsLesser [size - 1 ];
121
+ allLesser = (int * ) malloc ( totalLenLesser * sizeof (int )) ;
122
+ }
123
+ MPI_Gatherv (localLesser , localLesserCount , MPI_INT ,
124
+ allLesser , recvCountsLesser , displs , MPI_INT ,
125
+ 0 , MPI_COMM_WORLD );
126
+
127
+
128
+ //GREAT--------------------------------------------------------------------------------
129
+ //get all numbers greater than midian and add them to local array
130
+ int * localGreater = new int [localRecieveCount ];
131
+ int localGreaterCount = 0 ;
132
+ for (int i = 0 ; i < localRecieveCount ; i ++ ) {
133
+ if (localNumbersArray [i ] > midian ) {
134
+ localGreater [localGreaterCount ] = localNumbersArray [i ];
135
+ localGreaterCount ++ ;
136
+ }
137
+ }
138
+
139
+ //Gathar size of numbers greater than midian to process 0
140
+ int * recvCountsGreater = NULL ;
141
+ if (rank == 0 ){
142
+ recvCountsGreater = (int * ) malloc ( size * sizeof (int )) ;
143
+ }
144
+ MPI_Gather (& localGreaterCount , 1 , MPI_INT ,
145
+ recvCountsGreater , 1 , MPI_INT ,
146
+ 0 , MPI_COMM_WORLD );
147
+ //Gathar all numbers greater than midian to process 0
148
+ int totalLenGreater = 0 ;
149
+ int * displsGreater = NULL ;
150
+ int * allGreater = NULL ;
151
+ if (rank == 0 ) {
152
+ displsGreater = (int * ) malloc ( size * sizeof (int )) ;
153
+ displsGreater [0 ] = 0 ;
154
+ for (int i = 1 ; i < size ; i ++ ) {
155
+ displsGreater [i ] = displsGreater [i - 1 ] + recvCountsGreater [i - 1 ];
156
+ }
157
+ totalLenGreater = displsGreater [size - 1 ] + recvCountsGreater [size - 1 ];
158
+ allGreater = (int * ) malloc ( totalLenGreater * sizeof (int )) ;
159
+ }
160
+ MPI_Gatherv (localGreater , localGreaterCount , MPI_INT ,
161
+ allGreater , recvCountsGreater , displsGreater , MPI_INT ,
162
+ 0 , MPI_COMM_WORLD );
163
+
164
+
165
+ //EQUAL--------------------------------------------------------------------------------
166
+ //gather all equal numbers than midian to process 0
167
+ int * localEqual = new int [localRecieveCount ];
168
+ int localEqualCount = 0 ;
169
+ for (int i = 0 ; i < localRecieveCount ; i ++ ) {
170
+ if (localNumbersArray [i ] == midian ) {
171
+ localEqual [localEqualCount ] = localNumbersArray [i ];
172
+ localEqualCount ++ ;
173
+ }
174
+ }
175
+
176
+ //Gathar size of numbers equal to midian to process 0
177
+ int * recvCountsEqual = NULL ;
178
+ if (rank == 0 ){
179
+ recvCountsEqual = (int * ) malloc ( size * sizeof (int )) ;
180
+ }
181
+ MPI_Gather (& localEqualCount , 1 , MPI_INT ,
182
+ recvCountsEqual , 1 , MPI_INT ,
183
+ 0 , MPI_COMM_WORLD );
184
+ //Gathar all numbers equal to midian to process 0
185
+ int totalLenEqual = 0 ;
186
+ int * displsEqual = NULL ;
187
+ int * allEqual = NULL ;
188
+ if (rank == 0 ) {
189
+ displsEqual = (int * ) malloc ( size * sizeof (int )) ;
190
+ displsEqual [0 ] = 0 ;
191
+ for (int i = 1 ; i < size ; i ++ ) {
192
+ displsEqual [i ] = displsEqual [i - 1 ] + recvCountsEqual [i - 1 ];
193
+ }
194
+ totalLenEqual = displsEqual [size - 1 ] + recvCountsEqual [size - 1 ];
195
+ allEqual = (int * ) malloc ( totalLenEqual * sizeof (int )) ;
196
+ }
197
+ MPI_Gatherv (localEqual , localEqualCount , MPI_INT ,
198
+ allEqual , recvCountsEqual , displsEqual , MPI_INT ,
199
+ 0 , MPI_COMM_WORLD );
200
+
201
+
202
+ //print all Lesser than midian
203
+ if (rank == 0 ) {
204
+ cout << "L: " ;
205
+ for (int i = 0 ; i < totalLenLesser ; i ++ ) {
206
+ cout << allLesser [i ] << " " ;
207
+ }
208
+ cout << endl ;
209
+ }
210
+
211
+ //print all Equal to midian
212
+ if (rank == 0 ) {
213
+ cout << "E: " ;
214
+ for (int i = 0 ; i < totalLenEqual ; i ++ ) {
215
+ cout << allEqual [i ] << " " ;
216
+ }
217
+ cout << endl ;
218
+ }
219
+
220
+ //print all Greater than midian
221
+ if (rank == 0 ) {
222
+ cout << "G: " ;
223
+ for (int i = 0 ; i < totalLenGreater ; i ++ ) {
224
+ cout << allGreater [i ] << " " ;
225
+ }
226
+ cout << endl ;
227
+ }
228
+
229
+ // Clean up memory
230
+ delete [] numbersArray ;
231
+ delete [] localNumbersArray ;
232
+ delete [] localLesser ;
233
+ delete [] localGreater ;
234
+ delete [] localEqual ;
235
+ // End
236
+ MPI_Finalize ();
237
+ return 0 ;
238
+ }
0 commit comments