Skip to content

Commit

Permalink
Merge pull request #917 from alicevision/dev/featureMemoryEstimation
Browse files Browse the repository at this point in the history
[software] FeatureExtraction: minor update to SIFT memory estimation
  • Loading branch information
fabiencastan authored Oct 14, 2020
2 parents b8e58ad + 7c69caf commit adfaa6d
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 13 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# AliceVision Changelog

## Release 2.3.1 (2020.10.14)

- [software] FeatureExtraction: minor update to SIFT memory estimation [PR](https://github.com/alicevision/AliceVision/pull/917)


## Release 2.3.0 (2020.10.09)

### Release Notes Summary
Expand Down
3 changes: 2 additions & 1 deletion src/aliceVision/feature/sift/ImageDescriber_SIFT_popSIFT.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ class ImageDescriber_SIFT_popSIFT : public ImageDescriber
*/
std::size_t getMemoryConsumption(std::size_t width, std::size_t height) const override
{
return 3 * width * height * sizeof(float); // GPU only
// GPU only
return 4 * width * height * sizeof(float); // only use the input RGBA image
}

/**
Expand Down
11 changes: 7 additions & 4 deletions src/aliceVision/feature/sift/SIFT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ std::size_t getMemoryConsumptionVLFeat(std::size_t width, std::size_t height, co
{
double scaleFactor = 1.0;
if(params._firstOctave > 0)
scaleFactor = 1.0/params._firstOctave;
scaleFactor = 1.0 / std::pow(2.0, params._firstOctave);
else if(params._firstOctave < 0)
scaleFactor = 2.0 * -params._firstOctave;
std::size_t fullImgSize = width * height * scaleFactor * scaleFactor;
scaleFactor = std::pow(2.0, std::abs(params._firstOctave));
const std::size_t fullImgSize = width * height * scaleFactor * scaleFactor;

std::size_t pyramidMemoryConsuption = 0;
double downscale = 1.0;
Expand All @@ -29,7 +29,10 @@ std::size_t getMemoryConsumptionVLFeat(std::size_t width, std::size_t height, co
}
pyramidMemoryConsuption *= params._numScales * sizeof(float);

return 4 * pyramidMemoryConsuption + (3 * width * height * sizeof(float)) + (params._maxTotalKeypoints * 128 * sizeof(float));
const int nbTempPyramids = 4; // Gaussian + DOG + Gradiant + orientation (Note: DOG use 1 layer less, but this is ignored here)
return fullImgSize * 4 * sizeof(float) + // input RGBA image
nbTempPyramids * pyramidMemoryConsuption + // pyramids
(params._maxTotalKeypoints * 128 * sizeof(float)); // output keypoints
}

void VLFeatInstance::initialize()
Expand Down
2 changes: 1 addition & 1 deletion src/aliceVision/multiview/RelativePoseKernel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class RelativePoseKernel_K
, _K1(K1)
, _K2(K2)
{
ALICEVISION_LOG_INFO("RelativePoseKernel_K: x1: " << x1.rows() << "x" << x1.cols() << ", x2: " << x2.rows() << "x" << x2.cols());
ALICEVISION_LOG_TRACE("RelativePoseKernel_K: x1: " << x1.rows() << "x" << x1.cols() << ", x2: " << x2.rows() << "x" << x2.cols());
assert(2 == x1.rows());
assert(x1.rows() == x2.rows());
assert(x1.cols() == x2.cols());
Expand Down
2 changes: 1 addition & 1 deletion src/aliceVision/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#define ALICEVISION_VERSION_MAJOR 2
#define ALICEVISION_VERSION_MINOR 3
#define ALICEVISION_VERSION_REVISION 0
#define ALICEVISION_VERSION_REVISION 1

// Preprocessor to string conversion
#define ALICEVISION_TO_STRING_HELPER(x) #x
Expand Down
39 changes: 33 additions & 6 deletions src/software/pipeline/main_featureExtraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,44 @@ class FeatureExtractor
{
system::MemoryInfo memoryInformation = system::getMemoryInfo();

ALICEVISION_LOG_DEBUG("Job max memory consumption: " << jobMaxMemoryConsuption << " B");
ALICEVISION_LOG_DEBUG("Memory information: " << std::endl <<memoryInformation);
ALICEVISION_LOG_INFO("Job max memory consumption for one image: " << jobMaxMemoryConsuption / (1024*1024) << " MB");
ALICEVISION_LOG_INFO("Memory information: " << std::endl << memoryInformation);

if(jobMaxMemoryConsuption == 0)
throw std::runtime_error("Cannot compute feature extraction job max memory consumption.");

std::size_t nbThreads = (0.9 * memoryInformation.freeRam) / jobMaxMemoryConsuption;
// How many buffers can fit in 90% of the available RAM?
// This is used to estimate how many jobs can be computed in parallel without SWAP.
const std::size_t memoryImageCapacity = std::size_t((0.9 * memoryInformation.freeRam) / jobMaxMemoryConsuption);
std::size_t nbThreads = std::max(std::size_t(1), memoryImageCapacity);
ALICEVISION_LOG_INFO("Max number of threads regarding memory usage: " << nbThreads);
const double oneGB = 1024.0 * 1024.0 * 1024.0;
if(jobMaxMemoryConsuption > memoryInformation.freeRam)
{
ALICEVISION_LOG_WARNING("The amount of RAM available is critical to extract features.");
if(jobMaxMemoryConsuption <= memoryInformation.totalRam)
{
ALICEVISION_LOG_WARNING("But the total amount of RAM is enough to extract features, so you should close other running applications.");
ALICEVISION_LOG_WARNING(" => " << std::size_t(std::round((double(memoryInformation.totalRam - memoryInformation.freeRam) / oneGB)))
<< " GB are used by other applications for a total RAM capacity of "
<< std::size_t(std::round(double(memoryInformation.totalRam) / oneGB)) << " GB.");
}
}
else
{
if(memoryInformation.freeRam < 0.5 * memoryInformation.totalRam)
{
ALICEVISION_LOG_WARNING("More than half of the RAM is used by other applications. It would be more efficient to close them.");
ALICEVISION_LOG_WARNING(" => "
<< std::size_t(std::round(double(memoryInformation.totalRam - memoryInformation.freeRam) / oneGB))
<< " GB are used by other applications for a total RAM capacity of "
<< std::size_t(std::round(double(memoryInformation.totalRam) / oneGB)) << " GB.");
}
}

if(memoryInformation.freeRam == 0)
{
ALICEVISION_LOG_WARNING("Cannot find available system memory, this can be due to OS limitations.\n"
ALICEVISION_LOG_WARNING("Cannot find available system memory, this can be due to OS limitation.\n"
"Use only one thread for CPU feature extraction.");
nbThreads = 1;
}
Expand All @@ -188,10 +215,10 @@ class FeatureExtractor
// nbThreads should not be higher than the core number
nbThreads = std::min(static_cast<std::size_t>(omp_get_num_procs()), nbThreads);

// nbThreads should not be higher than the job number
// nbThreads should not be higher than the number of jobs
nbThreads = std::min(_cpuJobs.size(), nbThreads);

ALICEVISION_LOG_DEBUG("# threads for extraction: " << nbThreads);
ALICEVISION_LOG_INFO("# threads for extraction: " << nbThreads);
omp_set_nested(1);

#pragma omp parallel for num_threads(nbThreads)
Expand Down

0 comments on commit adfaa6d

Please sign in to comment.