[Boost.thread] Simultaneously starting thread execution
Hi there,
I'm trying to find a way to let a number of threads start execution
simultaneously, and in any case not before a certain condition has come
true. I would also like to terminate them within a relatively short time
frame.
I can not use the Boost.Thread barrier class, as I do not know the number of
threads in advance (users register consumer-type objects, and I do not know
how many there will be). I also believe I do not have to use a condition
variable, as the different threads need to synchronize their access to a
data ressource anyway, and I can use the same mutex to block them in the
beginning.
I have thus come up with something like the code quoted below. Are there
easier ways to do this with the Boost.Thread library ?
One of the problems (which seems to be unrelated to the code below) is that
the three threads do not get called equally often. In one run, one thread
was called 14564 times, another 1607 times and the third one 8676 times.
Thanks and Best Regards,
Ruediger
/***********************************************************************/
#include <iostream>
#include
On Wed, Aug 06, 2008 at 01:36:19AM +0200, Ruediger Berlich wrote:
I'm trying to find a way to let a number of threads start execution simultaneously, and in any case not before a certain condition has come true.
Define "simultaneously". If you have more threads than CPUs, it should be obvious that, due to time-slicing, it is physically impossible that they start simultaneously. Even with more CPUs than threads, this is achievable only in architecture-specific way and with instructions that are accessible only to supervisor-level code (e.g. Pentium's MONITOR instruction or broadcasted interprocessor interrupt -- if the latter exists at all). Every other mechanism will incur some delay between start of different threads.
I also believe I do not have to use a condition variable, as the different threads need to synchronize their access to a data ressource anyway, and I can use the same mutex to block them in the beginning.
While one thread is in the critical section protected by the mutex, all others will wait until that thread exits the critical section. This is hardly "simultaneous" start.
One of the problems (which seems to be unrelated to the code below) is that the three threads do not get called equally often. In one run, one thread was called 14564 times, another 1607 times and the third one 8676 times.
This is perfectly normal, and is not a "problem". Threaded code that depends on relative speeds of threads (on a general-purpose OS) is calling for trouble. Can you describe what are you trying to achieve? Threads might not be the best solution..
Hi there, o.k., being a physicist, I hope I can find the right words in this computer-scientist-rich environment ;-) Imagine an environment where m entities produce items ("producers") which are processed by n workers ("consumers"), running as threads. The results are then returned back to the original entities, which themselves run in threads. Both m and n are not known in advance, as it is the user (or an automated procedure) that determines how many producers and consumers there will be. In the middle of this sits a broker, which takes care of all communication between producers and consumers. Both need to register with the broker before being able to communicate with each other. I want to have as few restrictions for my users as possible, as I want my library to be easy to use. Hence there is no rule when producers and consumers may or may not be registered. However, my current setup makes it desirable that consumer threads do not *start* before at least one producer has been registered (they are started by the broker). Hence I need to have a mechanism that blocks all consumers that have been registered before the first producer, until such time that the first items to be processed are available. If the number of consumer threads would be known in advance, Boost's Thread-Barrier might be a possible choice. As I do not know this number, however, I'll probably have to do my own locking (see my sample implementation). Best, Ruediger Zeljko Vrba wrote:
On Wed, Aug 06, 2008 at 01:36:19AM +0200, Ruediger Berlich wrote:
I'm trying to find a way to let a number of threads start execution simultaneously, and in any case not before a certain condition has come true.
Define "simultaneously". If you have more threads than CPUs, it should be obvious that, due to time-slicing, it is physically impossible that they start simultaneously. Even with more CPUs than threads, this is achievable only in architecture-specific way and with instructions that are accessible only to supervisor-level code (e.g. Pentium's MONITOR instruction or broadcasted interprocessor interrupt -- if the latter exists at all). Every other mechanism will incur some delay between start of different threads.
I also believe I do not have to use a condition variable, as the different threads need to synchronize their access to a data ressource anyway, and I can use the same mutex to block them in the beginning.
While one thread is in the critical section protected by the mutex, all others will wait until that thread exits the critical section. This is hardly "simultaneous" start.
One of the problems (which seems to be unrelated to the code below) is that the three threads do not get called equally often. In one run, one thread was called 14564 times, another 1607 times and the third one 8676 times.
This is perfectly normal, and is not a "problem". Threaded code that depends on relative speeds of threads (on a general-purpose OS) is calling for trouble.
Can you describe what are you trying to achieve? Threads might not be the best solution..
-- Kind Regards / Mit freundlichen Gruessen, Ruediger Berlich ------------------------------------------------------------------------ Dr. Ruediger Berlich | E-mail: ruediger.berlich@iwr.fzk.de Forschungszentrum Karlsruhe | Web: http://ruediger.berlich.com Steinbuch Centre for Computing | Phone: +49 (0)7247 825678 Hermann-von-Helmholtz-Platz 1 | Fax: +49 (0)7247 824972 D-76344 Eggenstein-Leopoldshafen | Mobile: +49 (0)178 5567842 ------------------------------------------------------------------------ /*************************************************************************/ The Steinbuch Centre for Computing of Karlsruhe Institute of Technology (the Cooperation of Forschungszentrum Karlsruhe GmbH and Universitaet Karlsruhe TH) will run its annual GridKa School from September 8th to 12th, 2008. Please find further information at http://www.fzk.de/gks08 . /*************************************************************************/ Forschungszentrum Karlsruhe GmbH Sitz: Weberstraße 5 76133 Karlsruhe Amtsgericht Mannheim HRB 100302 Vorsitzende des Aufsichtsrats: Baerbel Brumme-Bothe Vors. der Geschäftsführung: Prof. Dr. Eberhard Umbach
Ruediger Berlich: ...
If the number of consumer threads would be known in advance, Boost's Thread-Barrier might be a possible choice. As I do not know this number, however, I'll probably have to do my own locking (see my sample implementation).
You might want to look at Phasers: http://www.infoq.com/news/2008/07/phasers http://www.cs.rice.edu/%7Evs3/PDF/SPSS08-phasers.pdf
I wrote the following to do some volume testing on a service, may help
you:
boost::mutex mutex;
bool testthreads( std::string& mdoid, std::vector<unsigned char>&
userpin )
{
boost::mutex::scoped_lock lock( mutex );//wait for the main thread
to say go
lock.unlock();//release mutex immediately to allow other threads to
start
performOp();
return true;
}
bool testmultithreaded()
{
printf( "Please enter thread count [1-2048] : " );
std::string input;
std::cin >> input;
unsigned long encCnt = std::strtoul( input.c_str(), NULL, 0 );
if( encCnt == 0 || encCnt > 2048 ) {
printf( "Thread count out of range" );
return false;
}
const int threadCnt = encCnt;
std::vector
Le Mer 6 août 2008 16:45, Patrick Loney a écrit :
I wrote the following to do some volume testing on a service <snip>
How would go and adapt this if we wanted the thread to return into a waiting state after performing an operation so I can reuse them later for another cyle of operations triggered from the 1st thread ?
On Wed, Aug 06, 2008 at 10:53:43AM +0200, Ruediger Berlich wrote:
will be. In the middle of this sits a broker, which takes care of all communication between producers and consumers. Both need to register with the broker before being able to communicate with each other.
Having a single broker for all communication between producers and consumers defeats the point of having threads. Eventually, the broker will become the bottleneck (serialization point). Or did I misunderstand the first sentence?
has been registered (they are started by the broker). Hence I need to have a mechanism that blocks all consumers that have been registered before the first producer, until such time that the first items to be processed are available.
Condition variable?
Hi Zeljko,
will be. In the middle of this sits a broker, which takes care of all communication between producers and consumers. Both need to register with the broker before being able to communicate with each other.
Having a single broker for all communication between producers and consumers defeats the point of having threads. Eventually, the broker will become the bottleneck (serialization point). Or did I misunderstand the first sentence?
The part that is indeed serialized this way is the match-making between consumer and producer. Match-making just means fetching the next available producer from a list and connecting it to the consumer. Once that has happened, the match-maker (aka Broker) is free for a new connection. Processing the data takes far longer than the match-making. And what's handed over between producer and consumer in the end is just a shared_ptr (because sometimes a producer might go away and I can't hand back the data. So I don't want a headache with freeing the memory). So most part of the compute time will still be spent concurrently. I have thought of ways of handling even the hand-over concurrently, but I'm not sure they are worth the effort. The data processing time is far too long in comparison to the hand-over. Best, Ruediger
participants (5)
-
joel falcou
-
Patrick Loney
-
Peter Dimov
-
Ruediger Berlich
-
Zeljko Vrba