-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpar.cpp
More file actions
157 lines (131 loc) · 3.97 KB
/
par.cpp
File metadata and controls
157 lines (131 loc) · 3.97 KB
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
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <thread>
#include "utimer.cpp"
using namespace std;
#define vk vector
#define pb push_back
typedef vk<int> vi;
typedef pair<int, int> pii;
typedef vk<pii> vii;
const int ARG_COUNT = 3;
const int MINN = -1e5;
const int MAXX = 1e5 + 10;
/// mt19937 random number generator
int rand_generator(int mn, int mx) {
thread_local random_device rd;
thread_local mt19937 rng(rd());
thread_local uniform_int_distribution<int> uid;
return uid(rng, decltype(uid)::param_type {mn,mx});
}
/// generate random vector
vi rand_vec(int N, int nw) {
vk<thread> threads(nw); // threads vector
vi randArr(N); // to save generated rand values for each thread
int chunk = N / nw;
// utimer *timer_rand = new utimer("Generate Rand Vec");
for (int th = 0; th < nw; th++) {
// thread (function, parameters)
threads[th] = thread([&](const int si, const int ei) {
// loop over all items
for (int i = si; i < ei; i++)
randArr[i] = rand_generator(MINN, MAXX);
},
th * chunk,
th == (nw - 1) ? N : (th + 1) * chunk);
}
for_each(threads.begin(), threads.end(), [](thread & th) {
th.join();
});
// timer_rand->~utimer();
return randArr;
}
/// print vector
void print_vec(vi &vec) {
cout << "\n";
for (auto x: vec)
cout << x << "\t";
cout << "\n\n";
}
/// make ranges for threads
vii make_ranges(int N, int nw, int nt) {
// number taks, number workers, type number - [0 - even, 1 - odd]
vi idxList;
for(int i = 0; i < N; i++)
if(i%2 == nt) idxList.pb(i);
int sz = int(idxList.size());
int chunk = sz / nw;
int mod = sz % nw;
int idx = 0;
vii retList(nw);
for(int th = 0; th < nw; th++) {
int st = idx;
int ei = idx + chunk - 1 + (mod-- > 0);
retList[th] = make_pair(idxList[st], idxList[ei]);
idx = ei + 1;
}
return retList;
}
/// Odd-Even Sort
void OddEvenSort(vi &Arr, int nw) {
//
int N = Arr.size();
vi startIndex = {0, 1}; // 0 - Even, 1 - Odd
// Even Index starts from 0, Odd Index starts from 1.
// Both will increase by 2 in each step.
vk<thread> threads(nw); // threads vector
vii ranges_even = make_ranges(N, nw, 0);
vii ranges_odd = make_ranges(N, nw, 1);
utimer *timer = new utimer("Parallel Code");
while (!is_sorted(Arr.begin(), Arr.end())) {
for (int th = 0; th < nw; th++) {
threads[th] = thread([&](const int si, const int ei) {
// loop over all items
for (int i = si; i <= ei; i += 2) {
if (Arr[i] > Arr[i + 1])
swap(Arr[i], Arr[i + 1]);
}
}, ranges_even[th].first, ranges_even[th].second);
}
for_each(threads.begin(), threads.end(), [](thread & th) {
th.join();
});
for (int th = 0; th < nw; th++) {
threads[th] = thread([&](const int si, const int ei) {
// loop over all items
for (int i = si; i <= ei; i += 2) {
if (Arr[i] > Arr[i + 1])
swap(Arr[i], Arr[i + 1]);
}
}, ranges_odd[th].first, ranges_odd[th].second);
}
for_each(threads.begin(), threads.end(), [](thread & th) {
th.join();
});
}
timer->~utimer();
}
int main(int argc, char *argv[]) {
// read inputs
if (argc != ARG_COUNT) {
cout << "Input Error. Number of argument is wrong..\n";
exit(0);
}
int N = atoi(argv[1]);
int nw = atoi(argv[2]);
// input validation
if (N < 1 || nw == 0) {
cout << "Invalid Input..\n";
exit(0);
}
// genereate random vector
vi Arr = rand_vec(N, nw);
// print_vec(Arr);
// Run OddEvenSort
OddEvenSort(Arr, nw);
// Print Sorted Vector
// print_vec(Arr);
return 0;
}