[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(). 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.</FONT></SPAN></DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>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). </FONT></SPAN></DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2></FONT></SPAN> </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. 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> </DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>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.</FONT></SPAN></DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2></FONT></SPAN> </DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2> for( unsigned int i = 0;
i<ImageDimension-1; i++ )<BR> {<BR>
m_SmoothingFilters[ i ] = GaussianFilterType::New();<BR>
m_SmoothingFilters[ i ]->SetOrder( GaussianFilterType::ZeroOrder
);<BR> m_SmoothingFilters[ i ]->SetNormalizeAcrossScale(
m_NormalizeAcrossScale );<BR> m_SmoothingFilters[ i
]->AddObserver( ProgressEvent(), m_ProgressCommand );<BR>
m_SmoothingFilters[ i ]->ReleaseDataFlagOn();<BR> }</FONT></SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2> m_DerivativeFilter =
DerivativeFilterType::New();<BR> m_DerivativeFilter->SetOrder(
DerivativeFilterType::SecondOrder );<BR>
m_DerivativeFilter->SetNormalizeAcrossScale( m_NormalizeAcrossScale
);<BR> m_DerivativeFilter->AddObserver( ProgressEvent(),
m_ProgressCommand );</FONT></SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>
m_DerivativeFilter->SetInput( this->GetInput() );</FONT></SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2>
m_SmoothingFilters[0]->SetInput( m_DerivativeFilter->GetOutput()
);</FONT></SPAN></DIV>
<DIV> </DIV>
<DIV><SPAN class=368072316-18032003><FONT size=2> for( unsigned int i = 1;
i<ImageDimension-1; i++ )<BR> {<BR>
m_SmoothingFilters[ i ]->SetInput(
<BR>
m_SmoothingFilters[i-1]->GetOutput() );<BR> }<BR></FONT></SPAN></DIV>
<DIV class=Section1>
<P class=MsoNormal> <?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 &
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> <o:p></o:p></P></DIV>
<DIV> </DIV></BODY></HTML>
------_=_NextPart_001_01C2ED6D.42F42570--