Small optimization by not starting threads not likely to be used

This commit is contained in:
David Henningsson 2010-09-12 20:10:42 +00:00
parent 5a21df18a6
commit b86c115898

View file

@ -31,6 +31,10 @@
#define ENABLE_MIXER_THREADS 1 #define ENABLE_MIXER_THREADS 1
// If less than x voices, the thread overhead is larger than the gain,
// so don't activate the thread(s).
#define VOICES_PER_THREAD 8
typedef struct _fluid_mixer_buffers_t fluid_mixer_buffers_t; typedef struct _fluid_mixer_buffers_t fluid_mixer_buffers_t;
struct _fluid_mixer_buffers_t { struct _fluid_mixer_buffers_t {
@ -700,6 +704,7 @@ fluid_mixer_get_mt_rvoice(fluid_rvoice_mixer_t* mixer)
#define THREAD_BUF_PROCESSING 0 #define THREAD_BUF_PROCESSING 0
#define THREAD_BUF_VALID 1 #define THREAD_BUF_VALID 1
#define THREAD_BUF_NODATA 2 #define THREAD_BUF_NODATA 2
#define THREAD_BUF_TERMINATE 3
/* Core thread function (processes voices in parallel to primary synthesis thread) */ /* Core thread function (processes voices in parallel to primary synthesis thread) */
static void static void
@ -721,8 +726,12 @@ fluid_mixer_thread_func (void* data)
fluid_cond_mutex_unlock(mixer->thread_ready_m); fluid_cond_mutex_unlock(mixer->thread_ready_m);
fluid_cond_mutex_lock(mixer->wakeup_threads_m); fluid_cond_mutex_lock(mixer->wakeup_threads_m);
if (fluid_atomic_int_get(&buffers->ready) != THREAD_BUF_PROCESSING) while (1) {
int j = fluid_atomic_int_get(&buffers->ready);
if (j == THREAD_BUF_PROCESSING || j == THREAD_BUF_TERMINATE)
break;
fluid_cond_wait(mixer->wakeup_threads, mixer->wakeup_threads_m); fluid_cond_wait(mixer->wakeup_threads, mixer->wakeup_threads_m);
}
fluid_cond_mutex_unlock(mixer->wakeup_threads_m); fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
hasValidData = 0; hasValidData = 0;
@ -774,13 +783,13 @@ fluid_mixer_buffers_mix(fluid_mixer_buffers_t* dest, fluid_mixer_buffers_t* src)
* Go through all threads and see if someone is finished for mixing * Go through all threads and see if someone is finished for mixing
*/ */
static FLUID_INLINE int static FLUID_INLINE int
fluid_mixer_mix_in(fluid_rvoice_mixer_t* mixer) fluid_mixer_mix_in(fluid_rvoice_mixer_t* mixer, int extra_threads)
{ {
int i, result, hasmixed; int i, result, hasmixed;
do { do {
hasmixed = 0; hasmixed = 0;
result = 0; result = 0;
for (i=0; i < mixer->thread_count; i++) { for (i=0; i < extra_threads; i++) {
int j = fluid_atomic_int_get(&mixer->threads[i].ready); int j = fluid_atomic_int_get(&mixer->threads[i].ready);
switch (j) { switch (j) {
case THREAD_BUF_PROCESSING: case THREAD_BUF_PROCESSING:
@ -800,23 +809,33 @@ fluid_mixer_mix_in(fluid_rvoice_mixer_t* mixer)
static void static void
fluid_render_loop_multithread(fluid_rvoice_mixer_t* mixer) fluid_render_loop_multithread(fluid_rvoice_mixer_t* mixer)
{ {
int i; //, test=0, waits=0; int i, bufcount;
//int scount = mixer->current_blockcount * FLUID_BUFSIZE; //int scount = mixer->current_blockcount * FLUID_BUFSIZE;
FLUID_DECLARE_VLA(fluid_real_t*, bufs, FLUID_DECLARE_VLA(fluid_real_t*, bufs,
mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2); mixer->buffers.buf_count * 2 + mixer->buffers.fx_buf_count * 2);
int bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs); // How many threads should we start this time?
int extra_threads = mixer->active_voices / VOICES_PER_THREAD;
if (extra_threads > mixer->thread_count)
extra_threads = mixer->thread_count;
if (extra_threads == 0) {
// No extra threads? No thread overhead!
fluid_render_loop_singlethread(mixer);
return;
}
bufcount = fluid_mixer_buffers_prepare(&mixer->buffers, bufs);
// Prepare voice list // Prepare voice list
fluid_cond_mutex_lock(mixer->wakeup_threads_m); fluid_cond_mutex_lock(mixer->wakeup_threads_m);
fluid_atomic_int_set(&mixer->current_rvoice, 0); fluid_atomic_int_set(&mixer->current_rvoice, 0);
for (i=0; i < mixer->thread_count && i < (mixer->active_voices-1); i++) for (i=0; i < extra_threads; i++)
fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_PROCESSING); fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_PROCESSING);
// Signal threads to wake up // Signal threads to wake up
fluid_cond_broadcast(mixer->wakeup_threads); fluid_cond_broadcast(mixer->wakeup_threads);
fluid_cond_mutex_unlock(mixer->wakeup_threads_m); fluid_cond_mutex_unlock(mixer->wakeup_threads_m);
// If thread is finished, mix it in // If thread is finished, mix it in
while (fluid_mixer_mix_in(mixer)) { while (fluid_mixer_mix_in(mixer, extra_threads)) {
// Otherwise get a voice and render it // Otherwise get a voice and render it
fluid_rvoice_t* rvoice = fluid_mixer_get_mt_rvoice(mixer); fluid_rvoice_t* rvoice = fluid_mixer_get_mt_rvoice(mixer);
if (rvoice != NULL) { if (rvoice != NULL) {
@ -830,7 +849,7 @@ fluid_render_loop_multithread(fluid_rvoice_mixer_t* mixer)
int is_processing = 0; int is_processing = 0;
//waits++; //waits++;
fluid_cond_mutex_lock(mixer->thread_ready_m); fluid_cond_mutex_lock(mixer->thread_ready_m);
for (i=0; i < mixer->thread_count; i++) for (i=0; i < extra_threads; i++)
if (fluid_atomic_int_get(&mixer->threads[i].ready) == if (fluid_atomic_int_get(&mixer->threads[i].ready) ==
THREAD_BUF_PROCESSING) THREAD_BUF_PROCESSING)
is_processing = 1; is_processing = 1;
@ -862,6 +881,8 @@ fluid_rvoice_mixer_set_threads(fluid_rvoice_mixer_t* mixer, int thread_count,
fluid_atomic_int_set(&mixer->threads_should_terminate, 1); fluid_atomic_int_set(&mixer->threads_should_terminate, 1);
// Signal threads to wake up // Signal threads to wake up
fluid_cond_mutex_lock(mixer->wakeup_threads_m); fluid_cond_mutex_lock(mixer->wakeup_threads_m);
for (i=0; i < mixer->thread_count; i++)
fluid_atomic_int_set(&mixer->threads[i].ready, THREAD_BUF_TERMINATE);
fluid_cond_broadcast(mixer->wakeup_threads); fluid_cond_broadcast(mixer->wakeup_threads);
fluid_cond_mutex_unlock(mixer->wakeup_threads_m); fluid_cond_mutex_unlock(mixer->wakeup_threads_m);