Sign in to follow this  

Threads and performance!

This topic is 3854 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello, i have a problem. I have two threads, in an audio-system I am creating. Thread one renders the sound, and requires to run as close to realtime as possible (Running on the Win32, non-realtime OS). This thread renders the sound, and should run all the time (I tried to sleep it, but then it sleeps for to long, and the audio outputstream is broken) Thread two runs the gui, and the gui is the user controlle of the system... The gui is implemented in OpenGL, so this thread refreshes as often as it can, but waits if the other thread is in trouble. This is working but not optimaly, is there a way i can give super-high (max possible) priority to the first thread, but so that it still let the other tread run somethimes? If I sleep a high priority thread, does it wait shorter before returning, then an average priority thread? How can you tune them? (ny sunchronizing wait/notise is possible) Next problem: I need to measure the processing time used by each thread, but since they run simultaniously, this is hard to measure, anybody know a technique for aproximating? I would like to know something like: Thread1 uses 60%, Thread2 uses 30%, and 10% is used for waiting! Again, synchronizing while testing is not an option.

Share this post


Link to post
Share on other sites
I don't have experience with audio in particular, but in most such cases you're better off with some asynchronous mechanism for supplying the sound buffers.

I believe that recent Windows versions support these mechanisms natively via overlapped structures (I won't guarantee for sound, but it does for all other IO).

So if you're having issues with real-time, you might want to look into that. Relying on busy thread to provide data doesn't seem that reliable to me. This is very true for network IO for example, where async handling is the defacto optimal aproach.

Which API are you using for sound, and how do you keep it supplied with buffers?

Also, you do not need real-time OS to process sound in real-time (apparently, everyone else does it without much problem)


Performance is best measured with various profilers, those will usually give you a breakdown at OS level, including by thread/process/kernel mode.

Share this post


Link to post
Share on other sites
As far as sleep()..

A high priority thread, when issuing a sleep(0), will only yield its timeslice to other high priority threads.

sleep(n > 0) works more or less the same regardless of priority (if two threads of different priority are scheduled to resume at the same time, the higher one goes first)

Share this post


Link to post
Share on other sites
Quote:
Original post by uncutno2
Thread one renders the sound, and requires to run as close to realtime as possible (Running on the Win32, non-realtime OS). This thread renders the sound, and should run all the time (I tried to sleep it, but then it sleeps for to long, and the audio outputstream is broken)

I don't know what your particular situation is, but this problem is usually solved by making the audio buffers big enough so that even a long delay will not cause a problem.
Quote:
Original post by uncutno2
This is working but not optimaly, is there a way i can give super-high (max possible) priority to the first thread, but so that it still let the other tread run somethimes? If I sleep a high priority thread, does it wait shorter before returning, then an average priority thread?
The answer to the first question is yes. Run the thread at a high priority and then sleep it when you want to give the lower priority thread a chance to run. The answer to the second question is maybe yes, but not always. Remember that there are other processes that have equal or higher priorities than yours, so your high priority thread could still end up waiting for one of those to complete.

Share this post


Link to post
Share on other sites
Thanks guys!

ok the problem is that it's a realtime audio synthesiser, so i need to reduce the time from when the "player" presses a key to when the output sound changes. This should be about 20ms... Im also simulating sounds (i dont play them back from a file), so a lot of processing have to be done in this small time frame window...

Since this system turns my computer into a synthesiser, i dont care if it blocks out other processes (and im not going to give the system to someone else, so i don't have to be nice :-) )

I have looked at the VST audio plugin SDK and it seems to handle these things very good, but I want my native Win32 version to work whitout VST, and I think the problem now is my threads (that is why im asking for advice on how to pump out more power for this single real-time-ish thread). To much time used by the drawing thread, and more should be given to the sound-simulator thread.

So this is the best solution?:
A = important thread
B = unimportant thread

A run at very high priority, and sleep whenever the soundbuffer is full?
B run at low priority

Should i maybe extend it with:
B checks if soundbuffer is full, and sleeps if it isn't, before it does unimportant stuff?

Share this post


Link to post
Share on other sites
Are you sure that the problem is with the threads fighting for cpu time?

I would think that the big cause of latency would be the audio API and drivers in question. Check out FMOD.

Share this post


Link to post
Share on other sites
Quote:
Original post by uncutno2
Thanks guys!

ok the problem is that it's a realtime audio synthesiser, so i need to reduce the time from when the "player" presses a key to when the output sound changes. This should be about 20ms... Im also simulating sounds (i dont play them back from a file), so a lot of processing have to be done in this small time frame window...
I realise you want realtime sound, but I think you're going a little overboard trying to get the timing accurate. Using a 100ms buffer should still be plenty close enough to real-time sound.

One option to make the threads play nicer together is to have them do less work, i.e burn less CPU cycles to generate the sound samples. In other words, look into optimising the code that generates the sound samples.

Also, have you considered using lock-free data structures for passing data between threads?

Share this post


Link to post
Share on other sites
Tkanks again, i know that reducing the needed CPU cycles also is a must, but I want the absolute maximum out of this system, so if I can do both, that would be nice (I have already optimized most of the heavy code to a degree where every list is hashed, and no multiplications (only + and bitshift) is used under calculations, they are super fast, i have measured them).... Also, all data is lock free, that is why no synchronization is needed, Not a single variable in the whole system needs to be locked (This is also working great). Almost no memory is alocated while the system is running, and little overhead is used (the system is as optimized as it should be).

Im going to change drivers to VST architecture (which uses a dynamic latency always adjusted to be minimal, based on performance), but i want my Win32 version to work as good as possible, so the question remains: How do you get you threads to run as much as possible, and how do you tune your two threads to get appropriate percentages of the processing time?

Share this post


Link to post
Share on other sites
Ok well it sounds like you're doing pretty well then.
However you never know what incredible optimisations someone else might come up with.
In fact if you'd like to think of it as a challenge to optimise your code furthur for you, then feel free to post some. You'll get a few takers I'm sure.

Share this post


Link to post
Share on other sites
Thanks, this is version 3 of my synth, version 1 is 4 years old, and my current version is 8 times faster. From version 1 to version 3 i have changed the whole representation of the sound problem, and reduced representation data with 50%, which means that 50% less calculations are done calculating the same data. After that I have optimized every critical area, and separated the sound-calculating part of the system from the gui, so that they run seperately, and only share a set of controller variables (ex. volum), that dont need to be locked. For example: instead of processing a rendered sinus-wave, I only process 3 variables, the wave's frequency, volume and phase. If i want to pitch the frequency of the sin, i multiply the frequency by two (instead of recalculating the rendered sin)... Because of this i can handle about 10000 different waves or pulses every second, and they are all passed trough a set of dynamic filters which i dynamically connect together with cables within the gui. If I want an extra delay filter somewhere, I add a Delay module, and connect its cables... If I want 55 delay modules, no problems. By having a large set of primitive filters, I can create millions of different sounds and moods. The final rendering of the sin waves is done without floats or doubles, by only adding and bit-shifting. Both the waves volume and frequency changes over time, so this is not trivial.

I have now tried to turn the threads priorities to the maksimum, and my GUI thread sleeps 15 ms after each rendered frame. When using sleep(0), the system froze (no other top priority thread), so now i'm doing 10 ms sleeps (I know win32 cant guarantee anything less then 10 ms). Any other idea? Is there ANY way to squece out more power from the thread shedualing system?

Share this post


Link to post
Share on other sites
Quote:
Original post by uncutno2
Thanks, this is version 3 of my synth, version 1 is 4 years old, and my current version is 8 times faster. From version 1 to version 3 i have changed the whole representation of the sound problem, and reduced representation data with 50%, which means that 50% less calculations are done calculating the same data. After that I have optimized every critical area, and separated the sound-calculating part of the system from the gui, so that they run seperately, and only share a set of controller variables (ex. volum), that dont need to be locked. For example: instead of processing a rendered sinus-wave, I only process 3 variables, the wave's frequency, volume and phase. If i want to pitch the frequency of the sin, i multiply the frequency by two (instead of recalculating the rendered sin)... Because of this i can handle about 10000 different waves or pulses every second, and they are all passed trough a set of dynamic filters which i dynamically connect together with cables within the gui. If I want an extra delay filter somewhere, I add a Delay module, and connect its cables... If I want 55 delay modules, no problems. By having a large set of primitive filters, I can create millions of different sounds and moods. The final rendering of the sin waves is done without floats or doubles, by only adding and bit-shifting. Both the waves volume and frequency changes over time, so this is not trivial.

I have now tried to turn the threads priorities to the maksimum, and my GUI thread sleeps 15 ms after each rendered frame. When using sleep(0), the system froze (no other top priority thread), so now i'm doing 10 ms sleeps (I know win32 cant guarantee anything less then 10 ms). Any other idea? Is there ANY way to squece out more power from the thread shedualing system?
That sounds pretty impressive (excuse the slight pun). I'd love to hear how it sounds.

I wrote a synthesizer once where you could connect up various filters etc. I didn't optimise it that much though, and I don't have the code any more.

Share this post


Link to post
Share on other sites
Krek: Perfect! Just what I was looking for! Superthanks!

iMalc: "I'd love to hear how it sounds."
I can upload a sample, but currently Im optimizing my delay system, so it have to wait until this work is done... By combining different elements you can have hundreds of wildely different sounds, it will also later have a sequencer and a drum-machine (with sinus wave drum clicks).

The synth is supposed to be a live-synth, with a nice fullscreen gui that hides everything you dont need, and let you load/edit/adjust your synth while playing: One hand on the keyboard, and one hand on the mouse wheel controlling parameters :-), Two "smart" shortcut-keys handle all editing and fiksing, so if you dont use those, all keys are for playing only.. the keyboard is a piano-keyboard + i have midi keyboards as well... You can also "paint" sounds with the mouse, so you get sounds like the theremine instrument if you want. Pretty cool, my goal is to use it on stage some day! There will also be a SinusSynth album out once the synth is fully functional, the album will be an experiment on what music can be created by simply adding sinus-waves together, and I have some wild THX-intro-ish sounds :-) Funn stuff if your into noize and harmonies.

Cool that you guys show interest in my project, ill be glad to tell you any detail if you are interested.

Share this post


Link to post
Share on other sites
The synthesizer I wrote wasn't based on sin waves. Intead, you had to set up a plucked-string-filter. This consists of a single spike value in the input which goes through a loop with, a low-pass filter, a delay, and some slight attenuation. It sounded much like a guitar, which is what it actually simluates.

It would be interesting to have an option to switch from sin-wave to saw-tooth wave, and perhaps even square-wave, in your program[smile]

Share this post


Link to post
Share on other sites
Well, the cool thing about sin waves is that you can combine them into other types of waves, for example SAW or SQUARE.

You can find nice formulas here:
http://en.wikipedia.org/wiki/Saw_wave
http://en.wikipedia.org/wiki/Square_wave

The cool thing with this (having all waves consisting of multiple sin waves) is that when you pass your saw wave trough an equalizer or another frequency dependant filter, you simply need to filter each sin wave (An saw wave is actually a sine wave with a lot of higher frequency overtones). Only looking at the saw wave base frequency when equalizing would for example result in a lot of high frequencies passing straight through an low pass filter. By only having sin waves, all equalizers, low-pass filters, high-pass filters, cutoff + resonanse filters etc. automatically work as they are supposed to!

So instead of first creating an saw wave, and then decompose it when doing frequency filters, they all sin waves all the time. (You can actually do a pretty nice SAW wave with only 7 or 8 overtones, and since you cant hear frequencies over 22k (you cant at least play then on an 44.1k output rate)) you only need to add the ones up to this frequency.

Share this post


Link to post
Share on other sites
So you are saying that you get to avoid a fourier transform when filtering? :)

I think performing a fourier is probably the better alternative because it will work regardless of the source of the sound. As is you are forcing the sound to be generated by sine waves when often it is better to simply allow PCM data as a sound source (recorded voices and so forth)

Share this post


Link to post
Share on other sites
No Fourier, and until the final rendering step, each sin wave consists of 4 numbers: frequency, volume, pan and phase. So for every rendered frame (134 samples in 44.1k rate), i only move about 1k of data through the synth.

In regard to any input source, the synth is a synth and not an effect, so midi and other controllers are the only inputs...
The cool thing with this fast approach is that i can combine 30-50 filters to get the perfect sound... If i needed to filter real sounds as input, a lot less could be done per frame, and the synth would be limited alot. Most effect filters with real sound as input, dont have a lot of adjustments, so you need 3000 effects to cover all your needs.

Share this post


Link to post
Share on other sites
http://folk.ntnu.no/oredsson/sinsynth3.jpg

here is a link to an image of how the synth currently looks.
All modules can be moved around, added, removed etc.
While in PLAY mode, all knobs can be turned and buttons pressed!

Share this post


Link to post
Share on other sites

This topic is 3854 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this