VTK  9.5.20251207
vtkSMPTools.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2// SPDX-License-Identifier: BSD-3-Clause
23
24#ifndef vtkSMPTools_h
25#define vtkSMPTools_h
26
27#include "vtkCommonCoreModule.h" // For export macro
28#include "vtkObject.h"
29
31#include "vtkSMPThreadLocal.h" // For Initialized
32
33#include <functional> // For std::function
34#include <type_traits> // For std:::enable_if
35
36#ifndef DOXYGEN_SHOULD_SKIP_THIS
37namespace vtk
38{
39namespace detail
40{
41namespace smp
42{
43VTK_ABI_NAMESPACE_BEGIN
44template <typename T>
45class vtkSMPTools_Has_Initialize
46{
47 typedef char (&no_type)[1];
48 typedef char (&yes_type)[2];
49 template <typename U, void (U::*)()>
50 struct V
51 {
52 };
53 template <typename U>
54 static yes_type check(V<U, &U::Initialize>*);
55 template <typename U>
56 static no_type check(...);
57
58public:
59 static bool const value = sizeof(check<T>(nullptr)) == sizeof(yes_type);
60};
61
62template <typename T>
63class vtkSMPTools_Has_Initialize_const
64{
65 typedef char (&no_type)[1];
66 typedef char (&yes_type)[2];
67 template <typename U, void (U::*)() const>
68 struct V
69 {
70 };
71 template <typename U>
72 static yes_type check(V<U, &U::Initialize>*);
73 template <typename U>
74 static no_type check(...);
75
76public:
77 static bool const value = sizeof(check<T>(0)) == sizeof(yes_type);
78};
79
80template <typename Functor, bool Init>
81struct vtkSMPTools_FunctorInternal;
82
83template <typename Functor>
84struct vtkSMPTools_FunctorInternal<Functor, false>
85{
86 Functor& F;
87 vtkSMPTools_FunctorInternal(Functor& f)
88 : F(f)
89 {
90 }
91 void Execute(vtkIdType first, vtkIdType last) { this->F(first, last); }
92 void For(vtkIdType first, vtkIdType last, vtkIdType grain)
93 {
94 auto& SMPToolsAPI = vtkSMPToolsAPI::GetInstance();
95 SMPToolsAPI.For(first, last, grain, *this);
96 }
97 vtkSMPTools_FunctorInternal<Functor, false>& operator=(
98 const vtkSMPTools_FunctorInternal<Functor, false>&);
99 vtkSMPTools_FunctorInternal(const vtkSMPTools_FunctorInternal<Functor, false>&);
100};
101
102template <typename Functor>
103struct vtkSMPTools_FunctorInternal<Functor, true>
104{
105 Functor& F;
106 vtkSMPThreadLocal<unsigned char> Initialized;
107 vtkSMPTools_FunctorInternal(Functor& f)
108 : F(f)
109 , Initialized(0)
110 {
111 }
112 void Execute(vtkIdType first, vtkIdType last)
113 {
114 unsigned char& inited = this->Initialized.Local();
115 if (!inited)
116 {
117 this->F.Initialize();
118 inited = 1;
119 }
120 this->F(first, last);
121 }
122 void For(vtkIdType first, vtkIdType last, vtkIdType grain)
123 {
124 auto& SMPToolsAPI = vtkSMPToolsAPI::GetInstance();
125 SMPToolsAPI.For(first, last, grain, *this);
126 this->F.Reduce();
127 }
128 vtkSMPTools_FunctorInternal<Functor, true>& operator=(
129 const vtkSMPTools_FunctorInternal<Functor, true>&);
130 vtkSMPTools_FunctorInternal(const vtkSMPTools_FunctorInternal<Functor, true>&);
131};
132
133template <typename Functor>
134class vtkSMPTools_Lookup_For
135{
136 static bool const init = vtkSMPTools_Has_Initialize<Functor>::value;
137
138public:
139 typedef vtkSMPTools_FunctorInternal<Functor, init> type;
140};
141
142template <typename Functor>
143class vtkSMPTools_Lookup_For<Functor const>
144{
145 static bool const init = vtkSMPTools_Has_Initialize_const<Functor>::value;
146
147public:
148 typedef vtkSMPTools_FunctorInternal<Functor const, init> type;
149};
150
151template <typename Iterator, typename Functor, bool Init>
152struct vtkSMPTools_RangeFunctor;
153
154template <typename Iterator, typename Functor>
155struct vtkSMPTools_RangeFunctor<Iterator, Functor, false>
156{
157 Functor& F;
158 Iterator& Begin;
159 vtkSMPTools_RangeFunctor(Iterator& begin, Functor& f)
160 : F(f)
161 , Begin(begin)
162 {
163 }
164 void operator()(vtkIdType first, vtkIdType last)
165 {
166 Iterator itFirst(Begin);
167 std::advance(itFirst, first);
168 Iterator itLast(itFirst);
169 std::advance(itLast, last - first);
170 this->F(itFirst, itLast);
171 }
172};
173
174template <typename Iterator, typename Functor>
175struct vtkSMPTools_RangeFunctor<Iterator, Functor, true>
176{
177 Functor& F;
178 Iterator& Begin;
179 vtkSMPTools_RangeFunctor(Iterator& begin, Functor& f)
180 : F(f)
181 , Begin(begin)
182 {
183 }
184 void Initialize() { this->F.Initialize(); }
185 void operator()(vtkIdType first, vtkIdType last)
186 {
187 Iterator itFirst(Begin);
188 std::advance(itFirst, first);
189 Iterator itLast(itFirst);
190 std::advance(itLast, last - first);
191 this->F(itFirst, itLast);
192 }
193 void Reduce() { this->F.Reduce(); }
194};
195
196template <typename Iterator, typename Functor>
197class vtkSMPTools_Lookup_RangeFor
198{
199 static bool const init = vtkSMPTools_Has_Initialize<Functor>::value;
200
201public:
202 typedef vtkSMPTools_RangeFunctor<Iterator, Functor, init> type;
203};
204
205template <typename Iterator, typename Functor>
206class vtkSMPTools_Lookup_RangeFor<Iterator, Functor const>
207{
208 static bool const init = vtkSMPTools_Has_Initialize_const<Functor>::value;
209
210public:
211 typedef vtkSMPTools_RangeFunctor<Iterator, Functor const, init> type;
212};
213
214template <typename T>
215using resolvedNotInt = typename std::enable_if<!std::is_integral<T>::value, void>::type;
216VTK_ABI_NAMESPACE_END
217} // namespace smp
218} // namespace detail
219} // namespace vtk
220#endif // DOXYGEN_SHOULD_SKIP_THIS
221
222VTK_ABI_NAMESPACE_BEGIN
223class VTKCOMMONCORE_EXPORT vtkSMPTools
224{
225public:
227
236 template <typename Functor>
237 static void For(vtkIdType first, vtkIdType last, vtkIdType grain, Functor& f)
238 {
239 typename vtk::detail::smp::vtkSMPTools_Lookup_For<Functor>::type fi(f);
240 fi.For(first, last, grain);
241 }
242
243 template <typename Functor>
244 static void For(vtkIdType first, vtkIdType last, vtkIdType grain, Functor const& f)
245 {
246 typename vtk::detail::smp::vtkSMPTools_Lookup_For<Functor const>::type fi(f);
247 fi.For(first, last, grain);
248 }
249
250
252
261 template <typename Functor>
262 static void For(vtkIdType first, vtkIdType last, Functor& f)
263 {
264 vtkSMPTools::For(first, last, 0, f);
265 }
266
267 template <typename Functor>
268 static void For(vtkIdType first, vtkIdType last, Functor const& f)
269 {
270 vtkSMPTools::For(first, last, 0, f);
271 }
272
273
275
310 template <typename Iter, typename Functor>
311 static vtk::detail::smp::resolvedNotInt<Iter> For(
312 Iter begin, Iter end, vtkIdType grain, Functor& f)
313 {
314 vtkIdType size = std::distance(begin, end);
315 typename vtk::detail::smp::vtkSMPTools_Lookup_RangeFor<Iter, Functor>::type fi(begin, f);
316 vtkSMPTools::For(0, size, grain, fi);
317 }
318
319 template <typename Iter, typename Functor>
320 static vtk::detail::smp::resolvedNotInt<Iter> For(
321 Iter begin, Iter end, vtkIdType grain, Functor const& f)
322 {
323 vtkIdType size = std::distance(begin, end);
324 typename vtk::detail::smp::vtkSMPTools_Lookup_RangeFor<Iter, Functor const>::type fi(begin, f);
325 vtkSMPTools::For(0, size, grain, fi);
326 }
327
328
330
363 template <typename Iter, typename Functor>
364 static vtk::detail::smp::resolvedNotInt<Iter> For(Iter begin, Iter end, Functor& f)
365 {
366 vtkSMPTools::For(begin, end, 0, f);
367 }
368
369 template <typename Iter, typename Functor>
370 static vtk::detail::smp::resolvedNotInt<Iter> For(Iter begin, Iter end, Functor const& f)
371 {
372 vtkSMPTools::For(begin, end, 0, f);
373 }
374
375
379 static const char* GetBackend();
380
392 static bool SetBackend(const char* backend);
393
409 static void Initialize(int numThreads = 0);
410
418
426
438 static void SetNestedParallelism(bool isNested);
439
444 static bool GetNestedParallelism();
445
449 static bool IsParallelScope();
450
455 static bool GetSingleThread();
456
464 struct Config
465 {
468 bool NestedParallelism = false;
469
470 Config() = default;
471 Config(int maxNumberOfThreads)
472 : MaxNumberOfThreads(maxNumberOfThreads)
473 {
474 }
475 Config(std::string backend)
476 : Backend(backend)
477 {
478 }
479 Config(bool nestedParallelism)
480 : NestedParallelism(nestedParallelism)
481 {
482 }
483 Config(int maxNumberOfThreads, std::string backend, bool nestedParallelism)
484 : MaxNumberOfThreads(maxNumberOfThreads)
485 , Backend(backend)
486 , NestedParallelism(nestedParallelism)
487 {
488 }
489#ifndef DOXYGEN_SHOULD_SKIP_THIS
491 : MaxNumberOfThreads(API.GetInternalDesiredNumberOfThread())
492 , Backend(API.GetBackend())
493 , NestedParallelism(API.GetNestedParallelism())
494 {
495 }
496#endif // DOXYGEN_SHOULD_SKIP_THIS
497 };
498
521 static constexpr vtkIdType THRESHOLD = 100000;
522
534 template <typename T>
535 static void LocalScope(Config const& config, T&& lambda)
536 {
538 SMPToolsAPI.LocalScope<vtkSMPTools::Config>(config, lambda);
539 }
540
556 template <typename InputIt, typename OutputIt, typename Functor>
557 static void Transform(InputIt inBegin, InputIt inEnd, OutputIt outBegin, Functor transform)
558 {
560 SMPToolsAPI.Transform(inBegin, inEnd, outBegin, transform);
561 }
562
579 template <typename InputIt1, typename InputIt2, typename OutputIt, typename Functor>
580 static void Transform(
581 InputIt1 inBegin1, InputIt1 inEnd, InputIt2 inBegin2, OutputIt outBegin, Functor transform)
582 {
584 SMPToolsAPI.Transform(inBegin1, inEnd, inBegin2, outBegin, transform);
585 }
586
601 template <typename Iterator, typename T>
602 static void Fill(Iterator begin, Iterator end, const T& value)
603 {
605 SMPToolsAPI.Fill(begin, end, value);
606 }
607
613 template <typename RandomAccessIterator>
614 static void Sort(RandomAccessIterator begin, RandomAccessIterator end)
615 {
617 SMPToolsAPI.Sort(begin, end);
618 }
619
626 template <typename RandomAccessIterator, typename Compare>
627 static void Sort(RandomAccessIterator begin, RandomAccessIterator end, Compare comp)
628 {
630 SMPToolsAPI.Sort(begin, end, comp);
631 }
632};
633
634VTK_ABI_NAMESPACE_END
635#endif
636// VTK-HeaderTest-Exclude: vtkSMPTools.h
T & Local()
This needs to be called mainly within a threaded execution path.
A set of parallel (multi-threaded) utility functions.
static void Transform(InputIt1 inBegin1, InputIt1 inEnd, InputIt2 inBegin2, OutputIt outBegin, Functor transform)
A convenience method for transforming data.
static bool GetSingleThread()
Returns true if the given thread is specified thread for single scope.
static vtk::detail::smp::resolvedNotInt< Iter > For(Iter begin, Iter end, Functor const &f)
Execute a for operation in parallel.
static void Initialize(int numThreads=0)
/!
static bool SetBackend(const char *backend)
/!
static bool IsParallelScope()
Return true if it is called from a parallel scope.
static void Transform(InputIt inBegin, InputIt inEnd, OutputIt outBegin, Functor transform)
A convenience method for transforming data.
static int GetEstimatedNumberOfThreads()
Get the estimated number of threads being used by the backend.
static vtk::detail::smp::resolvedNotInt< Iter > For(Iter begin, Iter end, Functor &f)
Execute a for operation in parallel.
static void SetNestedParallelism(bool isNested)
/!
static vtk::detail::smp::resolvedNotInt< Iter > For(Iter begin, Iter end, vtkIdType grain, Functor &f)
Execute a for operation in parallel.
static void Sort(RandomAccessIterator begin, RandomAccessIterator end)
A convenience method for sorting data.
static void Fill(Iterator begin, Iterator end, const T &value)
A convenience method for filling data.
static void For(vtkIdType first, vtkIdType last, Functor const &f)
Execute a for operation in parallel.
static void For(vtkIdType first, vtkIdType last, Functor &f)
Execute a for operation in parallel.
static vtk::detail::smp::resolvedNotInt< Iter > For(Iter begin, Iter end, vtkIdType grain, Functor const &f)
Execute a for operation in parallel.
static void For(vtkIdType first, vtkIdType last, vtkIdType grain, Functor const &f)
Execute a for operation in parallel.
static void Sort(RandomAccessIterator begin, RandomAccessIterator end, Compare comp)
A convenience method for sorting data.
static bool GetNestedParallelism()
Get true if the nested parallelism is enabled.
static void LocalScope(Config const &config, T &&lambda)
/!
static const char * GetBackend()
Get the backend in use.
static constexpr vtkIdType THRESHOLD
This is an empirically determined threshold used by various cases to switch between serial and thread...
static void For(vtkIdType first, vtkIdType last, vtkIdType grain, Functor &f)
Execute a for operation in parallel.
static int GetEstimatedDefaultNumberOfThreads()
Get the estimated number of threads being used by the backend by default.
static vtkSMPToolsAPI & GetInstance()
@ value
Definition vtkX3D.h:221
@ type
Definition vtkX3D.h:517
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
Structure used to specify configuration for LocalScope() method.
Config(std::string backend)
Config(int maxNumberOfThreads)
std::string Backend
Config(bool nestedParallelism)
Config(int maxNumberOfThreads, std::string backend, bool nestedParallelism)
int vtkIdType
Definition vtkType.h:367