diff options
-rw-r--r-- | includes/benchmark.h | 5 | ||||
-rw-r--r-- | modules/benchmark.c | 102 |
2 files changed, 106 insertions, 1 deletions
diff --git a/includes/benchmark.h b/includes/benchmark.h index 975b7197..fa4ad0cf 100644 --- a/includes/benchmark.h +++ b/includes/benchmark.h @@ -41,6 +41,11 @@ bench_value bench_value_from_str(const char* str); bench_value benchmark_parallel_for(gint n_threads, guint start, guint end, gpointer callback, gpointer callback_data); +bench_value benchmark_parallel(gint n_threads, gpointer callback, gpointer callback_data); + +bench_value benchmark_crunch_for(float seconds, gint n_threads, + gpointer callback, gpointer callback_data); + extern bench_value bench_results[BENCHMARK_N_ENTRIES]; #endif /* __BENCHMARK_H__ */ diff --git a/modules/benchmark.c b/modules/benchmark.c index ed23243b..62720530 100644 --- a/modules/benchmark.c +++ b/modules/benchmark.c @@ -91,8 +91,94 @@ struct _ParallelBenchTask { gint thread_number; guint start, end; gpointer data, callback; + int *stop; }; +static gpointer benchmark_crunch_for_dispatcher(gpointer data) +{ + ParallelBenchTask *pbt = (ParallelBenchTask *)data; + gpointer (*callback)(void *data, gint thread_number); + gpointer return_value = g_malloc(sizeof(int)); + int count = 0; + + if ((callback = pbt->callback)) { + while(!*pbt->stop) { + callback(pbt->data, pbt->thread_number); + /* don't count if didn't finish in time */ + if (!*pbt->stop) + count++; + } + } else { + DEBUG("this is thread %p; callback is NULL and it should't be!", g_thread_self()); + } + + g_free(pbt); + + *(double*)return_value = (double)count; + return return_value; +} + +bench_value benchmark_crunch_for(float seconds, gint n_threads, + gpointer callback, gpointer callback_data) { + int cpu_procs, cpu_cores, cpu_threads, thread_number, stop = 0; + GSList *threads = NULL, *t; + GTimer *timer; + bench_value ret = EMPTY_BENCH_VALUE; + + timer = g_timer_new(); + + cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads); + if (n_threads > 0) + ret.threads_used = n_threads; + else if (n_threads < 0) + ret.threads_used = cpu_cores; + else + ret.threads_used = cpu_threads; + + g_timer_start(timer); + for (thread_number = 0; thread_number < ret.threads_used; thread_number++) { + ParallelBenchTask *pbt = g_new0(ParallelBenchTask, 1); + GThread *thread; + + DEBUG("launching thread %d", thread_number); + + pbt->thread_number = thread_number; + pbt->data = callback_data; + pbt->callback = callback; + pbt->stop = &stop; + + thread = g_thread_new("dispatcher", + (GThreadFunc)benchmark_crunch_for_dispatcher, pbt); + threads = g_slist_prepend(threads, thread); + + DEBUG("thread %d launched as context %p", thread_number, thread); + } + + /* wait for time */ + //while ( g_timer_elapsed(timer, NULL) < seconds ) { } + g_usleep(seconds * 1000000); + + /* signal all threads to stop */ + stop = 1; + g_timer_stop(timer); + + ret.result = 0; + DEBUG("waiting for all threads to finish"); + for (t = threads; t; t = t->next) { + DEBUG("waiting for thread with context %p", t->data); + gpointer *rv = g_thread_join((GThread *)t->data); + ret.result += *(double*)rv; + g_free(rv); + } + + ret.elapsed_time = g_timer_elapsed(timer, NULL); + + g_slist_free(threads); + g_timer_destroy(timer); + + return ret; +} + static gpointer benchmark_parallel_for_dispatcher(gpointer data) { ParallelBenchTask *pbt = (ParallelBenchTask *)data; @@ -113,6 +199,15 @@ static gpointer benchmark_parallel_for_dispatcher(gpointer data) return return_value; } +/* one call for each thread to be used */ +bench_value benchmark_parallel(gint n_threads, gpointer callback, gpointer callback_data) { + int cpu_procs, cpu_cores, cpu_threads; + cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads); + if (n_threads == 0) n_threads = cpu_threads; + else if (n_threads == -1) n_threads = cpu_cores; + return benchmark_parallel_for(n_threads, 0, n_threads, callback, callback_data); +} + bench_value benchmark_parallel_for(gint n_threads, guint start, guint end, gpointer callback, gpointer callback_data) { gchar *temp; @@ -174,7 +269,12 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end, DEBUG("waiting for all threads to finish"); for (t = threads; t; t = t->next) { DEBUG("waiting for thread with context %p", t->data); - g_thread_join((GThread *)t->data); + gpointer *rv = g_thread_join((GThread *)t->data); + if (rv) { + if (ret.result == -1.0) ret.result = 0; + ret.result += *(double*)rv; + } + g_free(rv); } g_timer_stop(timer); |