61 const int maxNumThreads = std::thread::hardware_concurrency();
62 std::size_t nWorkers = maxNumThreads > 1 ? maxNumThreads - 1 : 0;
64 _threadTaskReady.resize(nWorkers, 0);
65 _tasks.resize(nWorkers + 1);
67 for(std::size_t threadIdx = 0; threadIdx < nWorkers; ++threadIdx) {
68 _workerThreads.emplace_back([threadIdx,
this] {
71 std::unique_lock<std::mutex> lock(_taskMutex);
72 _condition.wait(lock, [threadIdx,
this] {
73 return _bStop || _threadTaskReady[threadIdx] == 1;
75 if(_bStop && !_threadTaskReady[threadIdx])
return;
82 _threadTaskReady[threadIdx] = 0;
85 _numBusyThreads.fetch_add(-1);
93 std::unique_lock<std::mutex> lock(_taskMutex);
97 _condition.notify_all();
98 for(std::thread& worker: _workerThreads) worker.join();
101 void parallel_for(std::size_t size, std::function<
void(std::size_t)>&& func) {
102 const auto nWorkers = _workerThreads.size();
104 _numBusyThreads = int(nWorkers);
106 const std::size_t chunkSize = std::size_t(Magnum::Math::ceil(
float(size)/
float(nWorkers + 1)));
107 for(std::size_t threadIdx = 0; threadIdx < nWorkers + 1; ++threadIdx) {
108 const std::size_t chunkStart = threadIdx * chunkSize;
109 const std::size_t chunkEnd = Magnum::Math::min(chunkStart + chunkSize, size);
112 _tasks[threadIdx] = [chunkStart, chunkEnd,
task = func] {
113 for(uint64_t idx = chunkStart; idx < chunkEnd; ++idx) {
121 std::unique_lock<std::mutex> lock(_taskMutex);
122 for(std::size_t threadIdx = 0; threadIdx < _threadTaskReady.size(); ++threadIdx)
123 _threadTaskReady[threadIdx] = 1;
125 _condition.notify_all();
131 while(_numBusyThreads.load() > 0) {}
133 }
else for(std::size_t idx = 0; idx < size; ++idx)
137 static ThreadPool& getUniqueInstance() {
138 static ThreadPool threadPool;
142 static int hardwareThreadSize() {
143 return std::thread::hardware_concurrency();
147 return getUniqueInstance()._workerThreads.size();
151 std::atomic<int> _numBusyThreads{0};
153 std::vector<int> _threadTaskReady;
154 std::vector<std::thread> _workerThreads;
156 std::vector<std::function<void()>> _tasks;
157 std::mutex _taskMutex;
158 std::condition_variable _condition;