-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmerge-splitting.cpp
188 lines (157 loc) · 5.34 KB
/
merge-splitting.cpp
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
/* PRL 2018 - Projekt 2 - Merge-splitting sort
* Autor: Marian Orszagh (xorsza00)
*
*/
#include <mpi.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <limits>
#include <iomanip>
using namespace std;
#define PLACEHOLDER numeric_limits<int>::max();
// Ak je zadefinovana, normalny vystup je potlaceny a na vystup je vypisany
// cas behu
// #define TIME true
void print_vec(vector<int> input, int size) {
for (int i=0; i<size; i++) {
cout << input[i] << endl;
}
}
/* Nacitanie suboru masterom (id 0) a distribucia hodnot medzi ostatne.
*/
vector<int> load_file(int ratio, int proc_count) {
vector<int> input_vec(ratio);
vector<int> master_vec(ratio);
fstream f;
f.open("numbers", ios::in);
for (int pid = 0; pid < proc_count; pid++){
for (int i=0; i<ratio; i++) {
if (!f.eof()) {
input_vec[i] = f.get();
if (input_vec[i] == EOF) {
input_vec.at(i) = PLACEHOLDER;
continue;
}
else {
// Vypis vsetkych cisel podla zadania
#ifndef TIME
cout << input_vec[i] << " ";
#endif
}
}
// V pripade, ze sme precitali vsetky cisla, do zvysnych slotov
// v procesoroch vlozime maximalny mozny integer ako
// placeholder
else {
input_vec.at(i) = PLACEHOLDER;
}
}
// Procesor 0 neposle svoju cast, ale rovno si ju uchova
// Je to zabrana proti situacii, kedy sa MPI buffer zahlti pri send/
// receive operacii.
if (pid == 0) {
master_vec = input_vec;
}
else MPI_Send(&input_vec[0], ratio, MPI_INT, pid, 0, MPI_COMM_WORLD);
}
f.close();
#ifndef TIME
cout << endl;
#endif
return master_vec;
}
/* Procesor odosle pravemu susedovi svoj vektor a caka na mensiu cast spojenej
* zoradenej postupnosti
*/
void send_and_wait(vector<int> &mynumbers, int ratio, int pid) {
MPI_Status status;
MPI_Send(&mynumbers[0], ratio, MPI_INT, pid+1, 0, MPI_COMM_WORLD);
MPI_Recv(&mynumbers[0], ratio, MPI_INT, pid+1, 0, MPI_COMM_WORLD,
&status);
}
/* Procesor prijme od svojeho laveho suseda jeho vektor, spoji ho so svojim,
* zoradi ich a susedovi posle mensiu polovicu.
*/
void sort_and_return(vector<int> &mynumbers, vector<int> &sort_v, int ratio,
int pid) {
MPI_Status status;
MPI_Recv(&sort_v[0], ratio, MPI_INT, pid-1, 0, MPI_COMM_WORLD, &status);
// Poskladam obe vektory
sort_v.insert(sort_v.end(), mynumbers.begin(), mynumbers.end());
// Zoradenie
sort(sort_v.begin(), sort_v.end());
// Druhu polovicu da procesor sebe, prvu posle dolava
copy(sort_v.begin() + ratio, sort_v.end(), mynumbers.begin());
MPI_Send(&sort_v[0], ratio, MPI_INT, pid-1, 0, MPI_COMM_WORLD);
}
int main(int argc, char *argv[])
{
// Init
int numb_count = stoi(argv[1]);
int proc_count;
int pid;
double start, finish;
MPI_Status stat;
//MPI init
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &proc_count);
MPI_Comm_rank(MPI_COMM_WORLD, &pid);
// Kolko cisel pripada jednemu procesoru
int ratio = 1 + ((numb_count - 1) / proc_count);
vector<int> mynumbers(ratio);
#ifdef TIME
if (!pid) start=MPI_Wtime();
#endif
// Master nacita a rozdistribuuje hodnoty
if (!pid) mynumbers = load_file(ratio, proc_count);
// cout<<pid<<":";
// print_vec(mynumbers, mynumbers.size());
// Kazdy procesor si nacita svoju cast cisel a predspracuje ju
if (pid) MPI_Recv(&mynumbers[0], ratio, MPI_INT, 0, 0, MPI_COMM_WORLD, &stat);
sort(mynumbers.begin(), mynumbers.end());
for(int i=1; i<= 1 + ((proc_count - 1) / 2); i++) {
vector<int> sort_v(ratio);
// Parne okrem posledneho, ak je parny poslu svoj vektor doprava
if (!(pid%2) && (pid != (proc_count-1))){
send_and_wait(mynumbers, ratio, pid);
}
// Neparne prijmu, zoradia a poslu mensiu polovicu naspat dolava
else if (pid%2) {
sort_and_return(mynumbers, sort_v, ratio, pid);
}
sort_v.resize(ratio);
// To iste, akurat sa vymeni pozicia parnych a neparnych procesorov
if((pid%2) && (pid != (proc_count-1))){
send_and_wait(mynumbers, ratio, pid);
}
else if(!(pid%2) && (pid != 0)){
sort_and_return(mynumbers, sort_v, ratio, pid);
}
}
// cout<<pid<<":";
// print_vec(mynumbers, mynumbers.size());
// Master si doalokuje pamat a postupne prijima hodnoty od ostatnych
// procesorov
if(pid == 0) mynumbers.resize(proc_count * ratio);
for(int i=1; i<proc_count; i++){
if(pid == i) MPI_Send(&mynumbers[0], ratio, MPI_INT, 0, 0,
MPI_COMM_WORLD);
if(pid == 0){
MPI_Recv(&mynumbers[i*ratio], ratio, MPI_INT, i, 0,
MPI_COMM_WORLD, &stat);
}
}
// Vysledok
if(pid == 0) {
#ifndef TIME
print_vec(mynumbers, numb_count);
#else
finish=MPI_Wtime();
cout<<std::setprecision(40)<<(finish-start)<<endl;
#endif
}
MPI_Finalize();
return 0;
}