Skip to content

Commit

Permalink
Merge topic 'workUnits'
Browse files Browse the repository at this point in the history
c26cc5f ENH: default number of work units is greater than default number of threads
ffe49d7 ENH: adding backwards compatibility for MultiThreaders
ce15429 ENH: renaming NumberOfThreads into NumberOfWorkUnits in MultiThreaderBase
38f516d ENH: Add backwards compatibility for Get/SetNumberOfThreads
011266e ENH: rename NumberOfThreads into NumberOfWorkUnits in filters
  • Loading branch information
dzenanz authored and kwrobot committed Jul 18, 2018
2 parents bc3c2b5 + c26cc5f commit 2075084
Show file tree
Hide file tree
Showing 203 changed files with 1,246 additions and 1,000 deletions.
4 changes: 3 additions & 1 deletion Documentation/ITK5MigrationGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,9 @@ this->AfterThreadedGenerateData();

Get/Set GlobalMaximumNumberOfThreads and GlobalDefaultNumberOfThreads
now reside in `MultiThreaderBase`. With a warning, they are still
available in `PlatformMultiThreader`.
available in `PlatformMultiThreader`. The common case of
`innerFilter->SetNumberOfThreads(1);` should be replaced by
`innerFilter->SetNumberOfWorkUnits(1);`.

To transition to the new threading model, it is usually enough to rename
`ThreadedGenerateData` into `DynamicThreadedGenerateData`, remove the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ int main( int argc, char *argv[] )
tensorReconstructionFilter->SetGradientImage( DiffusionVectors, reader->GetOutput() );

// This is necessary until we fix netlib/dsvdc.c
tensorReconstructionFilter->SetNumberOfThreads( 1 );
tensorReconstructionFilter->SetNumberOfWorkUnits( 1 );

tensorReconstructionFilter->SetBValue(b0);
tensorReconstructionFilter->SetThreshold( static_cast<
Expand Down
37 changes: 25 additions & 12 deletions Modules/Core/Common/include/itkDomainThreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ namespace itk
* Since a threaded operation is relatively complex compared to a simple serial
* operation, a class instead of a simple method is required. Inside this
* class, the method to partition the data is handled, the logic for
* determining the number of threads is determined, and operations surrounding
* deciding the number of work units is determined, and operations surrounding
* the threading are encapsulated into the class with the
* \c DetermineNumberOfThreadsToUse, \c BeforeThreadedExecution, \c ThreadedExecution,
* \c DetermineNumberOfWorkUnitsToUse, \c BeforeThreadedExecution, \c ThreadedExecution,
* and \c AfterThreadedExecution virtual methods.
*
* \tparam TDomainPartitioner A class that inherits from
Expand Down Expand Up @@ -90,30 +90,43 @@ class ITK_TEMPLATE_EXPORT DomainThreader: public Object
void Execute( AssociateType * enclosingClass, const DomainType & domain );

/** Set/Get the DomainPartitioner. */
itkSetObjectMacro( DomainPartitioner, DomainPartitionerType );
itkGetModifiableObjectMacro(DomainPartitioner, DomainPartitionerType );
itkSetObjectMacro( DomainPartitioner, DomainPartitionerType );
itkGetModifiableObjectMacro( DomainPartitioner, DomainPartitionerType );

/** Accessor for number of threads that were actually used in the last
/** Accessor for number of work units that were actually used in the last
* ThreadedExecution. */
itkGetConstMacro( NumberOfThreadsUsed, ThreadIdType );
itkGetConstMacro( NumberOfWorkUnitsUsed, ThreadIdType );

/** Return the multithreader used by this class. */
MultiThreaderBase * GetMultiThreader() const;

/** Convenience methods to set/get the desired number of work units to use.
* \warning When setting the desired number of work units, it might be clamped by
* itk::MultiThreaderBase::GetGlobalMaximumNumberOfThreads().
* */
ThreadIdType GetNumberOfWorkUnits() const
{
return this->m_MultiThreader->GetNumberOfWorkUnits();
}
void SetNumberOfWorkUnits( const ThreadIdType workUnits );

/** Convenience methods to set/get the maximum number of threads to use.
* \warning When setting the maximum number of threads, it will be clamped by
* itk::MultiThreaderBase::GetGlobalMaximumNumberOfThreads() and ITK_MAX_THREADS.
* itk::MultiThreaderBase::GetGlobalMaximumNumberOfThreads().
* */
ThreadIdType GetMaximumNumberOfThreads() const;
void SetMaximumNumberOfThreads( const ThreadIdType threads );
ThreadIdType GetMaximumNumberOfThreads() const
{
return this->m_MultiThreader->GetMaximumNumberOfThreads();
}
void SetMaximumNumberOfThreads(const ThreadIdType threads);

protected:
DomainThreader();
~DomainThreader() override;

/** This is evauated at the beginning of Execute() so that it can be used in
* BeforeThreadedExecution(). */
virtual void DetermineNumberOfThreadsUsed();
virtual void DetermineNumberOfWorkUnitsUsed();

/** When \c Execute is run, this method is run singled-threaded before \c
* ThreadedExecution. Inside this method optional operations such as
Expand Down Expand Up @@ -154,11 +167,11 @@ class ITK_TEMPLATE_EXPORT DomainThreader: public Object
DomainThreader * domainThreader;
};

/** Store the actual number of threads used, which may be less than
/** Store the actual number of work units used, which may be less than
* the number allocated by the threader if the object does not split
* well into that number.
* This value is determined at the beginning of \c Execute(). */
ThreadIdType m_NumberOfThreadsUsed;
ThreadIdType m_NumberOfWorkUnitsUsed;
typename DomainPartitionerType::Pointer m_DomainPartitioner;
DomainType m_CompleteDomain;
MultiThreaderBase::Pointer m_MultiThreader;
Expand Down
42 changes: 23 additions & 19 deletions Modules/Core/Common/include/itkDomainThreader.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ template< typename TDomainPartitioner, typename TAssociate >
DomainThreader< TDomainPartitioner, TAssociate >
::DomainThreader()
{
this->m_DomainPartitioner = DomainPartitionerType::New();
this->m_MultiThreader = MultiThreaderBase::New();
this->m_NumberOfThreadsUsed = 0;
this->m_Associate = nullptr;
this->m_DomainPartitioner = DomainPartitionerType::New();
this->m_MultiThreader = MultiThreaderBase::New();
this->m_NumberOfWorkUnitsUsed = 0;
this->m_Associate = nullptr;
}

template< typename TDomainPartitioner, typename TAssociate >
Expand All @@ -48,11 +48,15 @@ DomainThreader< TDomainPartitioner, TAssociate >
}

template< typename TDomainPartitioner, typename TAssociate >
ThreadIdType
void
DomainThreader< TDomainPartitioner, TAssociate >
::GetMaximumNumberOfThreads() const
::SetNumberOfWorkUnits( const ThreadIdType workUnits )
{
return this->m_MultiThreader->GetNumberOfThreads();
if( workUnits != this->GetNumberOfWorkUnits() )
{
this->m_MultiThreader->SetNumberOfWorkUnits( workUnits );
this->Modified();
};
}

template< typename TDomainPartitioner, typename TAssociate >
Expand All @@ -62,7 +66,7 @@ DomainThreader< TDomainPartitioner, TAssociate >
{
if( threads != this->GetMaximumNumberOfThreads() )
{
this->m_MultiThreader->SetNumberOfThreads( threads );
this->m_MultiThreader->SetMaximumNumberOfThreads( threads );
this->Modified();
}
}
Expand All @@ -75,7 +79,7 @@ DomainThreader< TDomainPartitioner, TAssociate >
this->m_Associate = enclosingClass;
this->m_CompleteDomain = completeDomain;

this->DetermineNumberOfThreadsUsed();
this->DetermineNumberOfWorkUnitsUsed();

this->BeforeThreadedExecution();

Expand All @@ -88,26 +92,26 @@ DomainThreader< TDomainPartitioner, TAssociate >
template< typename TDomainPartitioner, typename TAssociate >
void
DomainThreader< TDomainPartitioner, TAssociate >
::DetermineNumberOfThreadsUsed()
::DetermineNumberOfWorkUnitsUsed()
{
const ThreadIdType threaderNumberOfThreads = this->GetMultiThreader()->GetNumberOfThreads();
const ThreadIdType threaderNumberOfThreads = this->GetMultiThreader()->GetNumberOfWorkUnits();

// Attempt a single dummy partition, just to get the number of subdomains actually created
DomainType subdomain;
this->m_NumberOfThreadsUsed = this->m_DomainPartitioner->PartitionDomain(0,
this->m_NumberOfWorkUnitsUsed = this->m_DomainPartitioner->PartitionDomain(0,
threaderNumberOfThreads,
this->m_CompleteDomain,
subdomain);

if( this->m_NumberOfThreadsUsed < threaderNumberOfThreads )
if( this->m_NumberOfWorkUnitsUsed < threaderNumberOfThreads )
{
// If PartitionDomain is only able to create a lesser number of subdomains,
// ensure that superfluous threads aren't created
// ensure that superfluous work units aren't created
// DomainThreader::SetMaximumNumberOfThreads *should* already have been called by this point,
// but it's not fatal if it somehow gets called later
this->GetMultiThreader()->SetNumberOfThreads(this->m_NumberOfThreadsUsed);
this->GetMultiThreader()->SetNumberOfWorkUnits(this->m_NumberOfWorkUnitsUsed);
}
else if( this->m_NumberOfThreadsUsed > threaderNumberOfThreads )
else if( this->m_NumberOfWorkUnitsUsed > threaderNumberOfThreads )
{
itkExceptionMacro( "A subclass of ThreadedDomainPartitioner::PartitionDomain"
<< "returned more subdomains than were requested" );
Expand Down Expand Up @@ -135,11 +139,11 @@ ITK_THREAD_RETURN_TYPE
DomainThreader< TDomainPartitioner, TAssociate >
::ThreaderCallback( void* arg )
{
auto * info = static_cast<MultiThreaderBase::ThreadInfoStruct *>(arg);
auto * info = static_cast<MultiThreaderBase::WorkUnitInfo *>(arg);
auto * str = static_cast<ThreadStruct *>(info->UserData);
DomainThreader *thisDomainThreader = str->domainThreader;
const ThreadIdType threadId = info->ThreadID;
const ThreadIdType threadCount = info->NumberOfThreads;
const ThreadIdType threadId = info->WorkUnitID;
const ThreadIdType threadCount = info->NumberOfWorkUnits;

// Get the sub-domain to process for this thread.
DomainType subdomain;
Expand Down
2 changes: 1 addition & 1 deletion Modules/Core/Common/include/itkImageSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ class ITK_TEMPLATE_EXPORT ImageSource
* in its own specific thread. Pool and TBB multi-threaders maintain
* a pool of threads (normally equal to number of processing cores)
* which they use to process the pieces. This normally results
* in a single thread being reused to process multiple pieces.
* in a single thread being reused to process multiple work units.
*
* \sa GenerateData(), SplitRequestedRegion() */
virtual void ThreadedGenerateData(const OutputImageRegionType & outputRegionForThread,
Expand Down
12 changes: 6 additions & 6 deletions Modules/Core/Common/include/itkImageSource.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,9 @@ ImageSource<TOutputImage>

const OutputImageType *outputPtr = this->GetOutput();
const ImageRegionSplitterBase * splitter = this->GetImageRegionSplitter();
const unsigned int validThreads = splitter->GetNumberOfSplits(outputPtr->GetRequestedRegion(), this->GetNumberOfThreads());
const unsigned int validThreads = splitter->GetNumberOfSplits(outputPtr->GetRequestedRegion(), this->GetNumberOfWorkUnits());

this->GetMultiThreader()->SetNumberOfThreads(validThreads);
this->GetMultiThreader()->SetNumberOfWorkUnits(validThreads);
this->GetMultiThreader()->SetSingleMethod(callbackFunction, &str);

this->GetMultiThreader()->SingleMethodExecute();
Expand All @@ -238,7 +238,7 @@ ImageSource< TOutputImage >
}
else
{
this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
this->GetMultiThreader()->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());
this->GetMultiThreader()->template ParallelizeImageRegion<OutputImageDimension>(
this->GetOutput()->GetRequestedRegion(),
[this](const OutputImageRegionType & outputRegionForThread)
Expand Down Expand Up @@ -287,10 +287,10 @@ ITK_THREAD_RETURN_TYPE
ImageSource< TOutputImage >
::ThreaderCallback(void *arg)
{
using ThreadInfo = MultiThreaderBase::ThreadInfoStruct;
using ThreadInfo = MultiThreaderBase::WorkUnitInfo;
ThreadInfo * threadInfo = static_cast<ThreadInfo *>(arg);
ThreadIdType threadId = threadInfo->ThreadID;
ThreadIdType threadCount = threadInfo->NumberOfThreads;
ThreadIdType threadId = threadInfo->WorkUnitID;
ThreadIdType threadCount = threadInfo->NumberOfWorkUnits;
ThreadStruct *str = (ThreadStruct *)(threadInfo->UserData);

// execute the actual method with appropriate output region
Expand Down
2 changes: 1 addition & 1 deletion Modules/Core/Common/include/itkImageToImageFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ namespace itk
* GenerateData(), the image processing will run in a single thread and the
* implementation is responsible for allocating its output data. If a filter
* provides an implementation of ThreadedGenerateData() instead, the image
* will be divided into a number of pieces, a number of threads will be
* will be divided into a number of work units, a number of threads will be
* spawned, and ThreadedGenerateData() will be called in each thread. Here,
* the output memory will be allocated by this superclass prior to calling
* ThreadedGenerateData().
Expand Down
8 changes: 4 additions & 4 deletions Modules/Core/Common/include/itkImageTransformer.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ ImageTransformer< TInputImage >
ThreadStruct str;
str.Filter = this;

this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
this->GetMultiThreader()->SetNumberOfWorkUnits(this->GetNumberOfWorkUnits());
this->GetMultiThreader()->SetSingleMethod(callbackFunction, &str);

this->GetMultiThreader()->SingleMethodExecute();
Expand Down Expand Up @@ -337,10 +337,10 @@ ImageTransformer< TInputImage >
ThreadStruct *str;
ThreadIdType total, threadId, threadCount;

threadId = ( (MultiThreaderBase::ThreadInfoStruct *)( arg ) )->ThreadID;
threadCount = ( (MultiThreaderBase::ThreadInfoStruct *)( arg ) )->NumberOfThreads;
threadId = ( (MultiThreaderBase::WorkUnitInfo *)( arg ) )->WorkUnitID;
threadCount = ( (MultiThreaderBase::WorkUnitInfo *)( arg ) )->NumberOfWorkUnits;

str = (ThreadStruct *)( ( (MultiThreaderBase::ThreadInfoStruct *)( arg ) )->UserData );
str = (ThreadStruct *)( ( (MultiThreaderBase::WorkUnitInfo *)( arg ) )->UserData );

// execute the actual method with appropriate output region
// first find out how many pieces extent can be split into.
Expand Down
12 changes: 10 additions & 2 deletions Modules/Core/Common/include/itkMacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,21 @@ namespace itk
#if defined(__clang__) && defined(__has_warning)
#define CLANG_PRAGMA_PUSH ITK_PRAGMA(clang diagnostic push)
#define CLANG_PRAGMA_POP ITK_PRAGMA(clang diagnostic pop)
# if __has_warning("-Wfloat-equal")
#if __has_warning("-Wfloat-equal")
#define CLANG_SUPPRESS_Wfloat_equal ITK_PRAGMA( clang diagnostic ignored "-Wfloat-equal" )
# endif
#else
#define CLANG_SUPPRESS_Wfloat_equal
#endif
#if __has_warning( "-Wc++14-extensions" )
#define CLANG_SUPPRESS_Wc__14_extensions ITK_PRAGMA( clang diagnostic ignored "-Wc++14-extensions" )
#else
#define CLANG_SUPPRESS_Wc__14_extensions
#endif
#else
#define CLANG_PRAGMA_PUSH
#define CLANG_PRAGMA_POP
#define CLANG_SUPPRESS_Wfloat_equal
#define CLANG_SUPPRESS_Wc__14_extensions
#endif

// Define ITK_GCC_PRAGMA_DIAG(param1 [param2 [...]]) macro.
Expand Down
Loading

0 comments on commit 2075084

Please sign in to comment.