dune-assembler 2.12
Loading...
Searching...
No Matches
coloredrangeexecutor.hh
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
2// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
3
4#ifndef DUNE_ASSEMBLER_PARALLEL_COLOREDRANGEEXECUTOR_HH
5#define DUNE_ASSEMBLER_PARALLEL_COLOREDRANGEEXECUTOR_HH
6
7#include <algorithm>
8#include <cstddef>
9#include <vector>
10#include <thread>
11#include <atomic>
12
14
16
18
19
20
35template <class Range>
36static auto rangeSegment (Range& range, std::size_t i, std::size_t n) {
37 std::size_t length = range.size() / n;
38 std::size_t remainder = range.size() % n;
39 auto begin = length*i + std::min(remainder, i);
40 auto end = length*(i+1) + std::min(remainder, i+1);
42}
43
44
45
85template <class ColoredRange>
87{
88
89 class ThreadContext
90 {
91 std::size_t threadCount_;
92 std::size_t threadIndex_;
93 ColoredRange& coloredRange_;
96 bool useWorkStealing_;
97 std::size_t minChunkSize_ = 8;
98
99 public:
100
101 ThreadContext (std::size_t threadCount, std::size_t threadIndex, ColoredRange& coloredRange, Barrier& barrier, std::atomic<std::size_t>& counter, bool useWorkStealing)
102 : threadCount_(threadCount)
103 , threadIndex_(threadIndex)
104 , coloredRange_(coloredRange)
105 , barrier_(barrier)
106 , counter_(counter)
107 , useWorkStealing_(useWorkStealing)
108 {}
109
110 std::size_t threadIndex () const
111 {
112 return threadIndex_;
113 }
114
115 std::size_t threadCount () const
116 {
117 return threadCount_;
118 }
119
120 Barrier& barrier () const
121 {
122 return barrier_;
123 }
124
125 // For each loop over the stored colored range.
126 // Notice that the additional range argument is ignored.
127 // It is required to ensure a common interface that can
128 // also be implemented by the default constructible
129 // SequentialExecutor. Ideally, this method would check
130 // if the passed and stored range coincide and dispatch
131 // to a sequential loop otherwise.
132 template <class Range, class CallBack>
133 void forEach (Range&&, CallBack&& callBack)
134 {
135 if (threadCount()>1)
136 {
137 if (useWorkStealing_)
138 {
139 for (auto&& singleColorRange : coloredRange_)
140 {
141 if (threadIndex()==0)
142 counter_ = 0;
143 barrier_.arrive_and_wait();
144 auto size = singleColorRange.size();
145 auto chunkSize = std::size_t(size/(2*threadCount()));
146 while (true)
147 {
148 auto chunkStart = counter_.fetch_add(chunkSize, std::memory_order_relaxed);
149 if (chunkStart>=size)
150 break;
153 chunkSize = std::max(chunkSize/2, minChunkSize_);
154 }
155 barrier_.arrive_and_wait();
156 }
157 }
158 else
159 {
160 for (auto&& singleColorRange : coloredRange_)
161 {
162 for (auto&& entry : rangeSegment(singleColorRange, threadIndex_, threadCount_))
163 callBack(entry);
164 barrier_.arrive_and_wait();
165 }
166 }
167 }
168 else
169 for (auto&& singleColorRange : coloredRange_)
170 for (auto&& entry : singleColorRange)
171 callBack(entry);
172 }
173
174 };
175
176public:
177
178 static constexpr bool isParallel = true;
179
181 : coloredRange_(coloredRange)
182 , threadCount_(threadCount)
183 , useWorkStealing_(useWorkStealing)
184 {}
185
186 template <class ThreadImpl>
188 auto barrier = Barrier(threadCount_);
191 for (std::size_t i=0; i<threadCount_; ++i)
192 threads.emplace_back(threadImpl, ThreadContext(threadCount_, i, coloredRange_, barrier, counter, useWorkStealing_));
193 for (auto& thread : threads)
194 thread.join();
195 }
196
197private:
198 ColoredRange& coloredRange_;
199 std::size_t threadCount_;
200 bool useWorkStealing_;
201};
202
203
204
205
206} // end namespace Dune::Assembler::Experimental
207
208#endif // DUNE_ASSEMBLER_PARALLEL_COLOREDRANGEEXECUTOR_HH
Definition barrier.hh:11
static auto rangeSegment(Range &range, std::size_t i, std::size_t n)
Split range into uniform segments.
Definition coloredrangeexecutor.hh:36
int size() const
iterator end()
iterator begin()
static constexpr IntegralRange< T > range(T from, T to) noexcept
virtual void operator()()=0
RowIterator begin()
A barrier primitive for multi-threaded code.
Definition barrier.hh:24
void arrive_and_wait()
Definition barrier.hh:33
Utility for implementing parallel algorithms based on colored ranges.
Definition coloredrangeexecutor.hh:87
static constexpr bool isParallel
Definition coloredrangeexecutor.hh:178
ColoredRangeExecutor(ColoredRange &coloredRange, std::size_t threadCount, bool useWorkStealing=true)
Definition coloredrangeexecutor.hh:180
T fetch_add(T... args)
T max(T... args)
T min(T... args)