I am in the process of re-working Symbolic's multithreading operations. I've already completed the work for multithreaded memory clearing, multithreaded random came generation, and multithreaded text output operations. I'm now tackling the revision of multithreaded perft() as a precursor to reworking multithreaded search.
The current perft() arrangement uses a separate event input queue for each worker thread, guarded by a mutex and shared between the worker thread and the master distribution thread. When the worker thread is idle, it checks the pending event count via the mutex and does this using polling. The polling runs a loop with a 100 millisecond sleep and checks the event count once per cycle. The master distribution thread also uses polling to collect results from worker threads.
This is somewhat wasteful of CPU resources and it also can induce an unnecessary delay when waking the thread. It is what I call an "inefficient wait". What is preferred is an "efficient wait" which is much less wasteful and also provides a snappier response.
Unix-like platforms offer two means of efficient waiting from the pthread library: condition variables and semaphores. At present, I'm working with condition variables.
The basic problem I'm having is the case where a master thread calls pthread_cond_signal() when the worker thread is doing something other than waiting with pthread_cond_wait().
The master executes:
Code: Select all
pthread_mutex_lock();
EnqueueJob();
pthread_cond_signal();
pthread_mutex_unlock();
Code: Select all
pthread_cond_wait();
DequeueJob();
But this has problems, too. First, it prevents any master from enqueuing more requests as long as the worker is looping because the worker holds the queue mutex. This makes the master block which should be avoided as much as possible.
Second, if the worker carefully gives up the mutex lock while processing a job, this allows even more signals to be lost. Maybe some more tricky looping arrangement might fix this.
----
An alternative to a condition variable is a semaphore. Indeed, in the above the combination of an event queue including an element count and the condition variable is much like a semaphore. Should I just drop the condition variable scheme and use semaphores instead?