-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPermuteMultiThread.cpp
More file actions
129 lines (104 loc) · 3.4 KB
/
Copy pathPermuteMultiThread.cpp
File metadata and controls
129 lines (104 loc) · 3.4 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
/*
Program to calculate all of the possible permutations of a heterogram, single-thread
*/
//https://stackoverflow.com/questions/30865231/parallel-code-for-next-permutation?noredirect=1&lq=1
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <vector>
#include <random>
#include <thread>
#include <mutex>
#include <chrono>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <fstream>
using Clock = std::chrono::high_resolution_clock;
const unsigned int N = std::thread::hardware_concurrency(); //number of threads on device
std::unordered_map<int,double> ThreadTimes; //run-times of each individual std::thread
std::vector<std::string> permutations;
std::mutex mtx;
std::vector<std::thread> threads;
//calculate factorial
unsigned long long fact(int N)
{
if (N==0 || N==1)
{
return 1;
}
unsigned long long total = 1;
for (int i=1; i<=N; i++)
{
total *= i;
}
return total;
}
/*
calculate permutations for i'th partition by rotating the first
character and then permuting the second to last ones
*/
void permute(int ThreadNumber, unsigned long long partition, std::string vprime, int index)
{
auto TimeNow = Clock::now();
std::rotate(vprime.begin(), vprime.begin() + index, vprime.begin() + index + 1);
std::vector<std::string>::iterator from;
std::vector<std::string>::iterator to;
{
std::lock_guard<std::mutex> lock(mtx); // hold the lock only while accessing shared vector, not while accessing its contents
from = permutations.begin () + index*partition;
to = from + partition;
}
for (auto i = from; i < to; ++i, std::next_permutation(vprime.begin() + 1, vprime.end()))
{
*i = vprime;
}
ThreadTimes[ThreadNumber+1] += std::chrono::duration<double, std::nano>(Clock::now() - TimeNow).count();
}
// Driver Code
int main()
{
const int factor = 11; //Don't really have this many threads though, jtlyk
std::string str;
unsigned long long int number = fact(factor);
str.reserve(factor);
permutations.resize(number);
threads.reserve(factor);
for (int i=65; i<65+factor; i++)
{
str.push_back(static_cast<char>(i));
}
// std::cout << str << '\n';
// Function call
auto start_time = Clock::now();
std::random_device rd;
std::mt19937 gen(rd());
unsigned long long partition = (number/factor);
for (unsigned int i=0; i<factor; i++)
{
threads.emplace_back(std::move(std::thread(permute, i, partition, str, i)));
}
for (auto &i: threads)
{
i.join();
}
auto end_time = Clock::now();
// std::cout << permutations.size() << '\n';
// std::cout << "Time difference = "
// << std::chrono::duration<double, std::nano>(end_time - start_time).count() << " nanoseconds\n";
double TotalTime = std::chrono::duration<double, std::nano>(end_time - start_time).count();
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::ofstream out("ThreadTimes.txt", std::ios::trunc);
out << "total," << TotalTime << '\n';
for (auto& i: ThreadTimes)
{
out << i.first << ',' << i.second << '\n';
}
out.close();
// std::unordered_set test(permutations.begin(),permutations.end());
// std::cout << test.size() << '\n';
// for (auto& i: permutations)
// {
// std::cout << i << '\n';
// }
}