I see the question has been reactivated with a bounty, now asking what the practical uses for yield
are. I'll give an example from my experience.
As we know, yield
forces the calling thread to give up the processor that it's running on so that another thread can be scheduled to run. This is useful when the current thread has finished its work for now but wants to quickly return to the front of the queue and check whether some condition has changed. How is this different from a condition variable? yield
enables the thread to return much quicker to a running state. When waiting on a condition variable the thread is suspended and needs to wait for a different thread to signal that it should continue. yield
basically says "allow a different thread to run, but allow me to get back to work very soon as I expect something to change in my state very very quickly". This hints towards busy spinning, where a condition can change rapidly but suspending the thread would incur a large performance hit.
But enough babbling, here's a concrete example: the wavefront parallel pattern. A basic instance of this problem is computing the individual "islands" of 1s in a bidimensional array filled with 0s and 1s. An "island" is a group of cells that are adjacent to eachother either vertically or horizontally:
1 0 0 0
1 1 0 0
0 0 0 1
0 0 1 1
0 0 1 1
Here we have two islands of 1s: top-left and bottom-right.
A simple solution is to make a first pass over the entire array and replace the 1 values with an incrementing counter such that by the end each 1 was replaced with its sequence number in row major order:
1 0 0 0
2 3 0 0
0 0 0 4
0 0 5 6
0 0 7 8
In the next step, each value is replaced by the minimum between itself and its neighbours' values:
1 0 0 0
1 1 0 0
0 0 0 4
0 0 4 4
0 0 4 4
We can now easily determine that we have two islands.
The part we want to run in parallel is the the step where we compute the minimums. Without going into too much detail, each thread gets rows in an interleaved manner and relies on the values computed by the thread processing the row above. Thus, each thread needs to slightly lag behind the thread processing the previous line, but must also keep up within reasonable time. More details and an implementation are presented by myself in this document. Note the usage of sleep(0)
which is more or less the C equivalent of yield
.
In this case yield
was used in order to force each thread in turn to pause, but since the thread processing the adjacent row would advance very quickly in the meantime, a condition variable would prove a disastrous choice.
As you can see, yield
is quite a fine-grain optimization. Using it in the wrong place e.g. waiting on a condition that changes seldomly, will cause excessive use of the CPU.
Sorry for the long babble, hope I made myself clear.