[Insight-developers] mini-pipelines and using ReleaseDataFlagOn()

Miller, James V (Research) millerjv@crd.ge.com
Tue, 18 Mar 2003 11:41:45 -0500


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_01C2ED6D.42F42570
Content-Type: text/plain;
	charset="iso-8859-1"

I just wanted to remind people that ITK filters support a method called
ReleaseDataFlagOn().  This flag is usually set by an application developer
to manage the memory footprint of an ITK pipeline.  When the flag is on, the
pipeline will deallocate the bulk data for its input once the filter has
executed.  This can free up the block of memory that the OS can assign as
the bulk data to the output a filter later downstream.  If you have a
pipeline with many branches or an application where the user can change the
parameters on filters in the pipeline, you might want to leave the flag off
(which is the default) to avoid filters having to re-execute.  But if memory
footprint is an issue for your application, you can turn it on for each
filter and pay the penalty of "deeper" pipeline re-executions.
 
The ReleaseDataFlag is also useful when a filter is implemented as a
mini-pipeline.  Here, the filter writer manages the ReleaseDataFlag as
opposed to the application writer (though the application writer can still
set the flag on the filter to control the release of the filter's input).  
 
If a filter constructs a mini-pipeline that is longer than one filter, then
the filter should probably set the ReleaseDataFlag on all the sub-filters
but the first.  This will keep the memory usage of the mini-pipeline to a
minimum. You usually do not set the ReleaseDataFlag on the first filter of
the mini-pipeline since it shares the input with the "parent" filter and the
application writer has the control over whether that input should be
released.
 
Here is a snippet from the LaplacianRecursiveGaussianImageFilter.  This
filter uses a mini-pipeline of RecursiveGaussianImageFilters to compute the
sum of the second directional derivatives. The mini-pipeline consists of
ImageDimension filters cascaded together.  The first filter
(m_DerivativeFilter), gets the input of the parent filter.  The remaining
filters (m_SmoothingFilters[]) are cascaded together with the input of the
first smoothing filter being the output of the derivative filter.  So here,
the smoothing filters are set to release their inputs (using
ReleaseDataFlagOn()) while the derivative filter (the first filter in the
mini-pipeline) is left unchanged.  Its input is the input to the "parent"
filter so the normal pipeline mechanism will release its input under the
control of the application programmer.  Managing the release data flag on
this mini-pipeline saves ImageDimension-1 copies of the data.
 
  for( unsigned int i = 0; i<ImageDimension-1; i++ )
  {
    m_SmoothingFilters[ i ] = GaussianFilterType::New();
    m_SmoothingFilters[ i ]->SetOrder( GaussianFilterType::ZeroOrder );
    m_SmoothingFilters[ i ]->SetNormalizeAcrossScale( m_NormalizeAcrossScale
);
    m_SmoothingFilters[ i ]->AddObserver( ProgressEvent(), m_ProgressCommand
);
    m_SmoothingFilters[ i ]->ReleaseDataFlagOn();
  }
 
  m_DerivativeFilter = DerivativeFilterType::New();
  m_DerivativeFilter->SetOrder( DerivativeFilterType::SecondOrder );
  m_DerivativeFilter->SetNormalizeAcrossScale( m_NormalizeAcrossScale );
  m_DerivativeFilter->AddObserver( ProgressEvent(), m_ProgressCommand );
 
  m_DerivativeFilter->SetInput( this->GetInput() );
 
  m_SmoothingFilters[0]->SetInput( m_DerivativeFilter->GetOutput() );
 
  for( unsigned int i = 1; i<ImageDimension-1; i++ )
  {
    m_SmoothingFilters[ i ]->SetInput( 
                              m_SmoothingFilters[i-1]->GetOutput() );
  }


 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office"
/>

Jim Miller 
_____________________________________
Visualization & Computer Vision
GE Research
Bldg. KW, Room C218B
P.O. Box 8, Schenectady NY 12301

millerjv@research.ge.com <mailto:millerjv@research.ge.com> 

james.miller@research.ge.com
(518) 387-4005, Dial Comm: 8*833-4005, 
Cell: (518) 505-7065, Fax: (518) 387-6981 

 

 

------_=_NextPart_001_01C2ED6D.42F42570
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">


<META content="MSHTML 6.00.2715.400" name=GENERATOR></HEAD>
<BODY>
<DIV><SPAN class=368072316-18032003><FONT size=2>I just wanted to remind people 
that ITK filters support a method called ReleaseDataFlagOn().&nbsp; This flag is 
usually set by an application developer to manage the memory footprint of an ITK 
pipeline.&nbsp; When the flag is on, the pipeline will deallocate the bulk data 
for its input once the filter has executed.&nbsp; This can free up the block of 
memory that the OS can assign as the bulk data to the output a filter later 
downstream.&nbsp; If you have a pipeline with many branches or an application 
where the user can change the parameters on filters in the pipeline, you might 
want to leave the flag off (which is the default) to avoid filters having to 
re-execute.&nbsp; But if memory footprint is an issue for your application, you 
can turn it on for each filter and pay the penalty of "deeper" pipeline 
re-executions.</FONT></SPAN></DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>The ReleaseDataFlag is also 
useful when a filter is implemented as a mini-pipeline.&nbsp; Here, the filter 
writer manages the ReleaseDataFlag as opposed to the application writer (though 
the application writer can still set the flag on the filter to control the 
release of the filter's input).&nbsp; </FONT></SPAN></DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>If a filter constructs a 
mini-pipeline that is longer than one filter, then the filter should probably 
set the ReleaseDataFlag on all the sub-filters but the first.&nbsp; This will 
keep the memory usage of the mini-pipeline to a minimum. You usually do not set 
the ReleaseDataFlag on the first filter of the mini-pipeline since it shares the 
input with the "parent" filter and the application writer has the control over 
whether that input should be released.</FONT></SPAN></DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>Here is a snippet from the 
LaplacianRecursiveGaussianImageFilter.&nbsp; This filter uses a mini-pipeline of 
RecursiveGaussianImageFilters to compute the sum of the second directional 
derivatives. The mini-pipeline consists of ImageDimension filters cascaded 
together.&nbsp; The first filter (m_DerivativeFilter), gets the input of the 
parent filter.&nbsp; The remaining filters (m_SmoothingFilters[]) are cascaded 
together with the input of the first smoothing filter being the output of the 
derivative filter.&nbsp; So here, the smoothing filters are set to release their 
inputs (using ReleaseDataFlagOn()) while the derivative filter (the first filter 
in the mini-pipeline) is left unchanged.&nbsp; Its input is the input to the 
"parent" filter so the normal pipeline mechanism will release its input under 
the control of the application programmer.&nbsp; Managing the release data flag 
on this mini-pipeline saves ImageDimension-1 copies of the 
data.</FONT></SPAN></DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2></FONT></SPAN>&nbsp;</DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>&nbsp; for( unsigned int i = 0; 
i&lt;ImageDimension-1; i++ )<BR>&nbsp; {<BR>&nbsp;&nbsp;&nbsp; 
m_SmoothingFilters[ i ] = GaussianFilterType::New();<BR>&nbsp;&nbsp;&nbsp; 
m_SmoothingFilters[ i ]-&gt;SetOrder( GaussianFilterType::ZeroOrder 
);<BR>&nbsp;&nbsp;&nbsp; m_SmoothingFilters[ i ]-&gt;SetNormalizeAcrossScale( 
m_NormalizeAcrossScale );<BR>&nbsp;&nbsp;&nbsp; m_SmoothingFilters[ i 
]-&gt;AddObserver( ProgressEvent(), m_ProgressCommand );<BR>&nbsp;&nbsp;&nbsp; 
m_SmoothingFilters[ i ]-&gt;ReleaseDataFlagOn();<BR>&nbsp; }</FONT></SPAN></DIV>
<DIV>&nbsp;</DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>&nbsp; m_DerivativeFilter = 
DerivativeFilterType::New();<BR>&nbsp; m_DerivativeFilter-&gt;SetOrder( 
DerivativeFilterType::SecondOrder );<BR>&nbsp; 
m_DerivativeFilter-&gt;SetNormalizeAcrossScale( m_NormalizeAcrossScale 
);<BR>&nbsp; m_DerivativeFilter-&gt;AddObserver( ProgressEvent(), 
m_ProgressCommand );</FONT></SPAN></DIV>
<DIV>&nbsp;</DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>&nbsp; 
m_DerivativeFilter-&gt;SetInput( this-&gt;GetInput() );</FONT></SPAN></DIV>
<DIV>&nbsp;</DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>&nbsp; 
m_SmoothingFilters[0]-&gt;SetInput( m_DerivativeFilter-&gt;GetOutput() 
);</FONT></SPAN></DIV>
<DIV>&nbsp;</DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>&nbsp; for( unsigned int i = 1; 
i&lt;ImageDimension-1; i++ )<BR>&nbsp; {<BR>&nbsp;&nbsp;&nbsp; 
m_SmoothingFilters[ i ]-&gt;SetInput( 
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
m_SmoothingFilters[i-1]-&gt;GetOutput() );<BR>&nbsp; }<BR></FONT></SPAN></DIV>
<DIV class=Section1>
<P class=MsoNormal>&nbsp;<?xml:namespace prefix = o ns = 
"urn:schemas-microsoft-com:office:office" /><o:p></o:p></P>
<P style="MARGIN: 0in 0in 0pt"><B><SPAN 
style="COLOR: navy; FONT-FAMILY: 'Comic Sans MS'">Jim Miller</SPAN></B> 
<BR><B><I><SPAN 
style="FONT-SIZE: 10pt; COLOR: red; FONT-FAMILY: Arial">_____________________________________</SPAN></I></B><BR><EM><SPAN 
style="FONT-SIZE: 7.5pt; COLOR: black; FONT-FAMILY: Arial">Visualization &amp; 
Computer Vision</SPAN></EM><I><SPAN 
style="FONT-SIZE: 7.5pt; COLOR: black; FONT-FAMILY: Arial"><BR><EM>GE 
Research</EM><BR><EM>Bldg. KW, Room C218B</EM><BR><EM>P.O. Box 8, Schenectady NY 
12301</EM><BR><BR></SPAN></I><EM><U><SPAN 
style="FONT-SIZE: 7.5pt; COLOR: blue"><A 
href="mailto:millerjv@research.ge.com">millerjv@research.ge.com</A></SPAN></U></EM></P>
<P style="MARGIN: 0in 0in 0pt"><EM><U><SPAN 
style="FONT-SIZE: 7.5pt; COLOR: blue">james.miller@research.ge.com</SPAN></U></EM><BR><I><SPAN 
style="FONT-SIZE: 7.5pt; COLOR: black; FONT-FAMILY: Arial">(518) 387-4005, Dial 
Comm: 8*833-4005, </SPAN></I><BR><I><SPAN 
style="FONT-SIZE: 7.5pt; COLOR: black; FONT-FAMILY: Arial">Cell: (518) 505-7065, 
Fax: (518) 387-6981</SPAN></I> </P>
<P class=MsoNormal>&nbsp;<o:p></o:p></P></DIV>
<DIV>&nbsp;</DIV></BODY></HTML>

------_=_NextPart_001_01C2ED6D.42F42570--