[ITK Community] Memory leak when using GPUDemonsRegistrationFilter repeatedly

Skornitzke, Stephan Stephan.Skornitzke at med.uni-heidelberg.de
Fri Nov 8 06:15:57 EST 2013


Hello everyone,

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.
Using nvidia-smi confirms that more and more GPU memory is allocated with each run.
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.

I was able to reproduce this error with the following code (mainly copied from the example):
#include "itkGPUDemonsRegistrationFilter.h"
#include "itkHistogramMatchingImageFilter.h"
#include "itkCastImageFilter.h"
#include "itkWarpImageFilter.h"
#include "itkLinearInterpolateImageFunction.h"

#include "itkImportImageFilter.h"
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
#include "itkCommand.h"
#include "itkSmartPointer.h"
#include "itkTimeProbe.h"

#include "itkGPUImage.h"
#include "itkGPUKernelManager.h"
#include "itkGPUContextManager.h"
#include "itkGPUDemonsRegistrationFilter.h"

void DIF(){
                bool debug = false;

                //Fill some arrays with bogus
                const unsigned int Dimension = 3;
                typedef float PixelType;
                unsigned int width = 100;
                unsigned int height = 100;
                unsigned int slices = 10;
                unsigned int nump = width * height * slices;
                PixelType *FixedImageArray = new PixelType[nump];
                PixelType *MovingImageArray = new PixelType[nump];
                for (unsigned int i = 0; i < nump;++i){
                                FixedImageArray[i] = i % 5;
                                MovingImageArray[i] = i % 6;
                }


                //Import those arrays as images
                typedef itk::Image< PixelType, Dimension >  FixedImageType;
                typedef itk::Image< PixelType, Dimension >  MovingImageType;

                typedef itk::ImportImageFilter<PixelType, Dimension> FixedImportFilterType;
                typedef itk::ImportImageFilter<PixelType, Dimension> MovingImportFilterType;

                FixedImportFilterType::Pointer FixedImportFilter = FixedImportFilterType::New();
                if (debug) FixedImportFilter->DebugOn();
                MovingImportFilterType::Pointer MovingImportFilter = MovingImportFilterType::New();
                if (debug) MovingImportFilter->DebugOn();

                FixedImportFilterType::IndexType start;
                start[0] = 0;
                start[1] = 0;
                start[2] = 0;
                FixedImportFilterType::SizeType size;
                size[0] = width;
                size[1] = height;
                size[2] = slices;
                FixedImportFilterType::RegionType region;
                region.SetSize(size);
                region.SetIndex(start);
                FixedImportFilter->SetRegion(region);
                double origin[3];
                origin[0] = 0.0;
                origin[1] = 0.0;
                origin[2] = 0.0;
                FixedImportFilter->SetOrigin(origin);
                double spacing[3];
                spacing[0] = 1;
                spacing[1] = 1;
                spacing[2] = 1;
                FixedImportFilter->SetSpacing(spacing);

                MovingImportFilter->SetRegion(region);
                MovingImportFilter->SetOrigin(origin);
                MovingImportFilter->SetSpacing(spacing);

                FixedImportFilter->SetImportPointer(FixedImageArray, width * height * slices, true);
                MovingImportFilter->SetImportPointer(MovingImageArray, width * height * slices, true);

                FixedImageType::Pointer FixedImage = FixedImportFilter->GetOutput();
                if (debug) FixedImage->DebugOn();
                MovingImageType::Pointer MovingImage = MovingImportFilter->GetOutput();
                if (debug) MovingImage->DebugOn();


                //convert to GPUImages
                typedef float                                      InternalPixelType;
                typedef itk::GPUImage< InternalPixelType, Dimension > InternalImageType;
                typedef itk::CastImageFilter< FixedImageType,
                                                InternalImageType >  FixedImageCasterType;
                typedef itk::CastImageFilter< MovingImageType,
                                                InternalImageType >  MovingImageCasterType;

                FixedImageCasterType::Pointer fixedImageCaster   = FixedImageCasterType::New();
                if (debug) fixedImageCaster->DebugOn();
                MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New();
                if (debug) movingImageCaster->DebugOn();

                fixedImageCaster->SetInput(FixedImportFilter->GetOutput());
                movingImageCaster->SetInput(MovingImportFilter->GetOutput());

                InternalImageType::Pointer GPUFixedImage = fixedImageCaster->GetOutput();
                if (debug) GPUFixedImage->DebugOn();

                InternalImageType::Pointer GPUMovingImage = movingImageCaster->GetOutput();
                if (debug) GPUMovingImage->DebugOn();

                GPUFixedImage->Update();
                GPUMovingImage->Update();

                //Perform GPU Demons Registration
                typedef itk::Vector< float, Dimension >             VectorPixelType;
                typedef itk::GPUImage<  VectorPixelType, Dimension >   DeformationFieldType;
                typedef itk::GPUDemonsRegistrationFilter<
                                                InternalImageType,
                                                InternalImageType,
                                                DeformationFieldType> RegistrationFilterType;

                RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
                if (debug) filter->DebugOn();

                filter->SetFixedImage( GPUFixedImage );
                filter->SetMovingImage( GPUMovingImage );

                filter->SetNumberOfIterations( 1 );
                filter->SetStandardDeviations( 1.0 );

                filter->Update();
}

int main(int argc, char **argv){
                unsigned int numiter = 100000;
                for (unsigned int i = 0; i < numiter; ++i){
                                DIF();
                                std::cout << "ITERATION: " << i << std::endl;
                }
}

I am using a GeForce GTS 450 with driver version 319.37 under OpenSUSE 12.2 with ITK 4.4.2.

Thank you for your help.
Kind regards,

Stephan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/community/attachments/20131108/f6ad34b2/attachment.html>


More information about the Community mailing list