NetBSD-Users archive

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

Re: pthreads condition variables



WHat I don't really understand why you are creating that kind of scenario. Seems like you have designed things in a backward way from the start.

There is no way with pthreads to do what you want. You can wait on condition variables, but as you noted, this means also an associated mutex, which must be the same for all threads.

But what are you really doing which requires that all 256 (or whatever number) of threads needs to be woken up and started exactly in parallel?

Seems to me that this is where you maybe should rethink. Do you really have data for all 256 jobs ready at the same time, to be started at the same time?

Have your worked threads each have their own condvar and mutex instead. and fire each one off as soon as enough data for that thread to work on is available? Or don't even create the thread until the data is there for it to work on, and don't do any waits at all.

Obviously I don't know enough about your program to say how it can/should be done, but I can think of several alternative ways of doing most stuff, compared to trying to start 256 threads exactly simultaneously.

        Johnny


raymond.meyer%rambler.ru@localhost wrote:
On Wed, 18 Nov 2009 22:48:06 +0100
Jean-Yves Migeon <jeanyves.migeon%free.fr@localhost> wrote:

raymond.meyer%rambler.ru@localhost wrote:
 > The problem here is when all 256 threads wake up at the same time,
 > they will all try to lock the same mutex, creating a lot of
 > contention. Because the data is partitioned into 256 parallel
 > regions, each thread works on a different data set, hence no need
 > for mutual exclusion.

 From what I understand, it is the traditional worker thread model
from Butenhof, which is based on what you say, except that the
processed data is shared between threads (not your case).

You could split up the thing in 1/2, 1/3, 1/4... with multiple conditional variables, so that you reduce by an order of magnitude
the contention on the different mutexes, without relying to the "one
condvar per thread" model (actually, that is two, one to signal that
there is data to process, and one to signal that the processing just
finished).

IMHO, the "one condvar model to wake them all" is too much of a bottleneck, as when one of the region is filled, the associated
thread is waiting for the 255 other regions to be filled (right when
you will issue the broadcast).

 > When
 > a thread wakes up, it immediately calls pthread_mutex_unlock, which
 > seems to be redundant, but necessary to allow other threads to
 > continue.

No, it is necessary as the mutex protects a shared state, like a work queue. If the mutex_cond_wait returned with the mutex unlocked, there could be two threads working on the same queue at a time, generously poping/pushing items in it without locking, which is bad.

 > The alternative is to have each thread sleep on its own private
 > condition variable and mutex. This would require calling
 > 'pthread_cond_signal' for each thread, that is 256 time in total.
 >
 > So is there a way to design a function similar to
 > pthread_cond_broadcast, that doesn't cause each thread to lock the
 > same mutex when it wakes up?

You mean a function to wake up different sleeping threads without relying to mutex protection? Seems hard, especially when you have to handle spurious wakeups.

No, not really. What I mean is this:

Currently Posix 'pthread_cond_wait' is defined as:

int pthread_cond_wait(
        pthread_cond_t *cond, pthread_mutex_t *mutex);

I think it would be better to redesign this function as:

int pthread_cond_wait(
        pthread_cond_t *cond, pthread_mutex_t *mutex, int lock_mutex);

When you call this function and pass 'lock_mutex' set to 1, then it
behaves just like a currently implemented Posix function, i.e. when the
thread wakes up, the mutex will be automatically locked.

However when you pass 'lock_mutex' set to 0, then when the thread wakes
up, the mutex will be UNLOCKED. The rationale for this is to avoid the
'thundering herd' problem and to wake up as many threads in parallel as
possible. If you have 256 threads sleeping, and your algorithms and
data structures are designed in such a way that threads don't modify
shared data when woken up, then it would be much better to broadcast
condition and have 256 threads wake up WITHOUT blocking on the same
mutex in user space. The kernel would still probably have to lock the
mutex when moving threads from sleep queue to run queue etc, but at
least this would avoid unnecessary context switching in user space.


Home | Main Index | Thread Index | Old Index