Skip to content

Commit 00c451f

Browse files
authored
Full implementation of parsplit
0 parents  commit 00c451f

File tree

1 file changed

+238
-0
lines changed

1 file changed

+238
-0
lines changed

parsplit.c

+238
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
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

Comments
 (0)