1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
/**
\page ThreadingPage Threading
\section ThreadingIntroduction Introduction
ITK is designed to run in multiprocessor environments. Many of
ITK's filters are multithreaded. When a multithreading filter
executes, it automatically divides the work amongst multiprocessors
in a shared memory configuration. We call this "Filter Level
Multithreading". Applications built with ITK can also manage their
own execution threads. For instance, an application might use one
thread for processing data and another thread for a user
interface. We call this "Application Level Multithreading".
\image html Threading.gif "Filters may process their data in multiple threads in a shared memory configuration."
\section FilterThreadSafety Filter Level Multithreading
A multithreaded filter provides an implementation of the
ThreadedGenerateData() method (see
itk::ImageSource::ThreadedGenerateData()) as opposed to the
normal single threaded GenerateData() method (see
itk::ImageSource::GenerateData()). A superclass of the filter will
spawn several threads (usually matching the number of processors in
the system) and call ThreadedGenerateData() in each thread
specifying the portion of the output that a given thread is
responsible for generating. For instance, on a dual processor
computer, an image processing filter will spawn two threads, each
processing thread will generate one half of the output image, and
each thread is restricted to writing to separate portions of the
output image. Note that the "entire" input and "entire" output
images (i.e. what would be available normally to the GenerateData()
method, see the discussion on Streaming) are available to each
call of ThreadedGenerateData(). Each thread is allowed to read
from anywhere in the input image but each thread can only write to
its designated portion of the output image.
The output image is a single contiguous block on memory that is
used for all processing threads. Each thread is informed which
pixels they are responsible for producing the output values. All
the threads write to this same block of memory but a given thread
is only allowed to set specific pixels.
\subsection FilterMemoryAllocation Memory Management
The GenerateData() method is responsible for allocation the output
bulk data. For an image processing filter, this corresponds to
calling Allocate() on the output image object. If a filter is
multithreaded, then it does not provide a GenerateData() method but
provides a ThreadedGenerateData() method. In this case, a
superclass' GenerateData() method will allocate the output bulk
data and call ThreadedGenerateData() for each thread. If a filter
is not multithreaded, then it must provided its own GenerateData()
method and allocate the bulk output data (for instance, calling
Allocate() on an output image) itself.
\section ApplicationThreadSafety Application Level Multithreading
ITK applications can be written to have multiple execution threads.
This is distinct from a given filter dividing its labor across
multiple execution threads. If the former, the application is
responsible for spawning the separate execution threads,
terminating threads, and handling all events
mechanisms. (itk::MultiThreader can be used to spawn threads and
terminate threads in a platform independent manner.) In the latter
case, an individual filter will automatically spawn threads, execute
an algorithm, and terminate the processing threads.
Care must in taken in setting up an application to have separate
application level (as opposed to filter level) execution threads.
Individual ITK objects are not guaranteed to be thread safe. By this
we mean that a single instance of an object should only be modified
by a single execution thread. You should not try to modify a single
instance of an object in multiple execution threads.
ITK is designed so that different instances of the same class can be
accessed in different execution threads. But multiple threads should
not attempt to modify a single instance. This granularity of thread
safety was chosen as a compromise between performance and flexibility.
If we allow ITK objects to be modified in multiple threads then ITK
would have to mutex every access to every instance variable of a
class. This would severely affect performance.
\section NumericsThreadSafety Thread Safety in the Numerics Library
ITK uses a C++ wrapper around the standard NETLIB distributions
(https://www.netlib.org). These NETLIB distributions were converted
from FORTRAN to C using the standard f2c converter
(https://www.netlib.org/f2c/). A cursory glance at the f2c
generated NETLIB C code yields the impression that the NETLIB code
is not thread safe (due to COMMON blocks being translated to
function scope statics). We are still investigating this matter.
*/
|