Re: multithreaded mixer
Re: multithreaded mixer
- Subject: Re: multithreaded mixer
- From: Philippe Wicker <email@hidden>
- Date: Thu, 5 Feb 2004 11:37:40 +0100
On Wednesday, February 4, 2004, at 08:57 PM, Jeff Moore wrote:
Hi,
The original reply was too long and rejected, here is a snipped version.
On Feb 3, 2004, at 11:00 PM, Philippe Wicker wrote:
On Wednesday, February 4, 2004, at 12:56 AM, Jeff Moore wrote:
The reason why is that there is no "politically correct" way to
block the IO thread.
On the other hand I cannot figure why it could have a negative
impact on the MIDI threads. Could tell us more about this?
The way it works is that the IO thread will not be pre-emptible for a
portion of it's cycle right after it wakes up. Then it becomes
pre-emptible by other real time threads. By constantly blocking the IO
thread, you are essentially putting it into a state where it won't
ever be pre-emptible. This will prevent the real time MIDI threads
from being able to sneak in for a few mics to do their thing and
result in a degradation of MIDI timing which will have the natural
consequence of making MIDI and audio go out of synch.
That's clear.
In short, don't ever block the IO thread. It is number one on the
list of "bad things" you can do.
The question then is: is this scheduler the best one for the kind of
applications we are all writing?
It is and the fact that lots of apps out there (like Logic, DP, etc)
have already solved this problem is proof that things work if you
cooperate with the system and are flexible with how you approach the
solution to the problem.
I get what I deserve. My remark about the scheduler was out of line. I
apologize for this.
I also want to suggest a nightmare scenario: what if everybody's
AudioUnit did what you are suggesting? This is not an unreasonable
suggestion at first blush considering that some of the synths and
effects are pretty darn complicated and do a lot of work that wouldn't
be too hard to parallelize. This would bring the system to it's knees
with all the real time thread traffic and no one would get anything
done.
I wasn't suggesting that everyone should try to split the dsp load
between a plethora of threads (I wouldn't do it myself on my own AUs).
I was *only* trying to give an answer to *one* question.
Also, let's not forget that in most applications, there is a whole lot
more going on than just DSP. There's UI to update, data to read from
the disk or the network, bookkeeping to do, MIDI data to read and
write, etc. Trying to split your DSP tasks up to distribute to all the
processors can easily get you into a situation where you just not able
to respond to the user or get the data from the disk that you need in
a timely fashion. This is another facet of why doing this won't
necessarily have the beneficial effect you think it will.
It makes sense. This is the second part of the answer to the original
question. To sum up: 2 guidelines, don't block the IO thread, *and*
don't overload the machine with too much works within real time threads.
To go back to the original question (split the DSP work between
different threads), the only solution I can see which satisfies the
"don't ever block the IO thread" constraint is to make both subgraphs
run in their own thread and "push" the audio into a private ring
buffer. The code executed in the context of the IO thread has then to
pull the audio from both ring buffers, mix it and return it to the
HAL. When the IOProc is called, the code here could pass the IOProc
parameters to these two threads using 2 non blocking queues (one for
each thread). This solution adds a latency which may be as much as an
IOProc buffer size. The other bad news is that the synchronization of
the worker threads with the IOProc needs a mutex/condvar couple or a
mach semaphore. In both cases, a lock must be taken either by the IO
thread or the worker thread which may lead to block the IO thread
(although for a very short amount of time). It is true however that
in this particular case the probability of such a blocking is very
low and may be neglected (???).
This is a common misconception about how pthreads work. One doesn't
have to own the mutex associated with a condvar to signal it.
I think you misunderstood me here. I didn't mean that you need to take
a lock to signal the condvar. The lock on the signaler side is
necessary to avoid a race condition at the waiter side.
A signaler thread executes a code such as:
mutex_lock();
predicate = true;
mutex_unlock();
cond_signal(); // No need to take the lock to signal
A waiter thread executes a code such as:
mutex_lock();
while (! predicate) cond_wait(); // while (! predicate) to protect
against spurious wake up
// Reset the predicate if needed
mutex_unlock();
If you don't bracket "predicate = true" with a lock/unlock pair then
the following may occur:
Signaler thread Waiter thread
mutex_lock()
while (!predicate)
- waiter is pre-empted by signaler here before the call to cond_wait
predicate = true
cond_signal()
- no thread is waiting, so no actual signal
- waiter is yielded the cpu here
cond_wait()
- the predicate is true, but Waiter have to wait next cond_signal to
wake up. It has missed one IO cycle.
I'm sure you're aware of this race condition, but maybe not all the
readers. The lock I was thinking about is the one around "predicate =
true". If the waiter is able to deal with such a miss, then the lock is
not necessary.
I don't use mach semaphores, so I can't comment on them. Also, there
is no reason why you have to use a signal to do this. You could just
as easily wake the thread up on the decrementer and thus save a bit of
overhead. After all, if it's good enough for the main IO thread, it
should be good enough for any auxiliaries, right?
I'm not aware of this technique. Is it documented somewhere? IOKit?
Available in user land?
--
Jeff Moore
Core Audio
Apple
Anyway, this discussion gives me a much better understanding of how the
scheduler works. Thanks for that.
Philippe Wicker
email@hidden
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.