@@ -18,7 +18,7 @@ \section{System Organization}
1818 concepts include generic programming, smart pointers for memory
1919 management, object factories for adaptable object instantiation,
2020 event management using the command/observer design paradigm, and
21- multithreading support.
21+ multi-threading support.
2222
2323 \item [Numerics.] ITK uses VXL's VNL numerics libraries. These are
2424 easy-to-use C++ wrappers around the Netlib Fortran numerical
@@ -36,7 +36,7 @@ \section{System Organization}
3636 \emph {filters } that in turn may be organized into data flow
3737 \emph {pipelines }. These pipelines maintain state and therefore
3838 execute only when necessary. They also support
39- multithreading , and are streaming capable (i.e., can operate
39+ multi-threading , and are streaming capable (i.e., can operate
4040 on pieces of data to minimize the memory footprint).
4141
4242 \item [IO Framework.] Associated with the data processing
@@ -375,30 +375,100 @@ \subsection{Event Handling}
375375\subsection {Multi-Threading }
376376\label {sec:MultiThreading }
377377
378- Multithreading is handled in ITK through a high-level design
379- abstraction. This approach provides portable multithreading and hides the
378+ Multi-threading is handled in ITK through a high-level design
379+ abstraction. This approach provides portable multi-threading and hides the
380380complexity of differing thread implementations on the many systems supported
381- by ITK. For example, the class \doxygen {MultiThreader} provides support for
382- multithreaded execution using \code {sproc()} on an SGI, or
383- \code {pthread\_ create} on any platform supporting POSIX threads.
384-
385- Multithreading is typically employed by an algorithm during its execution
386- phase. MultiThreader can be used to execute a single method on
387- multiple threads, or to specify a method per thread. For example, in the
381+ by ITK. For example, the class \doxygen {PlatformMultiThreader} provides support for
382+ multi-threaded execution by directly using platform-specific primitives such as
383+ \code {pthread\_ create}. \doxygen {TBBMultiThreader} uses Intel's
384+ Thread Building Blocks cross-platform library,
385+ which can do dynamic workload balancing across multiple processes.
386+ This means that \code {outputRegionForThread} might have different sizes
387+ which change over time, depending on overall processor load.
388+ All multi-threader implementations derive from \doxygen {MultiThreaderBase}.
389+
390+ Multi-threading is typically employed by an algorithm during its execution
391+ phase. For example, in the
388392class \doxygen {ImageSource} (a superclass for most image processing filters)
389393the \code {GenerateData()} method uses the following methods:
390394
391395\small
392396\begin {minted }[baselinestretch=1,fontsize=\footnotesize ,linenos=false,bgcolor=ltgray]{cpp}
393- multiThreader->SetNumberOfThreads(int);
394- multiThreader->SetSingleMethod(ThreadFunctionType, void* data);
395- multiThreader->SingleMethodExecute();
397+ this->GetMultiThreader()->template ParallelizeImageRegion<OutputImageDimension>(
398+ this->GetOutput()->GetRequestedRegion(),
399+ [this](const OutputImageRegionType & outputRegionForThread)
400+ { this->DynamicThreadedGenerateData(outputRegionForThread); }, this);
401+ \end {minted }
402+ \normalsize
403+
404+ In this example each thread invokes \code {DynamicThreadedGenerateData}
405+ method of the derived filter. The \code {ParallelizeImageRegion}
406+ method takes care to divide the image into different regions
407+ that do not overlap for write operations.
408+ \code {ImageSource}'s \code {GenerateData()} passes \code {this} pointer
409+ to \code {ParallelizeImageRegion}, which allows \code {ParallelizeImageRegion}
410+ to update the filter's progress after each region is finished processing.
411+
412+ If a filter has some serial part in the middle, in addition to initialization
413+ done in \code {BeforeThreadedGenerateData()} and finalization done in
414+ \code {AfterThreadedGenerateData()}, it can parallelize more than one method
415+ in its own version of \code {GenerateData()}, such as done by
416+ \doxygen {CannyEdgeDetectionImageFilter}:
417+
418+ \small
419+ \begin {minted }[baselinestretch=1,fontsize=\footnotesize ,linenos=false,bgcolor=ltgray]{cpp}
420+ ::GenerateData()
421+ {
422+ this->UpdateProgress(0.0f);
423+ Superclass::AllocateOutputs();
424+ // Small serial section
425+ this->UpdateProgress(0.01f);
426+
427+ // Calculate 2nd order directional derivative
428+ this->GetMultiThreader()->template ParallelizeImageRegion<TOutputImage::ImageDimension>(
429+ this->GetOutput()->GetRequestedRegion(),
430+ [this](const OutputImageRegionType & outputRegionForThread)
431+ { this->ThreadedCompute2ndDerivative(outputRegionForThread); }, nullptr);
432+ this->UpdateProgress(0.45f);
433+
434+ // Calculate the gradient of the second derivative
435+ this->GetMultiThreader()->template ParallelizeImageRegion<TOutputImage::ImageDimension>(
436+ this->GetOutput()->GetRequestedRegion(),
437+ [this](const OutputImageRegionType & outputRegionForThread)
438+ { this->ThreadedCompute2ndDerivativePos(outputRegionForThread); }, nullptr);
439+ this->UpdateProgress(0.9f);
440+
441+ // More processing
442+ this->UpdateProgress(1.0f);
443+ }
396444\end {minted }
397445\normalsize
398446
399- In this example each thread invokes the same method. The multithreaded filter
400- takes care to divide the image into different regions that do not overlap for
401- write operations.
447+ When invoking \code {ParallelizeImageRegion} multiple times from
448+ \code {GenerateData()}, \code {nullptr} should be passed instead of \code {this},
449+ otherwise progress will go from 0\% to 100\% more than once. And this
450+ will at least confuse any other class watching the filter's progress events,
451+ even if it does not cause a crash. So the filter's author should estimate
452+ how long each part of \code {GenerateData()} takes, and update the progress
453+ `` manually'' as in the example above.
454+
455+ With ITK version 5.0, the Multi-Threading mechanism has been refactored.
456+ What was previously \code {itk::MultiThreader}, is now a hierarchy of classes.
457+ \doxygen {PlatformMultiThreader} is a slightly cleaned-up version of the old
458+ class - \code {MultipleMethodExecute} and \code {SpawnThread} methods have been
459+ deprecated. But much of its content has been moved to
460+ \doxygen {MultiThreaderBase}. And classes should use the multi-threaders via
461+ \code {MultiThreaderBase} interface, to allow the end user the flexibility to
462+ select the multi-threader at run time. This also allows the filter to
463+ benefit from future improvements in threading such as addition of a new
464+ multi-threader implementation.
465+
466+ The backwards compatible \code {ThreadedGenerateData(Region, ThreadId)} method
467+ signature has been kept, for use in filters that must know their thread number.
468+ To use this signature, a filter must invoke
469+ \code {this->DynamicMultiThreadingOff();} before \code {Update();} is called by
470+ the filter's user or downstream filter in the pipeline. The best place for
471+ invoking \code {this->DynamicMultiThreadingOff();} is the filter's constructor.
402472
403473The general philosophy in ITK regarding thread safety is that accessing
404474different instances of a class (and its methods) is a thread-safe operation.
@@ -501,7 +571,7 @@ \section{Data Representation}
501571
502572One of the important ITK concepts regarding images is that rectangular,
503573continuous pieces of the image are known as \emph {regions }. Regions are used
504- to specify which part of an image to process, for example in multithreading ,
574+ to specify which part of an image to process, for example in multi-threading ,
505575or which part to hold in memory. In ITK there are three common types of
506576regions:
507577\begin {enumerate }
0 commit comments