[Insight-developers] RE: multi-thread filter

Miller, James V (CRD) millerjv@crd.ge.com
Tue, 25 Sep 2001 12:22:33 -0400


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_001_01C145DE.480751A0
Content-Type: text/plain;
	charset="iso-8859-1"

Lydia had an issue with multithreading some of her filters.  She needed to perform some filter
initialization prior to having the threads spawned. Here original message is below.

To address this, I modified the pipeline execution model so that the default implementation of
GenerateData() inherited from ImageSource performs the following steps:

1) Allocate the output buffer
2) Call BeforeThreadedGenerateData()
3) Spawn threads, calling ThreadedGenerateData() in each thread.
4) Call AfterThreadedGenerateData()

This added two new methods: ImageSource::BeforeThreadedGenerateData() and
ImageSource::AfterThreadedGenerateData().  These methods are called in the main processing thread
before/after the threaded computation is performed.  You can use these methods to perform setup or
breakdown operations. A setup operation might initialize member ivars so that they are ready for all
the threads to use (be careful that their use by each thread is done in a thread safe manner).  A
breakdown operation might merge or summarize information calculated by threads.

These methods are a convenience operation and do not have to be used.  They only apply to the
ThreadedGenerateData() case.  There is no corresponding BeforeGenerateData(), AfterGenerateData()
pair since those operations could simply be put in the GenerateData() method of a single threaded
filter.

There is another way this could have been done (and can still be done) which is to use a MutexLock
inside the ThreadedGenerateData() method to synchronize the threads. You would use a mutex lock
around the initialization code.  The first thread to get inside the lock would perform all the
initialization and then set an ivar to indicate that everything was initialized.  Then it would
release the lock.  The other threads would each grab the lock, see that everything was initialized
and release the lock.

The filter would have an ivar of type SimpleFastMutexLock m_Lock and an ivar m_Initialized. The
ThreadedGenerateData() method would then have code that looks like

m_Lock.Lock();
if (!m_Initialized)
  {
  // perform initialization for all the threads
 
  // set flag so other threads will not initialize
  m_Initialized = true;
  }
m_Lock.UnLock();

The tricky part here is resetting m_Initialized after the filter finishes executing.  But you could
use a similar locking mechanism.

This methodology can still be used but it does complicate the ThreadedGenerateData() methods.  The
BeforeThreadedGenerateData()/AfterThreadedGenerateData() methods should allow you to do most of the
same operations but without the complexity of setting up and releasing mutex locks.




-----Original Message-----
From: Lydia Ng [ mailto:lng@insightful.com <mailto:lng@insightful.com> ]
Sent: Monday, September 24, 2001 11:21 PM
To: Miller, James V (CRD)
Subject: multi-thread filter


Hi Jim,

Wonder if I could bounce an idea at you?

In our multi-threading filter implementation, I see
the need for initializing function (evoked before
ImageSource::GenerateData() ) which allows one to set
the state of a filter which otherwise can not be done
in a thread safe manner.

For example, the interpolation function caches some
information about the input image buffer size during
SetInputImage().

So I can't connect the input image to the interpolator
until the buffer size is valid.

In a single-threaded situation I would connect
the function at the beginning of GenerateData()

Since SetInputImage() is not thread-safe it
would be risky to do it in ThreadedGenerateData().

Besides if I wanted to use the same interpolator function
for all the threads (which is okay since Evaluate() is
thread-safe), evoking SetInputImage() in ThreadedGenerateData()
would be highly redundant.

Any thoughts on the idea of some Initialize method for
multi-threaded filters?

Thanks,
Lydia







------_=_NextPart_001_01C145DE.480751A0
Content-Type: text/html;
	charset="iso-8859-1"

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE></TITLE>

<META content="MSHTML 5.50.4616.200" name=GENERATOR></HEAD>
<BODY>
<P><FONT size=2>Lydia had an issue with multithreading some of her 
filters.&nbsp; She needed to perform some filter initialization prior to having 
the threads spawned. Here original message is below.</FONT></P>
<P><FONT size=2>To address this, I modified the pipeline execution model so that 
the default implementation of GenerateData() inherited from ImageSource performs 
the following steps:</FONT></P>
<P><FONT color=#0000ff size=2>1) Allocate the output buffer<BR>2) Call 
BeforeThreadedGenerateData()<BR>3) Spawn threads, calling ThreadedGenerateData() 
in each thread.<BR>4) Call AfterThreadedGenerateData()</FONT></P>
<P><FONT color=#0000ff size=2>This added two new methods: 
ImageSource::BeforeThreadedGenerateData() and 
ImageSource::AfterThreadedGenerateData().&nbsp; These methods are called in the 
main processing thread before/after the threaded computation is performed.&nbsp; 
You can use these methods to perform setup or breakdown operations. A setup 
operation might initialize member ivars so that they are ready for all the 
threads to use (be careful that their use by each thread is done in a thread 
safe manner).&nbsp; A breakdown operation might merge or summarize information 
calculated by threads.</FONT></P>
<DIV><FONT color=#0000ff size=2>These methods are a convenience operation and do 
not have to be used.&nbsp; They only apply to the ThreadedGenerateData() 
case.&nbsp; There is no corresponding BeforeGenerateData(), AfterGenerateData() 
pair since those operations could simply be put in the GenerateData() method of 
a single threaded filter.</DIV>
<P>There is another way this could have been done (and can still be done) which 
is to use a MutexLock inside the ThreadedGenerateData() method to synchronize 
the threads. </FONT><FONT size=2>You would use a mutex lock around the 
initialization code.&nbsp; The first thread to get inside the lock would perform 
all the initialization and then set an ivar to indicate that everything was 
initialized.&nbsp; Then it would release the lock.&nbsp; The other threads would 
each grab the lock, see that everything was initialized and release the 
lock.<BR><BR>The filter would have an ivar of type SimpleFastMutexLock m_Lock 
and an ivar m_Initialized. The ThreadedGenerateData() method would then have 
code that looks like<BR><BR>m_Lock.Lock();<BR>if (!m_Initialized)<BR>&nbsp; 
{<BR>&nbsp; // perform initialization for all the threads<BR>&nbsp;<BR>&nbsp; // 
set flag so other threads will not initialize<BR>&nbsp; m_Initialized = 
true;<BR>&nbsp; }<BR>m_Lock.UnLock();<BR><BR>The tricky part here is resetting 
m_Initialized after the filter finishes executing.&nbsp; But you could use a 
similar locking mechanism.</FONT></P>
<DIV><FONT size=2><FONT color=#0000ff>This methodology can still be used but it 
does complicate the ThreadedGenerateData() methods.&nbsp; The 
BeforeThreadedGenerateData()/AfterThreadedGenerateData() methods should allow 
you to do most of the same operations but without the complexity of setting up 
and releasing mutex locks.</FONT></DIV>
<P><BR><BR></FONT><FONT size=2><BR>-----Original Message-----<BR>From: Lydia Ng 
[<A href="mailto:lng@insightful.com">mailto:lng@insightful.com</A>]<BR>Sent: 
Monday, September 24, 2001 11:21 PM<BR>To: Miller, James V (CRD)<BR>Subject: 
multi-thread filter<BR><BR><BR>Hi Jim,<BR><BR>Wonder if I could bounce an idea 
at you?<BR><BR>In our multi-threading filter implementation, I see<BR>the need 
for initializing function (evoked before<BR>ImageSource::GenerateData() ) which 
allows one to set<BR>the state of a filter which otherwise can not be done<BR>in 
a thread safe manner.<BR><BR>For example, the interpolation function caches 
some<BR>information about the input image buffer size 
during<BR>SetInputImage().<BR><BR>So I can't connect the input image to the 
interpolator<BR>until the buffer size is valid.<BR><BR>In a single-threaded 
situation I would connect<BR>the function at the beginning of 
GenerateData()<BR><BR>Since SetInputImage() is not thread-safe it<BR>would be 
risky to do it in ThreadedGenerateData().<BR><BR>Besides if I wanted to use the 
same interpolator function<BR>for all the threads (which is okay since 
Evaluate() is<BR>thread-safe), evoking SetInputImage() in 
ThreadedGenerateData()<BR>would be highly redundant.<BR><BR>Any thoughts on the 
idea of some Initialize method for<BR>multi-threaded 
filters?<BR><BR>Thanks,<BR>Lydia<BR><BR><BR><BR><BR></P></FONT></BODY></HTML>

------_=_NextPart_001_01C145DE.480751A0--