-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path1c-parallel-but-in-sequence.cpp
More file actions
79 lines (69 loc) · 1.96 KB
/
1c-parallel-but-in-sequence.cpp
File metadata and controls
79 lines (69 loc) · 1.96 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
#include <mutex>
#include <condition_variable>
#include <thread>
#include <vector>
#include <iostream>
#include <functional>
template<int Remainder, int Factor>
void
incrementer(int &counter, int till, std::mutex &lock,
std::condition_variable ¬ify, std::condition_variable &wait,
int &increment_counter)
{
increment_counter = 0;
for (;;) {
std::unique_lock<std::mutex> lk(lock);
while (counter < till && counter % Factor != Remainder)
wait.wait(lk);
if (counter >= till)
break;
int next = ++counter;
lk.unlock();
increment_counter++;
if (next < till) {
notify.notify_one();
} else {
// make everyone awake and realize we've done
notify.notify_all();
wait.notify_all();
break;
}
}
}
// fsf = False Sharing Friendly - an integer counter and 60 bytes of padding
// to fill 64-byte cacheline
struct fsf_counter {
int value = 0;
int padding[15];
};
int main(int argc, char **argv)
{
if (argc != 3 || std::string_view(argv[1]) == "--help") {
std::cout << "Usage: " << argv[0] << " increment-till-this-value how-many-incrementers-of-each-type-to-use" << std::endl;
return 1;
}
int count = 0, till = std::atoi(argv[1]), ninc = std::stoi(argv[2]);
int N = ninc * 2;
std::mutex lock;
std::condition_variable group0, group1;
std::vector<std::thread> workers;
std::vector<fsf_counter> counters(N);
workers.reserve(N);
for (int i = 0; i < ninc; i++) {
workers.emplace_back([&, i]() {
incrementer<0, 2>(count, till, lock, group1, group0, counters[i * 2].value);
});
workers.emplace_back([&, i]() {
incrementer<1, 2>(count, till, lock, group0, group1, counters[i * 2 + 1].value);
});
}
for (auto &t : workers)
t.join();
std::cout << "New counter value is " << count << std::endl;
std::cout << "Actual increments performed by thread" << std::endl;
for (int i = 0; i < N; i++)
std::cout << " thread #" << i << " (group "
<< (i % 2 == 0 ? "even" : "odd") << "): "
<< counters[i].value << std::endl;
return 0;
}