Codebase list cppad / upstream/2015.00.00.7 doc / simple_ad_bthread.cpp.xml
upstream/2015.00.00.7

Tree @upstream/2015.00.00.7 (Download .tar.gz)

simple_ad_bthread.cpp.xml @upstream/2015.00.00.7raw · history · blame

<?xml version='1.0'?>
<html xmlns='http://www.w3.org/1999/xhtml'
      xmlns:math='http://www.w3.org/1998/Math/MathML'
>
<head>
<title>A Simple Boost Threading AD: Example and Test</title>
<meta http-equiv='Content-Type' content='text/html' charset='utf-8'/>
<meta name="description" id="description" content="A Simple Boost Threading AD: Example and Test"/>
<meta name="keywords" id="keywords" content=" a simple boost threading ad: example and test thread Ad purpose source code "/>
<style type='text/css'>
body { color : black }
body { background-color : white }
A:link { color : blue }
A:visited { color : purple }
A:active { color : purple }
</style>
<script type='text/javascript' language='JavaScript' src='_simple_ad_bthread.cpp_xml.js'>
</script>
</head>
<body>
<table><tr>
<td>
<a href="http://www.coin-or.org/CppAD/" target="_top"><img border="0" src="_image.gif"/></a>
</td>
<td><a href="simple_ad_openmp.cpp.xml" target="_top">Prev</a>
</td><td><a href="simple_ad_pthread.cpp.xml" target="_top">Next</a>
</td><td>
<select onchange='choose_across0(this)'>
<option>Index-&gt;</option>
<option>contents</option>
<option>reference</option>
<option>index</option>
<option>search</option>
<option>external</option>
</select>
</td>
<td>
<select onchange='choose_up0(this)'>
<option>Up-&gt;</option>
<option>CppAD</option>
<option>multi_thread</option>
<option>thread_test.cpp</option>
<option>simple_ad_bthread.cpp</option>
</select>
</td>
<td>
<select onchange='choose_down3(this)'>
<option>CppAD-&gt;</option>
<option>Install</option>
<option>Introduction</option>
<option>AD</option>
<option>ADFun</option>
<option>preprocessor</option>
<option>multi_thread</option>
<option>library</option>
<option>ipopt_solve</option>
<option>Example</option>
<option>speed</option>
<option>Appendix</option>
</select>
</td>
<td>
<select onchange='choose_down2(this)'>
<option>multi_thread-&gt;</option>
<option>parallel_ad</option>
<option>thread_test.cpp</option>
</select>
</td>
<td>
<select onchange='choose_down1(this)'>
<option>thread_test.cpp-&gt;</option>
<option>a11c_openmp.cpp</option>
<option>a11c_bthread.cpp</option>
<option>a11c_pthread.cpp</option>
<option>simple_ad_openmp.cpp</option>
<option>simple_ad_bthread.cpp</option>
<option>simple_ad_pthread.cpp</option>
<option>team_example.cpp</option>
<option>harmonic.cpp</option>
<option>multi_newton.cpp</option>
<option>team_thread.hpp</option>
</select>
</td>
<td>simple_ad_bthread.cpp</td>
<td>
<select onchange='choose_current0(this)'>
<option>Headings-&gt;</option>
<option>Purpose</option>
<option>Source Code</option>
</select>
</td>
</tr></table><br/>



<center><b><big><big>A Simple Boost Threading AD: Example and Test</big></big></b></center>
<br/>
<b><big><a name="Purpose" id="Purpose">Purpose</a></big></b>
<br/>
This example demonstrates how CppAD can be used in a 
boost multi-threading environment.

<br/>
<br/>
<b><big><a name="Source Code" id="Source Code">Source Code</a></big></b>

<code><font color="blue">
<br/>
<pre style='display:inline'> 
# include &lt;cppad/cppad.hpp&gt;
# include &lt;boost/thread.hpp&gt;
# define NUMBER_THREADS  4

namespace {
	// structure with problem specific information
	typedef struct {
		// function argument (worker input)
		double          x;
		// This structure would also have return information in it,
		// but this example only returns the ok flag
	} problem_specific;
	// =====================================================================
	// General purpose code you can copy to your application
	// =====================================================================
	using CppAD::thread_alloc;
	// ------------------------------------------------------------------
	// thread specific point to the thread number (initialize as null)
	void cleanup(size_t*)
	{	return; }
	boost::thread_specific_ptr&lt;size_t&gt; thread_num_ptr_(cleanup);

	// Are we in sequential mode; i.e., other threads are waiting for
	// master thread to set up next job ?
	bool sequential_execution_ = true;

	// used to inform CppAD when we are in parallel execution mode
	bool in_parallel(void)
	{	return ! sequential_execution_; }

	// used to inform CppAD of current thread number thread_number()
	size_t thread_number(void)
	{	// return thread_all_[thread_num].thread_num
		return *thread_num_ptr_.get();
	}
	// ---------------------------------------------------------------------
	// structure with information for one thread
	typedef struct {
		// number for this thread (thread specific points here)
		size_t            thread_num;
		// pointer to this boost thread
		boost::thread*    bthread;
		// false if an error occurs, true otherwise
		bool              ok;
		// pointer to problem specific information
		problem_specific* info;
	} thread_one_t;
	// vector with information for all threads
	thread_one_t thread_all_[NUMBER_THREADS];
	// --------------------------------------------------------------------
	// function that initializes the thread and then calls actual worker
	bool worker(size_t thread_num, problem_specific* info);
	void run_one_worker(size_t thread_num)
	{	bool ok = true;

		// The master thread should call worker directly
		ok &amp;= thread_num != 0;

		// This is not the master thread, so thread specific infromation
		// has not yet been set. We use it to inform other routines
		// of this threads number.
		// We must do this before calling thread_alloc::thread_num().
		thread_num_ptr_.reset(&amp; thread_all_[thread_num].thread_num);

		// Check the value of thread_alloc::thread_num().
		ok = thread_num == thread_alloc::thread_num();

		// Now do the work
		ok &amp;= worker(thread_num, thread_all_[thread_num].info);

		// pass back ok information for this thread
		thread_all_[thread_num].ok = ok;

		// no return value
		return;
	}
	// ----------------------------------------------------------------------
	// function that calls all the workers
	bool run_all_workers(size_t num_threads, problem_specific* info_all[])
	{	bool ok = true;

		// initialize thread_all_ (execpt for pthread_id)
		size_t thread_num;
		for(thread_num = 0; thread_num &lt; num_threads; thread_num++)
		{	// pointed to by thread specific info for this thread
			thread_all_[thread_num].thread_num = thread_num;
			// initialize as false to make sure worker gets called by other
			// threads. Note that thread_all_[0].ok does not get used
			thread_all_[thread_num].ok         = false;
			// problem specific information
			thread_all_[thread_num].info       = info_all[thread_num];
		}

		// master bthread number
		thread_num_ptr_.reset(&amp; thread_all_[0].thread_num);

		// Now thread_number() has necessary information for this thread
		// (number zero), and while still in sequential mode,
		// call setup for using CppAD::<a href="ad.xml" target="_top">AD</a>&lt;double&gt; in parallel mode.
		thread_alloc::parallel_setup(
			num_threads, in_parallel, thread_number
		);
		thread_alloc::hold_memory(true);
		CppAD::parallel_ad&lt;double&gt;();

		// inform CppAD that we now may be in parallel execution mode
		sequential_execution_ = false;
	
		// This master thread is already running, we need to create
		// num_threads - 1 more threads
		thread_all_[0].bthread = CPPAD_NULL;
		for(thread_num = 1; thread_num &lt; num_threads; thread_num++)
		{	// Create the thread with thread number equal to thread_num
			thread_all_[thread_num].bthread = 
				new boost::thread(run_one_worker, thread_num);
		}

		// now call worker for the master thread
		thread_num = thread_alloc::thread_num();
		ok &amp;= thread_num == 0;
		ok &amp;= worker(thread_num, thread_all_[thread_num].info);

		// now wait for the other threads to finish 
		for(thread_num = 1; thread_num &lt; num_threads; thread_num++)
		{	thread_all_[thread_num].bthread-&gt;join();
			delete thread_all_[thread_num].bthread;
			thread_all_[thread_num].bthread = CPPAD_NULL;
		}

		// Inform CppAD that we now are definately back to sequential mode
		sequential_execution_ = true;

		// now inform CppAD that there is only one thread
		thread_alloc::parallel_setup(1, CPPAD_NULL, CPPAD_NULL);
		thread_alloc::hold_memory(false);
		CppAD::parallel_ad&lt;double&gt;();

		// check to ok flag returned by during calls to work by other threads
		for(thread_num = 1; thread_num &lt; num_threads; thread_num++)
			ok &amp;= thread_all_[thread_num].ok;

		return ok;
	}
	// =====================================================================
	// End of General purpose code 
	// =====================================================================
	// function that does the work for one thread
	bool worker(size_t thread_num, problem_specific* info)
	{	bool ok = true;

		// CppAD::vector uses the CppAD fast multi-threading allocator
		CppAD::vector&lt; CppAD::<a href="ad.xml" target="_top">AD</a>&lt;double&gt; &gt; ax(1), ay(1);
		ax[0] = info-&gt;x;
		<a href="independent.xml" target="_top">Independent</a>(ax);
		ay[0] = sqrt( ax[0] * ax[0] );
		CppAD::<a href="funconstruct.xml" target="_top">ADFun</a>&lt;double&gt; f(ax, ay); 

		// Check function value corresponds to the identity 
		double eps = 10. * CppAD::numeric_limits&lt;double&gt;::epsilon();
		ok        &amp;= CppAD::<a href="nearequal.xml" target="_top">NearEqual</a>(ay[0], ax[0], eps, eps);

		// Check derivative value corresponds to the identity.
		CppAD::vector&lt;double&gt; d_x(1), d_y(1);
		d_x[0] = 1.;
		d_y    = f.<a href="forward.xml" target="_top">Forward</a>(1, d_x);
		ok    &amp;= CppAD::<a href="nearequal.xml" target="_top">NearEqual</a>(d_x[0], 1., eps, eps);

		return ok;
	}
}
bool simple_ad(void)
{	bool ok = true;
	size_t num_threads = NUMBER_THREADS;

	// Check that no memory is in use or avialable at start
	// (using thread_alloc in sequential mode)
	size_t thread_num;
	for(thread_num = 0; thread_num &lt; num_threads; thread_num++)
	{	ok &amp;= thread_alloc::inuse(thread_num) == 0; 
		ok &amp;= thread_alloc::available(thread_num) == 0; 
	}

	// initialize info_all
	problem_specific *info, *info_all[NUMBER_THREADS];
	for(thread_num = 0; thread_num &lt; num_threads; thread_num++)
	{	// problem specific information
		size_t min_bytes(sizeof(info)), cap_bytes;
		void*  v_ptr = thread_alloc::get_memory(min_bytes, cap_bytes);
		info         = static_cast&lt;problem_specific*&gt;(v_ptr);
		info-&gt;x      = double(thread_num) + 1.;
		info_all[thread_num] = info;
	}

	ok &amp;= run_all_workers(num_threads, info_all);

	// go down so that free memory for other threads before memory for master
	thread_num = num_threads;
	while(thread_num--)
	{	// delete problem specific information
		void* v_ptr = static_cast&lt;void*&gt;( info_all[thread_num] );
		thread_alloc::return_memory( v_ptr );
		// check that there is no longer any memory inuse by this thread
		ok &amp;= thread_alloc::inuse(thread_num) == 0; 
		// return all memory being held for future use by this thread
		thread_alloc::free_available(thread_num); 
	}

	return ok;
}
</pre>

</font></code>


<hr/>Input File: multi_thread/bthread/simple_ad_bthread.cpp

</body>
</html>