Skip to content

Commit

Permalink
PERF: Speed up full, grid, sparse mask samplers by a local sampleVector
Browse files Browse the repository at this point in the history
Did speed up `ImageFullSampler`, `ImageGridSampler`, and `ImageRandomSamplerSparseMask` by doing the `push_back`'s of samples to a local `std::vector` of samples (instead of directly to the sample container), and then eventually swapping the vector "into" the sample container.

When using `ImageFullSampler` on a 4096 x 4096 input image, a `sampler.Update()` call originally took more than 0.38 seconds, but it went down to almost 0.20 seconds with this commit, as observed using Visual C++ 2019 (Release configuration).
  • Loading branch information
N-Dekker committed Sep 13, 2023
1 parent 5e054ee commit 4d028f7
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 16 deletions.
30 changes: 21 additions & 9 deletions Common/ImageSamplers/itkImageFullSampler.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ ImageFullSampler<TInputImage>::GenerateData()
typename ImageSampleContainerType::Pointer sampleContainer = this->GetOutput();
typename MaskType::ConstPointer mask = this->GetMask();

/** Clear the container. */
sampleContainer->clear();
// Take capacity from the output container, and clear it.
std::vector<ImageSampleType> sampleVector;
sampleContainer->swap(sampleVector);
sampleVector.clear();

const auto croppedInputImageRegion = this->GetCroppedInputImageRegion();

Expand All @@ -61,7 +63,7 @@ ImageFullSampler<TInputImage>::GenerateData()
*/
try
{
sampleContainer->reserve(croppedInputImageRegion.GetNumberOfPixels());
sampleVector.reserve(croppedInputImageRegion.GetNumberOfPixels());
}
catch (const std::exception & excp)
{
Expand Down Expand Up @@ -90,7 +92,7 @@ ImageFullSampler<TInputImage>::GenerateData()
tempSample.m_ImageValue = iter.Get();

/** Store in container */
sampleContainer->push_back(tempSample);
sampleVector.push_back(tempSample);

} // end for
} // end if no mask
Expand All @@ -115,12 +117,15 @@ ImageFullSampler<TInputImage>::GenerateData()
tempSample.m_ImageValue = iter.Get();

/** Store in container. */
sampleContainer->push_back(tempSample);
sampleVector.push_back(tempSample);

} // end if
} // end for
} // end else (if mask exists)

// Move the samples from the vector into the output container.
sampleContainer->swap(sampleVector);

} // end GenerateData()


Expand All @@ -139,6 +144,11 @@ ImageFullSampler<TInputImage>::ThreadedGenerateData(const InputImageRegionType &
ImageSampleContainerPointer & sampleContainerThisThread // & ???
= this->m_ThreaderSampleContainer[threadId];

// Take capacity from the container of this thread, and clear it.
std::vector<ImageSampleType> sampleVector;
sampleContainerThisThread->swap(sampleVector);
sampleVector.clear();

/** Set up a region iterator within the user specified image region. */
using InputImageIterator = ImageRegionConstIteratorWithIndex<InputImageType>;
// InputImageIterator iter( inputImage, this->GetCroppedInputImageRegion() );
Expand All @@ -152,8 +162,7 @@ ImageFullSampler<TInputImage>::ThreadedGenerateData(const InputImageRegionType &
*/
try
{
sampleContainerThisThread->clear();
sampleContainerThisThread->reserve(chunkSize);
sampleVector.reserve(chunkSize);
}
catch (const std::exception & excp)
{
Expand Down Expand Up @@ -182,7 +191,7 @@ ImageFullSampler<TInputImage>::ThreadedGenerateData(const InputImageRegionType &
tempSample.m_ImageValue = iter.Get();

/** Store in container. */
sampleContainerThisThread->push_back(tempSample);
sampleVector.push_back(tempSample);

} // end for
} // end if no mask
Expand All @@ -207,12 +216,15 @@ ImageFullSampler<TInputImage>::ThreadedGenerateData(const InputImageRegionType &
tempSample.m_ImageValue = iter.Get();

/** Store in container. */
sampleContainerThisThread->push_back(tempSample);
sampleVector.push_back(tempSample);

} // end if
} // end for
} // end else (if mask exists)

// Move the samples from the vector into the container for this thread.
sampleContainerThisThread->swap(sampleVector);

} // end ThreadedGenerateData()


Expand Down
13 changes: 9 additions & 4 deletions Common/ImageSamplers/itkImageGridSampler.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ ImageGridSampler<TInputImage>::GenerateData()
typename ImageSampleContainerType::Pointer sampleContainer = this->GetOutput();
typename MaskType::ConstPointer mask = this->GetMask();

/** Clear the container. */
sampleContainer->Initialize();
// Take capacity from the output container, and clear it.
std::vector<ImageSampleType> sampleVector;
sampleContainer->swap(sampleVector);
sampleVector.clear();

/** Take into account the possibility of a smaller bounding box around the mask */
this->SetNumberOfSamples(this->m_RequestedNumberOfSamples);
Expand Down Expand Up @@ -120,7 +122,7 @@ ImageGridSampler<TInputImage>::GenerateData()
index[0] += this->m_SampleGridSpacing[0];

// Store sample in container.
sampleContainer->push_back(tempSample);
sampleVector.push_back(tempSample);

} // end x
index[0] = sampleGridIndex[0];
Expand Down Expand Up @@ -165,7 +167,7 @@ ImageGridSampler<TInputImage>::GenerateData()
tempSample.m_ImageValue = inputImage->GetPixel(index);

// Store sample in container.
sampleContainer->push_back(tempSample);
sampleVector.push_back(tempSample);

} // end if in mask
// Jump to next position on grid
Expand All @@ -190,6 +192,9 @@ ImageGridSampler<TInputImage>::GenerateData()
} // end t
} // else (if mask exists)

// Move the samples from the vector into the output container.
sampleContainer->swap(sampleVector);

} // end GenerateData()


Expand Down
11 changes: 8 additions & 3 deletions Common/ImageSamplers/itkImageRandomSamplerSparseMask.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ ImageRandomSamplerSparseMask<TInputImage>::GenerateData()
InputImageConstPointer inputImage = this->GetInput();
ImageSampleContainerPointer sampleContainer = this->GetOutput();

/** Clear the container. */
sampleContainer->Initialize();
// Take capacity from the output container, and clear it.
std::vector<ImageSampleType> sampleVector;
sampleContainer->swap(sampleVector);
sampleVector.clear();

/** Make sure the internal full sampler is up-to-date. */
this->m_InternalFullSampler->SetInput(inputImage);
Expand Down Expand Up @@ -92,9 +94,12 @@ ImageRandomSamplerSparseMask<TInputImage>::GenerateData()
for (unsigned int i = 0; i < this->GetNumberOfSamples(); ++i)
{
unsigned long randomIndex = this->m_RandomGenerator->GetIntegerVariate(numberOfValidSamples - 1);
sampleContainer->push_back(allValidSamples->ElementAt(randomIndex));
sampleVector.push_back(allValidSamples->ElementAt(randomIndex));
}

// Move the samples from the vector into the output container.
sampleContainer->swap(sampleVector);

} // end GenerateData()


Expand Down

0 comments on commit 4d028f7

Please sign in to comment.