[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [IMP-dev] More small patches



Ben Webb wrote:
Daniel Russel wrote:
- Clean up various attempts at automatically picking parameters in the nonbonded lists. For now just have them be user setable.

With this patch, 'scons examples' always fails for me on synth, with errors like:

scons: Building targets ...
builder_unit_test(["kernel/doc/examples/examples.passed"], ["bin/imppy.sh", "kernel/doc/examples/chain.py"]) cd /synth1/home/ben/imp/kernel/doc/examples && /synth1/home/ben/imp/bin/imppy.sh python chain.py > /dev/null ERROR: Nonbonded list is missing (7) (5.34008, 3.38164, 5.22317) 1 and (1) (7.81002, 2.4397, 4.51924)1 size is 75
That was dumb. In cleaning it up for submit I disabled rebuilding of nbl. Oops. Strange that it didn't get triggered on my machine.

Here is an improved patch


While I am at it, here is a patch which moves the "-O3" flag for gcc to being controlled by the release flag as it makes non release building take a really long time and be hard to debug.

Finally, I cleaned up the example slightly

Index: kernel/include/IMP/score_states/NonbondedListScoreState.h
===================================================================
--- kernel/include/IMP/score_states/NonbondedListScoreState.h	(revision 561)
+++ kernel/include/IMP/score_states/NonbondedListScoreState.h	(working copy)
@@ -42,15 +42,18 @@
   /** How much to add to the size of particles to allow particles to move
       without rebuilding the list */
   Float slack_;
-  //! An estimate of what the slack should be next time the list is recomputed
-  Float next_slack_;
-  int num_steps_;
   bool nbl_is_valid_;
   int number_of_rebuilds_;
   int number_of_updates_;
-  typedef std::vector<std::pair<Particle*, Particle*> > NBL;
-  NBL nbl_;
+  int number_of_overflows_;
+  //! The maximum allowable size for the NBL
+  /** An exception will be thrown if the list exceeds this size.
+   */
+  unsigned int max_nbl_size_;
+  ParticlePairs nbl_;
 
+  struct NBLTooLargeException{};
+
 protected:
 
   Float get_slack() const {return slack_;}
@@ -93,7 +96,11 @@
     if (!are_bonded(a,b)) {
       IMP_LOG(VERBOSE, "Found pair " << a->get_index() 
         << " " << b->get_index() << std::endl);
-      nbl_.push_back(std::make_pair(a, b));
+      if (nbl_.size() <  max_nbl_size_) {
+        nbl_.push_back(std::make_pair(a, b));
+      } else {
+        throw NBLTooLargeException();
+      }
     } else {
       IMP_LOG(VERBOSE, "Pair " << a->get_index()
               << " and " << b->get_index() << " rejected on bond" 
@@ -184,6 +191,29 @@
   FloatKey get_radius_key() const {return rk_;}
   void set_radius_key(FloatKey rk) {rk_=rk;} 
 
+  //! Set the maximum allowable size for the NBL
+  /** The NBL will keep reducing the slack and trying to
+      rebuild until it can make the list smaller than this.
+   */
+  void set_max_size(unsigned int mx) {
+    max_nbl_size_= mx;
+  }
+
+
+  //! Set the slack used when generating the NBL
+  /** The slack allows the the NBL to non be rebuilt every step
+      making the process more efficient. However, too large
+      a value can result in the NBL being excessively large.
+
+      A good guideline is that it should be the maximum amount
+      a particle coordinate would change in 20 steps or so.
+   */
+  void set_slack(float slack) {
+    IMP_check(slack>= 0, "Slack must be nonnegative",
+              ValueException("Negative slack"));
+    slack_=slack;
+  }
+
   IMP_CONTAINER(BondedListScoreState, bonded_list,
                 BondedListIndex);
 
@@ -201,7 +231,7 @@
   /** The value type is an ParticlePair. 
    */
   typedef boost::filter_iterator<BoxesOverlap,
-    NBL::const_iterator> NonbondedIterator;
+    ParticlePairs::const_iterator> NonbondedIterator;
 
   //! Iterates through the pairs of non-bonded particles
   NonbondedIterator nonbonded_begin() const {
@@ -217,6 +247,9 @@
                              nbl_.end(), nbl_.end());
   }
 
+  const ParticlePairs get_nonbonded() const {
+    return nbl_;
+  }
 
   unsigned int number_of_nonbonded() const {
     IMP_check(get_nbl_is_valid(), "Must call update first",
Index: kernel/src/score_states/NonbondedListScoreState.cpp
===================================================================
--- kernel/src/score_states/NonbondedListScoreState.cpp	(revision 561)
+++ kernel/src/score_states/NonbondedListScoreState.cpp	(working copy)
@@ -37,11 +37,11 @@
                                         cutoff_(cut),
                                         nbl_is_valid_(false)
 {
-  slack_=20;
-  next_slack_=slack_;
-  num_steps_=1;
+  slack_=cutoff_;
   number_of_updates_=1;
   number_of_rebuilds_=0;
+  number_of_overflows_=0;
+  max_nbl_size_= std::numeric_limits<unsigned int>::max();
 }
 
 
@@ -55,7 +55,9 @@
 {
   out << "Nonbonded list averaged " 
       << static_cast<Float>(number_of_updates_)
-      / number_of_rebuilds_ << " steps between rebuilds" << std::endl;
+      / number_of_rebuilds_ << " steps between rebuilds"
+      << " and overflowed " <<  number_of_overflows_ 
+      << " times" << std::endl;
 }
 
 
@@ -96,47 +98,26 @@
     (*bli)->before_evaluate(ScoreState::get_before_evaluate_iteration());
   }
 
-  if (nbl_is_valid_) {
-    /*std::cout << "Rate is " << rate << " target is " << target_steps
-              << " so slack is " << target_slack << " mc " << mc
-              << " nbl " << nbl_.size() << " cost " 
-              << rebuild_cost << std::endl;*/
-    if (mc > slack_) {
-      /*    Float rate= std::pow(static_cast<Float>(nbl_.size()),
-            .333f)/ num_steps_;
-            Float target_steps= .6*std::pow(rebuild_cost, .25f)
-            *std::pow(rate, -.75f);
-            Float target_slack= (target_steps+1)*mc/num_steps_;
-            next_slack_= target_slack*.5 + .5*next_slack_;
-      */
-
-      /*std::cout << "Killing nbl because " << mc << " 
-        << slack_ << " " << next_slack_ 
-        << " " << num_steps_ << std::endl;*/
-      if (num_steps_ < 50) {
-        //slack_= next_slack_;
-      }
-      num_steps_=1;
-      //next_slack_= std::max(2.0*mc, 2.0*slack_);
-      set_nbl_is_valid(false);
-      ++number_of_rebuilds_;
-      slack_=next_slack_;
-    /*} else if (num_steps_ > 100) {
-      //next_slack_=slack_/2.0;
-      slack_=next_slack_;
-      num_steps_=1;
-      set_nbl_is_valid(false);
-      ++number_of_rebuilds_;*/
-    } else {
-      ++num_steps_;
-      //next_slack_= next_slack_*.98;
-    }
-  }
-
   bool rebuilt=false;
-  if (!get_nbl_is_valid()) {
-    rebuild_nbl();
-    rebuilt=true;
+  if (mc > slack_ || !get_nbl_is_valid()) {
+    unsigned int rebuild_attempts=0;
+    do {
+      try {
+        ++rebuild_attempts;
+        ++number_of_rebuilds_;
+        set_nbl_is_valid(false);
+        rebuild_nbl();
+        rebuilt=true;
+      } catch (NBLTooLargeException &) {
+        slack_= slack_/2.0;
+        ++number_of_overflows_;
+        if (number_of_rebuilds_==100) {
+          IMP_WARN("Can't rebuild NBL with given max NBL size of "
+                   << max_nbl_size_ << std::endl);
+          throw ValueException("Bad NBL max size");
+        }
+      }
+    } while (!rebuilt);
   } else {
     nbl_.erase(std::remove_if(nbl_.begin(), nbl_.end(), 
                               internal::HasInactive()),
@@ -154,7 +135,7 @@
 {
   nbl_is_valid_= tf;
   if (!nbl_is_valid_) {
-    NBL empty;
+    ParticlePairs empty;
     // free memory to make sure it shrinks
     std::swap(empty, nbl_);
   }
Index: kernel/src/score_states/AllNonbondedListScoreState.cpp
===================================================================
--- kernel/src/score_states/AllNonbondedListScoreState.cpp	(revision 561)
+++ kernel/src/score_states/AllNonbondedListScoreState.cpp	(working copy)
@@ -94,6 +94,7 @@
   }
   if (P::update(mc, cost)) {
     mc_->reset();
+    mcr_->reset();
   }
   IMP_IF_CHECK(EXPENSIVE) {
     check_nbl();
@@ -334,7 +335,9 @@
                    << " " << gr(ps[i])
                    << " and " << ps[j]->get_index() << " " 
                    << dj << gr(ps[j]) 
-                   << " size is " << number_of_nonbonded() << std::endl);
+                   << " size is " << number_of_nonbonded() 
+                   << " distance is " << distance(di, dj) 
+                   << " max is " << mc_->get_max() << std::endl);
       }
     }
   }
Index: tools/__init__.py
===================================================================
--- tools/__init__.py	(revision 561)
+++ tools/__init__.py	(working copy)
@@ -53,7 +53,9 @@
 def _add_release_flags(env):
     """Add compiler flags for release builds, if requested"""
     if env.get('release', False):
-        env.Append(CPPDEFINES='NDEBUG')
+        env.Append(CPPDEFINES=['NDEBUG'])
+        if env['CC'] == 'gcc':
+            env.Append(CCFLAGS=['-O3'])
 
 def CheckGNUHash(context):
     """Disable GNU_HASH-style linking (if found) for backwards compatibility"""
@@ -186,7 +188,7 @@
         pass
     env.Prepend(SCANNERS = _SWIGScanner)
     if env['CC'] == 'gcc':
-        env.Append(CCFLAGS="-Wall -g -O3")
+        env.Append(CCFLAGS="-Wall -g")
     if env.get('include', None) is not None:
         env['include'] = [os.path.abspath(x) for x in \
                           env['include'].split(os.path.pathsep)]
Index: kernel/doc/examples/chain.py
===================================================================
--- kernel/doc/examples/chain.py	(revision 561)
+++ kernel/doc/examples/chain.py	(working copy)
@@ -7,27 +7,28 @@
 # another.
 
 #IMP.set_log_level(IMP.VERBOSE)
+np=20
 radius =1.0
 rk= IMP.FloatKey("radius")
 m= IMP.Model()
 # The particles in the chain
 chain= IMP.Particles()
-for i in range(0,20):
+for i in range(0,np):
     p= IMP.Particle()
     pi= m.add_particle(p)
     d= IMP.XYZDecorator.create(p)
-    d.set_x(random.uniform(0,10))
-    d.set_y(random.uniform(0,10))
-    d.set_z(random.uniform(0,10))
+    d.randomize_in_box(IMP.Vector3D(0,0,0),
+                       IMP.Vector3D(10,10,10))
     d.set_coordinates_are_optimized(True)
     p.add_attribute(rk, radius, False)
-    # create a bond between successive particles
-    if (i != 0):
-        bp= IMP.BondedDecorator.create(p)
-        bpr= IMP.BondedDecorator.cast(chain.back())
-        b= IMP.custom_bond(bp, bpr, 1.5*radius, 10)
     chain.append(p)
 
+# create a bond between successive particles
+for i in range(1, len(chain)):
+    bp= IMP.BondedDecorator.create(chain[i])
+    bpr= IMP.BondedDecorator.cast(chain[i-1])
+    b= IMP.custom_bond(bp, bpr, 1.5*radius, 10)
+
 # If you want to inspect the particles
 # Notice that each bond is a particle
 for p in m.get_particles():