[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