<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        margin-bottom:.0001pt;
        font-size:11.0pt;
        font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
        {mso-style-priority:99;
        color:purple;
        text-decoration:underline;}
span.E-MailFormatvorlage17
        {mso-style-type:personal-compose;
        font-family:"Calibri","sans-serif";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri","sans-serif";}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal">Hello everyone,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I tried to use the GPUDemonsRegistrationFilter for image registration, but experienced some problems when trying to perform multiple registrations in a row. As far as I can tell, there seems to be a memory leak caused by the registration.
 After a few registrations, depending on the image size, I get an OpenCL Error : CL_MEM_OBJECT_ALLOCATION_FAILURE.<o:p></o:p></p>
<p class="MsoNormal">Using nvidia-smi confirms that more and more GPU memory is allocated with each run.<o:p></o:p></p>
<p class="MsoNormal">Using the ITK debug output, I noticed that the GPUImages aren’t destroyed at the end of the function, because they still have a reference count, while all the other objects are destroyed.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I was able to reproduce this error with the following code (mainly copied from the example):<o:p></o:p></p>
<p class="MsoNormal">#include "itkGPUDemonsRegistrationFilter.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkHistogramMatchingImageFilter.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkCastImageFilter.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkWarpImageFilter.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkLinearInterpolateImageFunction.h"<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#include "itkImportImageFilter.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkImageFileReader.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkImageFileWriter.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkCommand.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkSmartPointer.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkTimeProbe.h"<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">#include "itkGPUImage.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkGPUKernelManager.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkGPUContextManager.h"<o:p></o:p></p>
<p class="MsoNormal">#include "itkGPUDemonsRegistrationFilter.h"<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">void DIF(){<o:p></o:p></p>
<p class="MsoNormal">                bool debug = false;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                //Fill some arrays with bogus<o:p></o:p></p>
<p class="MsoNormal">                const unsigned int Dimension = 3;<o:p></o:p></p>
<p class="MsoNormal">                typedef float PixelType;<o:p></o:p></p>
<p class="MsoNormal">                unsigned int width = 100;<o:p></o:p></p>
<p class="MsoNormal">                unsigned int height = 100;<o:p></o:p></p>
<p class="MsoNormal">                unsigned int slices = 10;<o:p></o:p></p>
<p class="MsoNormal">                unsigned int nump = width * height * slices;<o:p></o:p></p>
<p class="MsoNormal">                PixelType *FixedImageArray = new PixelType[nump];<o:p></o:p></p>
<p class="MsoNormal">                PixelType *MovingImageArray = new PixelType[nump];<o:p></o:p></p>
<p class="MsoNormal">                for (unsigned int i = 0; i < nump;++i){<o:p></o:p></p>
<p class="MsoNormal">                                FixedImageArray[i] = i % 5;<o:p></o:p></p>
<p class="MsoNormal">                                MovingImageArray[i] = i % 6;<o:p></o:p></p>
<p class="MsoNormal">                }<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                //Import those arrays as images<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::Image< PixelType, Dimension >  FixedImageType;<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::Image< PixelType, Dimension >  MovingImageType;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                typedef itk::ImportImageFilter<PixelType, Dimension> FixedImportFilterType;<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::ImportImageFilter<PixelType, Dimension> MovingImportFilterType;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                FixedImportFilterType::Pointer FixedImportFilter = FixedImportFilterType::New();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) FixedImportFilter->DebugOn();<o:p></o:p></p>
<p class="MsoNormal">                MovingImportFilterType::Pointer MovingImportFilter = MovingImportFilterType::New();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) MovingImportFilter->DebugOn();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                FixedImportFilterType::IndexType start;<o:p></o:p></p>
<p class="MsoNormal">                start[0] = 0;<o:p></o:p></p>
<p class="MsoNormal">                start[1] = 0;<o:p></o:p></p>
<p class="MsoNormal">                start[2] = 0;<o:p></o:p></p>
<p class="MsoNormal">                FixedImportFilterType::SizeType size;<o:p></o:p></p>
<p class="MsoNormal">                size[0] = width;<o:p></o:p></p>
<p class="MsoNormal">                size[1] = height;<o:p></o:p></p>
<p class="MsoNormal">                size[2] = slices;<o:p></o:p></p>
<p class="MsoNormal">                FixedImportFilterType::RegionType region;<o:p></o:p></p>
<p class="MsoNormal">                region.SetSize(size);<o:p></o:p></p>
<p class="MsoNormal">                region.SetIndex(start);<o:p></o:p></p>
<p class="MsoNormal">                FixedImportFilter->SetRegion(region);<o:p></o:p></p>
<p class="MsoNormal">                double origin[3];<o:p></o:p></p>
<p class="MsoNormal">                origin[0] = 0.0;<o:p></o:p></p>
<p class="MsoNormal">                origin[1] = 0.0;<o:p></o:p></p>
<p class="MsoNormal">                origin[2] = 0.0;<o:p></o:p></p>
<p class="MsoNormal">                FixedImportFilter->SetOrigin(origin);<o:p></o:p></p>
<p class="MsoNormal">                double spacing[3];<o:p></o:p></p>
<p class="MsoNormal">                spacing[0] = 1;<o:p></o:p></p>
<p class="MsoNormal">                spacing[1] = 1;<o:p></o:p></p>
<p class="MsoNormal">                spacing[2] = 1;<o:p></o:p></p>
<p class="MsoNormal">                FixedImportFilter->SetSpacing(spacing);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                MovingImportFilter->SetRegion(region);<o:p></o:p></p>
<p class="MsoNormal">                MovingImportFilter->SetOrigin(origin);<o:p></o:p></p>
<p class="MsoNormal">                MovingImportFilter->SetSpacing(spacing);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                FixedImportFilter->SetImportPointer(FixedImageArray, width * height * slices, true);<o:p></o:p></p>
<p class="MsoNormal">                MovingImportFilter->SetImportPointer(MovingImageArray, width * height * slices, true);<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                FixedImageType::Pointer FixedImage = FixedImportFilter->GetOutput();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) FixedImage->DebugOn();<o:p></o:p></p>
<p class="MsoNormal">                MovingImageType::Pointer MovingImage = MovingImportFilter->GetOutput();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) MovingImage->DebugOn();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                //convert to GPUImages<o:p></o:p></p>
<p class="MsoNormal">                typedef float                                      InternalPixelType;<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::GPUImage< InternalPixelType, Dimension > InternalImageType;<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::CastImageFilter< FixedImageType,<o:p></o:p></p>
<p class="MsoNormal">                                                InternalImageType >  FixedImageCasterType;<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::CastImageFilter< MovingImageType,<o:p></o:p></p>
<p class="MsoNormal">                                                InternalImageType >  MovingImageCasterType;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                FixedImageCasterType::Pointer fixedImageCaster   = FixedImageCasterType::New();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) fixedImageCaster->DebugOn();<o:p></o:p></p>
<p class="MsoNormal">                MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) movingImageCaster->DebugOn();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                fixedImageCaster->SetInput(FixedImportFilter->GetOutput());<o:p></o:p></p>
<p class="MsoNormal">                movingImageCaster->SetInput(MovingImportFilter->GetOutput());<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                InternalImageType::Pointer GPUFixedImage = fixedImageCaster->GetOutput();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) GPUFixedImage->DebugOn();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                InternalImageType::Pointer GPUMovingImage = movingImageCaster->GetOutput();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) GPUMovingImage->DebugOn();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                GPUFixedImage->Update();<o:p></o:p></p>
<p class="MsoNormal">                GPUMovingImage->Update();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                //Perform GPU Demons Registration<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::Vector< float, Dimension >             VectorPixelType;<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::GPUImage<  VectorPixelType, Dimension >   DeformationFieldType;<o:p></o:p></p>
<p class="MsoNormal">                typedef itk::GPUDemonsRegistrationFilter<<o:p></o:p></p>
<p class="MsoNormal">                                                InternalImageType,<o:p></o:p></p>
<p class="MsoNormal">                                                InternalImageType,<o:p></o:p></p>
<p class="MsoNormal">                                                DeformationFieldType> RegistrationFilterType;<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                RegistrationFilterType::Pointer filter = RegistrationFilterType::New();<o:p></o:p></p>
<p class="MsoNormal">                if (debug) filter->DebugOn();<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                filter->SetFixedImage( GPUFixedImage );<o:p></o:p></p>
<p class="MsoNormal">                filter->SetMovingImage( GPUMovingImage );<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                filter->SetNumberOfIterations( 1 );<o:p></o:p></p>
<p class="MsoNormal">                filter->SetStandardDeviations( 1.0 );<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">                filter->Update();<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">int main(int argc, char **argv){<o:p></o:p></p>
<p class="MsoNormal">                unsigned int numiter = 100000;<o:p></o:p></p>
<p class="MsoNormal">                for (unsigned int i = 0; i < numiter; ++i){<o:p></o:p></p>
<p class="MsoNormal">                                DIF();<o:p></o:p></p>
<p class="MsoNormal">                                std::cout << "ITERATION: " << i << std::endl;<o:p></o:p></p>
<p class="MsoNormal">                }<o:p></o:p></p>
<p class="MsoNormal">}<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">I am using a GeForce GTS 450 with driver version 319.37 under OpenSUSE 12.2 with ITK 4.4.2.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thank you for your help.<o:p></o:p></p>
<p class="MsoNormal">Kind regards,<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Stephan<o:p></o:p></p>
</div>
</body>
</html>