Check validity of residual block before removal in RemoveResidualBlock.

- Breaking change: Problem::Options::enable_fast_parameter_block_removal
  is now Problem::Options::enable_fast_removal, as it now controls
  the behaviour for both parameter and residual blocks.

- Previously we did not check that the specified residual block to
  remove in RemoveResidualBlock actually represented a valid residual
  for the problem.
- This meant that Ceres would die unexpectedly if the user passed an
  uninitialised residual_block, or more likely attempted to remove a
  residual block that had already been removed automatically after
  the user removed a parameter block upon on which it was dependent.
- RemoveResidualBlock now verifies the validity of the given
  residual_block to remove.  Either by checking against a hash set of
  all residuals maintained in ProblemImpl iff enable_fast_removal
  is enabled.  Or by a full scan of the residual blocks if not.

Change-Id: I9ab178e2f68a74135f0a8e20905b16405c77a62b
This commit is contained in:
Alex Stewart
2014-03-26 11:36:11 +00:00
parent 74762b6033
commit 195e49351b
5 changed files with 180 additions and 54 deletions
+16 -12
View File
@@ -124,7 +124,7 @@ class Problem {
: cost_function_ownership(TAKE_OWNERSHIP),
loss_function_ownership(TAKE_OWNERSHIP),
local_parameterization_ownership(TAKE_OWNERSHIP),
enable_fast_parameter_block_removal(false),
enable_fast_removal(false),
disable_all_safety_checks(false) {}
// These flags control whether the Problem object owns the cost
@@ -138,17 +138,21 @@ class Problem {
Ownership loss_function_ownership;
Ownership local_parameterization_ownership;
// If true, trades memory for a faster RemoveParameterBlock() operation.
// If true, trades memory for faster RemoveResidualBlock() and
// RemoveParameterBlock() operations.
//
// RemoveParameterBlock() takes time proportional to the size of the entire
// Problem. If you only remove parameter blocks from the Problem
// occassionaly, this may be acceptable. However, if you are modifying the
// Problem frequently, and have memory to spare, then flip this switch to
// By default, RemoveParameterBlock() and RemoveResidualBlock() take time
// proportional to the size of the entire problem. If you only ever remove
// parameters or residuals from the problem occassionally, this might be
// acceptable. However, if you have memory to spare, enable this option to
// make RemoveParameterBlock() take time proportional to the number of
// residual blocks that depend on it. The increase in memory usage is an
// additonal hash set per parameter block containing all the residuals that
// depend on the parameter block.
bool enable_fast_parameter_block_removal;
// residual blocks that depend on it, and RemoveResidualBlock() take (on
// average) constant time.
//
// The increase in memory usage is twofold: an additonal hash set per
// parameter block containing all the residuals that depend on the parameter
// block; and a hash set in the problem containing all residuals.
bool enable_fast_removal;
// By default, Ceres performs a variety of safety checks when constructing
// the problem. There is a small but measurable performance penalty to
@@ -276,7 +280,7 @@ class Problem {
// residual blocks that depend on the parameter are also removed, as
// described above in RemoveResidualBlock().
//
// If Problem::Options::enable_fast_parameter_block_removal is true, then the
// If Problem::Options::enable_fast_removal is true, then the
// removal is fast (almost constant time). Otherwise, removing a parameter
// block will incur a scan of the entire Problem object.
//
@@ -362,7 +366,7 @@ class Problem {
// Get all the residual blocks that depend on the given parameter block.
//
// If Problem::Options::enable_fast_parameter_block_removal is true, then
// If Problem::Options::enable_fast_removal is true, then
// getting the residual blocks is fast and depends only on the number of
// residual blocks. Otherwise, getting the residual blocks for a parameter
// block will incur a scan of the entire Problem object.