ITK  5.0.0
Insight Segmentation and Registration Toolkit
itkMultiThreaderBase.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 /*=========================================================================
19  *
20  * Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21  *
22  * Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23  *
24  * For complete copyright, license and disclaimer of warranty information
25  * please refer to the NOTICE file at the top of the ITK source tree.
26  *
27  *=========================================================================*/
28 #ifndef itkMultiThreaderBase_h
29 #define itkMultiThreaderBase_h
30 
31 #include "itkObject.h"
32 #include "itkThreadSupport.h"
33 #include "itkObjectFactory.h"
34 #include "itkIntTypes.h"
35 #include "itkImageRegion.h"
36 #include "itkImageIORegion.h"
37 #include "itkSingletonMacro.h"
38 #include <functional>
39 #include <thread>
40 
41 
42 namespace itk
43 {
58 struct MultiThreaderBaseGlobals;
59 class ProcessObject;
60 
61 class ITKCommon_EXPORT MultiThreaderBase : public Object
62 {
63 public:
64  ITK_DISALLOW_COPY_AND_ASSIGN(MultiThreaderBase);
65 
68  using Superclass = Object;
71 
73  static Pointer New();
74 
76  itkTypeMacro(MultiThreaderBase, Object);
77 
81  virtual void SetMaximumNumberOfThreads( ThreadIdType numberOfThreads );
82  itkGetConstMacro( MaximumNumberOfThreads, ThreadIdType );
84 
88  virtual void SetNumberOfWorkUnits( ThreadIdType numberOfWorkUnits );
89  itkGetConstMacro( NumberOfWorkUnits, ThreadIdType );
91 
97  static void SetGlobalMaximumNumberOfThreads(ThreadIdType val);
98  static ThreadIdType GetGlobalMaximumNumberOfThreads();
100 
106  itkLegacyMacro(static void SetGlobalDefaultUseThreadPool( const bool GlobalDefaultUseThreadPool ));
107  itkLegacyMacro(static bool GetGlobalDefaultUseThreadPool( ));
109 
112  enum ThreaderType { Platform = 0, First = Platform, Pool, TBB, Last = TBB, Unknown = -1 };
113 
115  static ThreaderType ThreaderTypeFromString(std::string threaderString);
116 
118  static std::string ThreaderTypeToString(ThreaderType threader)
119  {
120  switch (threader)
121  {
122  case ThreaderType::Platform:
123  return "Platform";
124  break;
125  case ThreaderType::Pool:
126  return "Pool";
127  break;
128  case ThreaderType::TBB:
129  return "TBB";
130  break;
131  case ThreaderType::Unknown:
132  default:
133  return "Unknown";
134  break;
135  }
136  }
138 
150  static void SetGlobalDefaultThreader(ThreaderType threaderType);
151  static ThreaderType GetGlobalDefaultThreader();
153 
158  static void SetGlobalDefaultNumberOfThreads(ThreadIdType val);
159  static ThreadIdType GetGlobalDefaultNumberOfThreads();
161 
162 #if !defined( ITK_LEGACY_REMOVE )
163 
165  itkLegacyMacro( virtual void SetNumberOfThreads( ThreadIdType numberOfThreads ) )
166  {
167  this->SetMaximumNumberOfThreads( numberOfThreads );
168  this->SetNumberOfWorkUnits( this->GetMaximumNumberOfThreads() ); // Might be clamped
169  }
170  itkLegacyMacro( virtual ThreadIdType GetNumberOfThreads() )
171  {
172  return this->GetNumberOfWorkUnits();
173  }
175 
184 #ifdef ITK_HAS_GCC_PRAGMA_DIAG_PUSHPOP
185  ITK_GCC_PRAGMA_DIAG_PUSH()
186 #endif
187 ITK_GCC_PRAGMA_DIAG(ignored "-Wattributes")
188 INTEL_PRAGMA_WARN_PUSH
189 INTEL_SUPPRESS_warning_1292
190 CLANG_PRAGMA_PUSH
191 CLANG_SUPPRESS_Wc__14_extensions
192  struct [[deprecated( "Use WorkUnitInfo, ThreadInfoStruct is deprecated since ITK 5.0" )]] ThreadInfoStruct
193 CLANG_PRAGMA_POP
194 INTEL_PRAGMA_WARN_POP
195  {
196  ThreadIdType ThreadID;
197  ThreadIdType NumberOfThreads;
198  void* UserData;
199  ThreadFunctionType ThreadFunction;
200  enum { SUCCESS, ITK_EXCEPTION, ITK_PROCESS_ABORTED_EXCEPTION, STD_EXCEPTION, UNKNOWN } ThreadExitCode;
201  };
202 #ifdef ITK_HAS_GCC_PRAGMA_DIAG_PUSHPOP
203  ITK_GCC_PRAGMA_DIAG_POP()
204 #else
205  ITK_GCC_PRAGMA_DIAG(warning "-Wattributes")
206 #endif
207 #endif //ITK_LEGACY_REMOVE
208 
209 
217  {
220  void* UserData;
222  enum
223  {
228  UNKNOWN
229  } ThreadExitCode;
230  };
231 
236  virtual void SingleMethodExecute() = 0;
237 
242  virtual void SetSingleMethod(ThreadFunctionType, void *data) = 0;
243 
244  template <unsigned int VDimension>
245  using TemplatedThreadingFunctorType = std::function<void(const ImageRegion<VDimension> &)>;
246  using ThreadingFunctorType = std::function<void(
247  const IndexValueType index[],
248  const SizeValueType size[])>;
249  using ArrayThreadingFunctorType = std::function< void( SizeValueType ) >;
250 
256  virtual void
257  ParallelizeArray(
258  SizeValueType firstIndex,
259  SizeValueType lastIndexPlus1,
261  ProcessObject* filter );
262 
266  template<unsigned int VDimension>
267  ITK_TEMPLATE_EXPORT void ParallelizeImageRegion(const ImageRegion<VDimension> & requestedRegion,
269  ProcessObject* filter)
270  {
271  this->ParallelizeImageRegion(
272  VDimension,
273  requestedRegion.GetIndex().m_InternalArray,
274  requestedRegion.GetSize().m_InternalArray,
275  [funcP](const IndexValueType index[], const SizeValueType size[])
276  {
278  for (unsigned int d = 0; d < VDimension; ++d)
279  {
280  region.SetIndex(d, index[d]);
281  region.SetSize(d, size[d]);
282  }
283  funcP(region);
284  },
285  filter);
286  }
288 
292  template<unsigned int VDimension>
293  ITK_TEMPLATE_EXPORT void ParallelizeImageRegionRestrictDirection(unsigned int restrictedDirection,
294  const ImageRegion<VDimension> & requestedRegion,
296  ProcessObject* filter)
297  {
298  if (VDimension <= 1) // Cannot split, no parallelization
299  {
301  funcP(requestedRegion);
303  }
304  else // Can split, parallelize!
305  {
306  constexpr unsigned int SplitDimension = (VDimension-1) ? VDimension-1 : VDimension;
307  using SplitRegionType = ImageRegion<SplitDimension>;
309 
310  SplitRegionType splitRegion;
311  for( unsigned int splitDimension = 0, dimension = 0; dimension < VDimension; ++dimension )
312  {
313  if( dimension == restrictedDirection )
314  {
315  continue;
316  }
317  splitRegion.SetIndex( splitDimension, requestedRegion.GetIndex( dimension ) );
318  splitRegion.SetSize( splitDimension, requestedRegion.GetSize( dimension ) );
319  ++splitDimension;
320  }
321 
322  this->ParallelizeImageRegion(
323  SplitDimension,
324  splitRegion.GetIndex().m_InternalArray,
325  splitRegion.GetSize().m_InternalArray,
326  [&](const IndexValueType index[], const SizeValueType size[])
327  {
328  ImageRegion<VDimension> restrictedRequestedRegion;
329  restrictedRequestedRegion.SetIndex( restrictedDirection, requestedRegion.GetIndex( restrictedDirection ) );
330  restrictedRequestedRegion.SetSize( restrictedDirection, requestedRegion.GetSize( restrictedDirection ) );
331  for( unsigned int splitDimension = 0, dimension = 0; dimension < VDimension; ++dimension )
332  {
333  if( dimension == restrictedDirection )
334  {
335  continue;
336  }
337  restrictedRequestedRegion.SetIndex( dimension, index[splitDimension] );
338  restrictedRequestedRegion.SetSize( dimension, size[splitDimension] );
339  ++splitDimension;
340  }
341  funcP( restrictedRequestedRegion );
342  },
343  filter );
344  }
345  }
346 
349  virtual void ParallelizeImageRegion(
350  unsigned int dimension,
351  const IndexValueType index[],
352  const SizeValueType size[],
353  ThreadingFunctorType funcP,
354  ProcessObject* filter);
355 
358  static void HandleFilterProgress(ProcessObject *filter, float progress = -1.0f);
359 
360 protected:
362  ~MultiThreaderBase() override;
363  void PrintSelf(std::ostream & os, Indent indent) const override;
364 
366  {
371  std::thread::id callingThread;
372  std::atomic<SizeValueType> progress;
373  };
374 
375  static ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION ParallelizeArrayHelper(void *arg);
376 
378  {
380  unsigned int dimension;
384  std::thread::id callingThread;
386  std::atomic<SizeValueType> pixelProgress;
387  };
388 
389  static ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION ParallelizeImageRegionHelper(void *arg);
390 
393 
403 
410  static ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION SingleMethodProxy(void *arg);
411 
414 
417 
418 private:
419 
421  itkGetGlobalDeclarationMacro(MultiThreaderBaseGlobals, PimplGlobals);
422 
423  static MultiThreaderBaseGlobals * m_PimplGlobals;
427  friend class ProcessObject;
428 
430  static ThreadIdType GetGlobalDefaultNumberOfThreadsByPlatform();
431 
432 };
433 
434 ITKCommon_EXPORT std::ostream& operator << (std::ostream& os,
435  const MultiThreaderBase::ThreaderType& threader);
436 
437 } // end namespace itk
438 #endif
void SetSize(const SizeType &size)
void(* ThreadFunctionType)(void *)
Light weight base class for most itk classes.
const IndexType & GetIndex() const
static void HandleFilterProgress(ProcessObject *filter, float progress=-1.0f)
unsigned long SizeValueType
Definition: itkIntTypes.h:83
SizeValueType m_InternalArray[VDimension]
Definition: itkSize.h:220
static MultiThreaderBaseGlobals * m_PimplGlobals
std::ostream & operator<<(std::ostream &os, const Array< TValue > &arr)
Definition: itkArray.h:188
The base class for all process objects (source, filters, mappers) in the Insight data processing pipe...
std::atomic< SizeValueType > progress
ThreadFunctionType m_SingleMethod
itk::ITK_THREAD_RETURN_TYPE ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION
class ITK_FORWARD_EXPORT ProcessObject
Definition: itkDataObject.h:40
std::function< void(SizeValueType) > ArrayThreadingFunctorType
std::function< void(const IndexValueType index[], const SizeValueType size[])> ThreadingFunctorType
IndexValueType m_InternalArray[VDimension]
Definition: itkIndex.h:276
#define itkGetGlobalDeclarationMacro(Type, VarName)
static std::string ThreaderTypeToString(ThreaderType threader)
signed long IndexValueType
Definition: itkIntTypes.h:90
ITK_TEMPLATE_EXPORT void ParallelizeImageRegionRestrictDirection(unsigned int restrictedDirection, const ImageRegion< VDimension > &requestedRegion, TemplatedThreadingFunctorType< VDimension > funcP, ProcessObject *filter)
const SizeType & GetSize() const
A class for performing multithreaded execution.
std::function< void(const ImageRegion< VDimension > &)> TemplatedThreadingFunctorType
unsigned int ThreadIdType
Definition: itkIntTypes.h:99
Control indentation during Print() invocation.
Definition: itkIndent.h:49
Base class for most ITK classes.
Definition: itkObject.h:60
void SetIndex(const IndexType &index)
ITK_TEMPLATE_EXPORT void ParallelizeImageRegion(const ImageRegion< VDimension > &requestedRegion, TemplatedThreadingFunctorType< VDimension > funcP, ProcessObject *filter)