VTK  9.3.20240328
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
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
37 namespace vtk
38 {
39 namespace detail
40 {
41 namespace smp
42 {
43 VTK_ABI_NAMESPACE_BEGIN
44 template <typename T>
45 class 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 
58 public:
59  static bool const value = sizeof(check<T>(nullptr)) == sizeof(yes_type);
60 };
61 
62 template <typename T>
63 class 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 
76 public:
77  static bool const value = sizeof(check<T>(0)) == sizeof(yes_type);
78 };
79 
80 template <typename Functor, bool Init>
81 struct vtkSMPTools_FunctorInternal;
82 
83 template <typename Functor>
84 struct 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 
102 template <typename Functor>
103 struct vtkSMPTools_FunctorInternal<Functor, true>
104 {
105  Functor& F;
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 
133 template <typename Functor>
134 class vtkSMPTools_Lookup_For
135 {
136  static bool const init = vtkSMPTools_Has_Initialize<Functor>::value;
137 
138 public:
139  typedef vtkSMPTools_FunctorInternal<Functor, init> type;
140 };
141 
142 template <typename Functor>
143 class vtkSMPTools_Lookup_For<Functor const>
144 {
145  static bool const init = vtkSMPTools_Has_Initialize_const<Functor>::value;
146 
147 public:
148  typedef vtkSMPTools_FunctorInternal<Functor const, init> type;
149 };
150 
151 template <typename Iterator, typename Functor, bool Init>
152 struct vtkSMPTools_RangeFunctor;
153 
154 template <typename Iterator, typename Functor>
155 struct 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 
174 template <typename Iterator, typename Functor>
175 struct 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 
196 template <typename Iterator, typename Functor>
197 class vtkSMPTools_Lookup_RangeFor
198 {
199  static bool const init = vtkSMPTools_Has_Initialize<Functor>::value;
200 
201 public:
202  typedef vtkSMPTools_RangeFunctor<Iterator, Functor, init> type;
203 };
204 
205 template <typename Iterator, typename Functor>
206 class vtkSMPTools_Lookup_RangeFor<Iterator, Functor const>
207 {
208  static bool const init = vtkSMPTools_Has_Initialize_const<Functor>::value;
209 
210 public:
211  typedef vtkSMPTools_RangeFunctor<Iterator, Functor const, init> type;
212 };
213 
214 template <typename T>
215 using resolvedNotInt = typename std::enable_if<!std::is_integral<T>::value, void>::type;
216 VTK_ABI_NAMESPACE_END
217 } // namespace smp
218 } // namespace detail
219 } // namespace vtk
220 #endif // DOXYGEN_SHOULD_SKIP_THIS
221 
222 VTK_ABI_NAMESPACE_BEGIN
223 class VTKCOMMONCORE_EXPORT vtkSMPTools
224 {
225 public:
227 
236  template <typename Functor>
237  static void For(vtkIdType first, vtkIdType last, vtkIdType grain, Functor& f)
238  {
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  {
247  fi.For(first, last, grain);
248  }
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  }
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);
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);
325  vtkSMPTools::For(0, size, grain, fi);
326  }
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  }
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  {
466  int MaxNumberOfThreads = 0;
468  bool NestedParallelism = false;
469 
470  Config() = default;
471  Config(int maxNumberOfThreads)
472  : MaxNumberOfThreads(maxNumberOfThreads)
473  {
474  }
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  };
521  static constexpr vtkIdType THRESHOLD = 100000;
522 
534  template <typename T>
535  static void LocalScope(Config const& config, T&& lambda)
536  {
537  auto& SMPToolsAPI = vtk::detail::smp::vtkSMPToolsAPI::GetInstance();
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  {
559  auto& SMPToolsAPI = vtk::detail::smp::vtkSMPToolsAPI::GetInstance();
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  {
583  auto& SMPToolsAPI = vtk::detail::smp::vtkSMPToolsAPI::GetInstance();
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  {
604  auto& SMPToolsAPI = vtk::detail::smp::vtkSMPToolsAPI::GetInstance();
605  SMPToolsAPI.Fill(begin, end, value);
606  }
607 
613  template <typename RandomAccessIterator>
614  static void Sort(RandomAccessIterator begin, RandomAccessIterator end)
615  {
616  auto& SMPToolsAPI = vtk::detail::smp::vtkSMPToolsAPI::GetInstance();
617  SMPToolsAPI.Sort(begin, end);
618  }
619 
626  template <typename RandomAccessIterator, typename Compare>
627  static void Sort(RandomAccessIterator begin, RandomAccessIterator end, Compare comp)
628  {
629  auto& SMPToolsAPI = vtk::detail::smp::vtkSMPToolsAPI::GetInstance();
630  SMPToolsAPI.Sort(begin, end, comp);
631  }
632 };
633 
634 VTK_ABI_NAMESPACE_END
635 #endif
636 // VTK-HeaderTest-Exclude: vtkSMPTools.h
Thread local storage for VTK objects.
T & Local()
This needs to be called mainly within a threaded execution path.
A set of parallel (multi-threaded) utility functions.
Definition: vtkSMPTools.h:224
static vtk::detail::smp::resolvedNotInt< Iter > For(Iter begin, Iter end, vtkIdType grain, Functor const &f)
Execute a for operation in parallel.
Definition: vtkSMPTools.h:320
static void Transform(InputIt1 inBegin1, InputIt1 inEnd, InputIt2 inBegin2, OutputIt outBegin, Functor transform)
A convenience method for transforming data.
Definition: vtkSMPTools.h:580
static bool GetSingleThread()
Returns true if the given thread is specified thread for single scope.
static void Initialize(int numThreads=0)
/!\ This method is not thread safe.
static bool SetBackend(const char *backend)
/!\ This method is not thread safe.
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.
Definition: vtkSMPTools.h:557
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 const &f)
Execute a for operation in parallel.
Definition: vtkSMPTools.h:370
static void SetNestedParallelism(bool isNested)
/!\ This method is not thread safe.
static void Sort(RandomAccessIterator begin, RandomAccessIterator end)
A convenience method for sorting data.
Definition: vtkSMPTools.h:614
static void Fill(Iterator begin, Iterator end, const T &value)
A convenience method for filling data.
Definition: vtkSMPTools.h:602
static void For(vtkIdType first, vtkIdType last, Functor const &f)
Execute a for operation in parallel.
Definition: vtkSMPTools.h:268
static void For(vtkIdType first, vtkIdType last, Functor &f)
Execute a for operation in parallel.
Definition: vtkSMPTools.h:262
static vtk::detail::smp::resolvedNotInt< Iter > For(Iter begin, Iter end, Functor &f)
Execute a for operation in parallel.
Definition: vtkSMPTools.h:364
static void For(vtkIdType first, vtkIdType last, vtkIdType grain, Functor const &f)
Execute a for operation in parallel.
Definition: vtkSMPTools.h:244
static vtk::detail::smp::resolvedNotInt< Iter > For(Iter begin, Iter end, vtkIdType grain, Functor &f)
Execute a for operation in parallel.
Definition: vtkSMPTools.h:311
static const char * GetBackend()
Get the backend in use.
static void Sort(RandomAccessIterator begin, RandomAccessIterator end, Compare comp)
A convenience method for sorting data.
Definition: vtkSMPTools.h:627
static bool GetNestedParallelism()
Get true if the nested parallelism is enabled.
static void LocalScope(Config const &config, T &&lambda)
/!\ This method is not thread safe.
Definition: vtkSMPTools.h:535
static void For(vtkIdType first, vtkIdType last, vtkIdType grain, Functor &f)
Execute a for operation in parallel.
Definition: vtkSMPTools.h:237
static int GetEstimatedDefaultNumberOfThreads()
Get the estimated number of threads being used by the backend by default.
static vtkSMPToolsAPI & GetInstance()
@ value
Definition: vtkX3D.h:220
@ type
Definition: vtkX3D.h:516
@ size
Definition: vtkX3D.h:253
@ string
Definition: vtkX3D.h:490
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
Structure used to specify configuration for LocalScope() method.
Definition: vtkSMPTools.h:465
Config(std::string backend)
Definition: vtkSMPTools.h:475
Config(int maxNumberOfThreads)
Definition: vtkSMPTools.h:471
Config(bool nestedParallelism)
Definition: vtkSMPTools.h:479
Config(int maxNumberOfThreads, std::string backend, bool nestedParallelism)
Definition: vtkSMPTools.h:483
int vtkIdType
Definition: vtkType.h:315