multi_newton_takedown

View page source

Take Down Multi-threaded Newton Method

Syntax

ok = harmonic_takedown ( xout )

Purpose

This routine does the takedown for splitting the Newton method into sub-intervals.

Thread

It is assumed that this function is called by thread zero, and all the other threads have completed their work and are blocked (waiting).

xout

See multi_newton_run .

Source

namespace {
bool multi_newton_takedown(vector<double>& xout)
{  // number of threads in the calculation
   size_t num_threads  = std::max(num_threads_, size_t(1));

   // remove duplicates and points that are not solutions
   xout.resize(0);
   bool   ok = true;
   ok       &= thread_alloc::thread_num() == 0;

   // initialize as more that sub_length_ / 2 from any possible solution
   double xlast = - sub_length_;
   for(size_t thread_num = 0; thread_num < num_threads; thread_num++)
   {  vector<double>& x = work_all_[thread_num]->x;

      size_t i;
      for(i = 0; i < x.size(); i++)
      {  // check for case where this point is lower limit for this
         // thread and upper limit for previous thread
         if( fabs(x[i] - xlast) >= sub_length_ )
         {  xout.push_back( x[i] );
            xlast = x[i];
         }
         else
         {  double fcur, flast, df;
            fun_(x[i],   fcur, df);
            fun_(xlast, flast, df);
            if( fabs(fcur) < fabs(flast) )
            {  xout[ xout.size() - 1] = x[i];
               xlast                  = x[i];
            }
         }
      }
      // check that this thread was ok with the work it did
      ok &= work_all_[thread_num]->ok;
   }

   // go down so free memory for other threads before memory for master
   size_t thread_num = num_threads;
   while(thread_num--)
   {
# if USE_THREAD_ALLOC_FOR_WORK_ALL
      // call the destructor for vector destructor
      work_all_[thread_num]->x.~vector<double>();
      // delete the raw memory allocation
      void* v_ptr = static_cast<void*>( work_all_[thread_num] );
      thread_alloc::return_memory( v_ptr );
# else
      delete work_all_[thread_num];
# endif
      // Note that xout corresponds to memroy that is inuse by master
      // (so we can only chech have freed all their memory).
      if( thread_num > 0 )
      {  // check that there is no longer any memory inuse by this thread
         ok &= thread_alloc::inuse(thread_num) == 0;
         // return all memory being held for future use by this thread
         thread_alloc::free_available(thread_num);
      }
   }
   // now we are done with the work_all_ vector so free its memory
   // (because it is a static variable)
   work_all_.clear();

   return ok;
}
}