[boost 1.42, gcc 4.4, ubuntu 10.10] Program hangs when using barrier.wait() even though all threads have reached wait.
I'm having problems with boost::barrier. I've written a class that creates a thread pool to map evaluate an array of functions to an array of results. I've used barriers in the synchronisation. The problem is that the threads are all getting stuck at the barrier::wait calls. I've verified with gdb that all the worker threads and the manager thread are sitting in barrier::wait() however, there all stuck. I have no idea what's causing this. I've put the source code in the following github gist and also pasted it to the end of the email. https://gist.github.com/1041351 I've also checked the bugs list for any known bugs, fixed or otherwise, to do with threading and I haven't found anything. I'm not sure what I'm doing wrong. -Gareth Charnock /* compile: g++ thread_template.cpp -lboost_thread Outputs: BOOST_VERSION = 104200 Starting thread 0 Starting thread 1 Thread 0 waiting for work Thread 1 waiting for work Threads have work... */ #include <boost/version.hpp> #include <boost/thread.hpp> #include <boost/thread/barrier.hpp> #include <boost/function.hpp> #include <iostream> #include <vector> template<typename T> class Multithreader { public: Multithreader() : numCPU(sysconf(_SC_NPROCESSORS_ONLN)), _barrier(numCPU+1), mFuncs(NULL), mMapTo(NULL) { std::cout << "BOOST_VERSION = " << BOOST_VERSION << std::endl; //Start the thread pool for(long i = 0;i<numCPU;i++) { std::cout << "Starting thread "<<i<< std::endl; boost::thread(WorkerThread(i,this)); } } ~Multithreader() { //Terminate the threads //todo } void map(const std::vector<boost::function<T ()> >& funcs,std::vector<T>& mapTo) { mFuncs = &funcs; mMapTo = &mapTo; std::cout << "Threads have work..." << std::endl; _barrier.wait(); //Workers are working at this point std::cout << "Threads are working..." << std::endl; _barrier.wait(); std::cout << "Threads have finished" << std::endl; } private: const std::vector<boost::function<T ()> >* mFuncs; std::vector<T>* mMapTo; boost::barrier _barrier; size_t numCPU; class WorkerThread { public: WorkerThread(long _id,Multithreader* _parent) : id(_id),parent(_parent) { } void operator()() { while(true) { std::cout << "Thread "<<id<<" waiting for work" << std::endl; parent->_barrier.wait(); std::cout << "Thread "<<id<<" has work" << std::endl; //Do work for(long i = id;i<parent->mFuncs->size();i+=parent->numCPU) { parent->mMapTo->at(i) = parent->mFuncs->at(i)(); } parent->_barrier.wait(); std::cout << "Thread "<<id<<" finished the work" << std::endl; } } long id; Multithreader* parent; }; }; #include <boost/bind.hpp> double f(double x) { return x*2; } int main() { //Start the thread pool Multithreader<double> mt; std::vector<boost::function<double()> > work;work.resize(20); std::vector<double> results;results.resize(20); //Prepare the work for(unsigned long i = 0;i<20;i++) { work[i] = boost::bind(f,i); } //Execute in parallel mt.map(work,results); while(true) { //For the purposes of the example, keep the main thread alive //so we don't delete mt } }
I've just tried the same program with a fresh compile of boost 1.46.1 and got the same hanging problem. On Thu, Jun 23, 2011 at 10:32 AM, Gareth <gareth.tpc@gmail.com> wrote:
I'm having problems with boost::barrier. I've written a class that creates a thread pool to map evaluate an array of functions to an array of results. I've used barriers in the synchronisation. The problem is that the threads are all getting stuck at the barrier::wait calls. I've verified with gdb that all the worker threads and the manager thread are sitting in barrier::wait() however, there all stuck. I have no idea what's causing this. I've put the source code in the following github gist and also pasted it to the end of the email.
https://gist.github.com/1041351
I've also checked the bugs list for any known bugs, fixed or otherwise, to do with threading and I haven't found anything. I'm not sure what I'm doing wrong.
-Gareth Charnock
/* compile: g++ thread_template.cpp -lboost_thread
Outputs:
BOOST_VERSION = 104200 Starting thread 0 Starting thread 1 Thread 0 waiting for work Thread 1 waiting for work Threads have work... */
#include <boost/version.hpp> #include <boost/thread.hpp> #include <boost/thread/barrier.hpp> #include <boost/function.hpp> #include <iostream> #include <vector>
template<typename T> class Multithreader { public: Multithreader() : numCPU(sysconf(_SC_NPROCESSORS_ONLN)), _barrier(numCPU+1), mFuncs(NULL), mMapTo(NULL) { std::cout << "BOOST_VERSION = " << BOOST_VERSION << std::endl; //Start the thread pool for(long i = 0;i<numCPU;i++) { std::cout << "Starting thread "<<i<< std::endl; boost::thread(WorkerThread(i,this)); } }
~Multithreader() { //Terminate the threads
//todo }
void map(const std::vector<boost::function<T ()> >& funcs,std::vector<T>& mapTo) { mFuncs = &funcs; mMapTo = &mapTo;
std::cout << "Threads have work..." << std::endl; _barrier.wait(); //Workers are working at this point std::cout << "Threads are working..." << std::endl; _barrier.wait(); std::cout << "Threads have finished" << std::endl; } private: const std::vector<boost::function<T ()> >* mFuncs; std::vector<T>* mMapTo; boost::barrier _barrier;
size_t numCPU;
class WorkerThread { public: WorkerThread(long _id,Multithreader* _parent) : id(_id),parent(_parent) { } void operator()() { while(true) { std::cout << "Thread "<<id<<" waiting for work" << std::endl; parent->_barrier.wait(); std::cout << "Thread "<<id<<" has work" << std::endl; //Do work for(long i = id;i<parent->mFuncs->size();i+=parent->numCPU) { parent->mMapTo->at(i) = parent->mFuncs->at(i)(); } parent->_barrier.wait(); std::cout << "Thread "<<id<<" finished the work" << std::endl; } } long id; Multithreader* parent; };
};
#include <boost/bind.hpp>
double f(double x) { return x*2; }
int main() { //Start the thread pool Multithreader<double> mt;
std::vector<boost::function<double()> > work;work.resize(20); std::vector<double> results;results.resize(20);
//Prepare the work for(unsigned long i = 0;i<20;i++) { work[i] = boost::bind(f,i); } //Execute in parallel mt.map(work,results);
while(true) { //For the purposes of the example, keep the main thread alive //so we don't delete mt } }
On Thu, Jun 23, 2011 at 10:32 AM, Gareth <gareth.tpc@gmail.com> wrote:
...
I've also checked the bugs list for any known bugs, fixed or otherwise, to do with threading and I haven't found anything. I'm not sure what I'm doing wrong.
The problem is here: https://gist.github.com/1041351#L60 You declare _barrier first and numCPU second, so in your constructor, _barrier will be initialized first, using the value of numCPU, which hasn't been initialized yet. Just change the order of the declarations. Declare _barrier below numNPU. By the way, compiling with -Wall catches all these errors. Regards, Ignacio Burgueño
D'oh, fell for that old one. I guess I did forget to put -Wall in my makefile. Cheers. 2011/6/23 Ignacio Burgueño <iburgueno@gmail.com>:
On Thu, Jun 23, 2011 at 10:32 AM, Gareth <gareth.tpc@gmail.com> wrote:
...
I've also checked the bugs list for any known bugs, fixed or otherwise, to do with threading and I haven't found anything. I'm not sure what I'm doing wrong.
The problem is here: https://gist.github.com/1041351#L60 You declare _barrier first and numCPU second, so in your constructor, _barrier will be initialized first, using the value of numCPU, which hasn't been initialized yet. Just change the order of the declarations. Declare _barrier below numNPU. By the way, compiling with -Wall catches all these errors. Regards, Ignacio Burgueño
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (2)
-
Gareth
-
Ignacio Burgueño