forked from Ubpa/RenderLab
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParallel.h
More file actions
117 lines (100 loc) · 3.03 KB
/
Parallel.h
File metadata and controls
117 lines (100 loc) · 3.03 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
#pragma once
#include <UTemplate/FuncTraits.h>
#include <vector>
#include <thread>
#include <functional>
namespace Ubpa {
class Parallel
{
public:
static Parallel& Instance() {
static Parallel instance;
return instance;
}
const size_t & CoreNum() const { return coreNum; }
template<typename Func>
void Run(const std::vector<Func> & works);
template<typename Func, typename Data>
void Run(const Func & func, const std::vector<Data>& datas);
template<typename Func>
void Run(const Func& func, size_t n);
template<typename Func>
typename FuncTraits<Func>::Ret RunSum(const std::vector<Func>& works);
template<typename Func, typename Data>
typename FuncTraits<Func>::Ret RunSum(const Func& func, const std::vector<Data>& datas);
private:
Parallel();
const size_t coreNum;
};
//------------------------------------------
template<typename Func>
void Parallel::Run(const std::vector<Func>& works) {
std::vector<std::thread> workers;
if (works.size() <= coreNum) {
for (const auto& work : works)
workers.emplace_back(work);
}
else {
auto threadWork = [&works, workersNum = coreNum](size_t id) {
for (size_t i = id; i < works.size(); i += workersNum)
works[i]();
};
for (size_t i = 0; i < coreNum; i++)
workers.emplace_back(threadWork, i);
}
for (auto& worker : workers)
worker.join();
}
template<typename Func, typename Data>
void Parallel::Run(const Func& func, const std::vector<Data>& datas) {
std::vector<std::function<void()>> works;
works.reserve(datas.size());
for (auto& data : datas)
works.emplace_back([&]() { func(data); });
Run(works);
}
template<typename Func>
void Parallel::Run(const Func& func, size_t n) {
std::vector<size_t> indices(n);
for (size_t i = 0; i < n; i++)
indices[i] = i;
Run(func, indices);
}
template<typename Func>
typename FuncTraits<Func>::Ret Parallel::RunSum(const std::vector<Func>& works) {
using RstType = typename FuncTraits<Func>::Ret;
std::vector<RstType> rsts;
std::vector<std::thread> workers;
if (works.size() <= coreNum) {
for (size_t i = 0; i < works.size(); i++) {
rsts.push_back(static_cast<RstType>(0));
workers.emplace_back([&]() { rsts[i] = works[i](); });
}
}
else {
auto threadWork = [&works, &rsts, workersNum = coreNum](size_t id) {
for (size_t i = id; i < works.size(); i += workersNum)
rsts[id] += works[i]();
};
for (size_t i = 0; i < coreNum; i++) {
rsts.push_back(static_cast<RstType>(0));
workers.emplace_back(threadWork, i);
}
}
for (auto& worker : workers)
worker.join();
auto sum = static_cast<RstType>(0);
for (const auto& rst : rsts)
sum += rst;
return sum;
}
template<typename Func, typename Data>
typename FuncTraits<Func>::Ret Parallel::RunSum(const Func& func, const std::vector<Data>& datas) {
using RstType = typename FuncTraits<Func>::Ret;
std::vector<std::function<RstType()>> works;
works.reserve(datas.size());
for (auto& data : datas)
works.emplace_back([&]() { return func(data); });
return RunSum(works);
}
}