aboutsummaryrefslogtreecommitdiff
path: root/modules/benchmark.c
diff options
context:
space:
mode:
authorSimon Quigley <tsimonq2@ubuntu.com>2018-02-27 22:34:48 -0600
committerSimon Quigley <tsimonq2@ubuntu.com>2018-02-27 22:34:48 -0600
commit09fcc751ef158898c315ebc9299a0fa3a722d914 (patch)
tree91116653d831ca5de92274277237ba2a42db3365 /modules/benchmark.c
parent11e616945340e87a1f567ab92e6dfac3068875b1 (diff)
New upstream version 0.5.1+git20180227
Diffstat (limited to 'modules/benchmark.c')
-rw-r--r--modules/benchmark.c440
1 files changed, 208 insertions, 232 deletions
diff --git a/modules/benchmark.c b/modules/benchmark.c
index 857904a8..26de9557 100644
--- a/modules/benchmark.c
+++ b/modules/benchmark.c
@@ -32,48 +32,130 @@
#include "benchmark/bench_results.c"
-void scan_fft(gboolean reload);
-void scan_raytr(gboolean reload);
-void scan_bfsh(gboolean reload);
-void scan_cryptohash(gboolean reload);
-void scan_fib(gboolean reload);
-void scan_nqueens(gboolean reload);
-void scan_zlib(gboolean reload);
-void scan_gui(gboolean reload);
-
-gchar *callback_fft();
-gchar *callback_raytr();
-gchar *callback_bfsh();
-gchar *callback_fib();
-gchar *callback_cryptohash();
-gchar *callback_nqueens();
-gchar *callback_zlib();
-gchar *callback_gui();
-
-static ModuleEntry entries[] = {
- {N_("CPU Blowfish"), "blowfish.png", callback_bfsh, scan_bfsh, MODULE_FLAG_NONE},
- {N_("CPU CryptoHash"), "cryptohash.png", callback_cryptohash, scan_cryptohash, MODULE_FLAG_NONE},
- {N_("CPU Fibonacci"), "nautilus.png", callback_fib, scan_fib, MODULE_FLAG_NONE},
- {N_("CPU N-Queens"), "nqueens.png", callback_nqueens, scan_nqueens, MODULE_FLAG_NONE},
- {N_("CPU Zlib"), "file-roller.png", callback_zlib, scan_zlib, MODULE_FLAG_NONE},
- {N_("FPU FFT"), "fft.png", callback_fft, scan_fft, MODULE_FLAG_NONE},
- {N_("FPU Raytracing"), "raytrace.png", callback_raytr, scan_raytr, MODULE_FLAG_NONE},
-#if !GTK_CHECK_VERSION(3,0,0)
- {N_("GPU Drawing"), "module.png", callback_gui, scan_gui, MODULE_FLAG_NO_REMOTE},
-#endif
- {NULL}
-};
+bench_value bench_results[BENCHMARK_N_ENTRIES];
+
+static void do_benchmark(void (*benchmark_function)(void), int entry);
+static gchar *benchmark_include_results_reverse(bench_value result, const gchar * benchmark);
+static gchar *benchmark_include_results(bench_value result, const gchar * benchmark);
+
+/* ModuleEntry entries, scan_*(), callback_*(), etc. */
+#include "benchmark/benches.c"
static gboolean sending_benchmark_results = FALSE;
+char *bench_value_to_str(bench_value r) {
+ return g_strdup_printf("%lf; %lf; %d", r.result, r.elapsed_time, r.threads_used);
+}
+
+bench_value bench_value_from_str(const char* str) {
+ bench_value ret = EMPTY_BENCH_VALUE;
+ double r, e;
+ int t, c;
+ if (str) {
+ c = sscanf(str, "%lf; %lf; %d", &r, &e, &t);
+ if (c >= 3) {
+ ret.result = r;
+ ret.elapsed_time = e;
+ ret.threads_used = t;
+ }
+ }
+ return ret;
+}
+
typedef struct _ParallelBenchTask ParallelBenchTask;
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;
@@ -94,50 +176,73 @@ static gpointer benchmark_parallel_for_dispatcher(gpointer data)
return return_value;
}
-gdouble benchmark_parallel_for(guint start, guint end,
+/* 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);
+}
+
+/* Note:
+ * benchmark_parallel_for(): element [start] included, but [end] is excluded.
+ * callback(): expected to processes elements [start] through [end] inclusive.
+ */
+bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
gpointer callback, gpointer callback_data) {
gchar *temp;
- guint n_cores, iter_per_core, iter, thread_number = 0;
- gdouble elapsed_time;
+ int cpu_procs, cpu_cores, cpu_threads;
+ guint iter_per_thread, iter, thread_number = 0;
GSList *threads = NULL, *t;
GTimer *timer;
+ bench_value ret = EMPTY_BENCH_VALUE;
+
timer = g_timer_new();
- temp = module_call_method("devices::getProcessorCount");
- n_cores = temp ? atoi(temp) : 1;
- g_free(temp);
+ cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads);
- while (n_cores > 0) {
- iter_per_core = (end - start) / n_cores;
+ 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;
- if (iter_per_core == 0) {
- DEBUG("not enough items per core; disabling one");
- n_cores--;
+ while (ret.threads_used > 0) {
+ iter_per_thread = (end - start) / ret.threads_used;
+
+ if (iter_per_thread == 0) {
+ DEBUG("not enough items per thread; disabling one thread");
+ ret.threads_used--;
} else {
break;
}
}
- DEBUG("processor has %d cores; processing %d elements (%d per core)",
- n_cores, (end - start), iter_per_core);
+ DEBUG("Using %d threads across %d logical processors; processing %d elements (%d per thread)",
+ ret.threads_used, cpu_threads, (end - start), iter_per_thread);
g_timer_start(timer);
- for (iter = start; iter < end; iter += iter_per_core) {
+ for (iter = start; iter < end; ) {
ParallelBenchTask *pbt = g_new0(ParallelBenchTask, 1);
GThread *thread;
- DEBUG("launching thread %d", 1 + (iter / iter_per_core));
+ guint ts = iter, te = iter + iter_per_thread;
+ /* add the remainder of items/iter_per_thread to the last thread */
+ if (end - te < iter_per_thread)
+ te = end;
+ iter = te;
+
+ DEBUG("launching thread %d", 1 + thread_number);
pbt->thread_number = thread_number++;
- pbt->start = iter == 0 ? 0 : iter;
- pbt->end = iter + iter_per_core - 1;
+ pbt->start = ts;
+ pbt->end = te - 1;
pbt->data = callback_data;
pbt->callback = callback;
- if (pbt->end > end)
- pbt->end = end;
-
thread = g_thread_new("dispatcher",
(GThreadFunc)benchmark_parallel_for_dispatcher, pbt);
threads = g_slist_prepend(threads, thread);
@@ -148,18 +253,23 @@ gdouble benchmark_parallel_for(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);
- elapsed_time = g_timer_elapsed(timer, NULL);
+ ret.elapsed_time = g_timer_elapsed(timer, NULL);
g_slist_free(threads);
g_timer_destroy(timer);
- DEBUG("finishing; all threads took %f seconds to finish", elapsed_time);
+ DEBUG("finishing; all threads took %f seconds to finish", ret.elapsed_time);
- return elapsed_time;
+ return ret;
}
static gchar *clean_cpuname(gchar *cpuname)
@@ -212,7 +322,7 @@ static void br_mi_add(char **results_list, bench_result *b, gboolean select) {
*results_list = h_strdup_cprintf("$%s%s$%s=%.2f|%s\n", *results_list,
select ? "*" : "", rkey, ckey,
- b->result, b->machine->cpu_config);
+ b->bvalue.result, b->machine->cpu_config);
moreinfo_add_with_prefix("BENCH", rkey, bench_result_more_info(b) );
@@ -220,7 +330,7 @@ static void br_mi_add(char **results_list, bench_result *b, gboolean select) {
g_free(rkey);
}
-static gchar *__benchmark_include_results(gdouble result,
+static gchar *__benchmark_include_results(bench_value r,
const gchar * benchmark,
ShellOrderType order_type)
{
@@ -232,12 +342,8 @@ static gchar *__benchmark_include_results(gdouble result,
moreinfo_del_with_prefix("BENCH");
- if (result > 0.0) {
- temp = module_call_method("devices::getProcessorCount");
- n_threads = temp ? atoi(temp) : 1;
- g_free(temp); temp = NULL;
-
- b = bench_result_this_machine(benchmark, result, n_threads);
+ if (r.result > 0.0) {
+ b = bench_result_this_machine(benchmark, r);
br_mi_add(&results, b, 1);
temp = bench_result_benchmarkconf_line(b);
@@ -292,76 +398,20 @@ static gchar *__benchmark_include_results(gdouble result,
return return_value;
}
-
-
-static gchar *benchmark_include_results_reverse(gdouble result,
- const gchar * benchmark)
+static gchar *benchmark_include_results_reverse(bench_value result, const gchar * benchmark)
{
- return __benchmark_include_results(result, benchmark,
- SHELL_ORDER_DESCENDING);
+ return __benchmark_include_results(result, benchmark, SHELL_ORDER_DESCENDING);
}
-static gchar *benchmark_include_results(gdouble result,
- const gchar * benchmark)
+static gchar *benchmark_include_results(bench_value result, const gchar * benchmark)
{
- return __benchmark_include_results(result, benchmark,
- SHELL_ORDER_ASCENDING);
-}
-
-gdouble bench_results[BENCHMARK_N_ENTRIES];
-
-gchar *callback_gui()
-{
- return benchmark_include_results_reverse(bench_results[BENCHMARK_GUI],
- "GPU Drawing");
-}
-
-gchar *callback_fft()
-{
- return benchmark_include_results(bench_results[BENCHMARK_FFT],
- "FPU FFT");
-}
-
-gchar *callback_nqueens()
-{
- return benchmark_include_results(bench_results[BENCHMARK_NQUEENS],
- "CPU N-Queens");
-}
-
-gchar *callback_raytr()
-{
- return benchmark_include_results(bench_results[BENCHMARK_RAYTRACE],
- "FPU Raytracing");
-}
-
-gchar *callback_bfsh()
-{
- return benchmark_include_results(bench_results[BENCHMARK_BLOWFISH],
- "CPU Blowfish");
-}
-
-gchar *callback_cryptohash()
-{
- return benchmark_include_results_reverse(bench_results[BENCHMARK_CRYPTOHASH],
- "CPU CryptoHash");
-}
-
-gchar *callback_fib()
-{
- return benchmark_include_results(bench_results[BENCHMARK_FIB],
- "CPU Fibonacci");
-}
-
-gchar *callback_zlib()
-{
- return benchmark_include_results(bench_results[BENCHMARK_ZLIB],
- "CPU Zlib");
+ return __benchmark_include_results(result, benchmark, SHELL_ORDER_ASCENDING);
}
typedef struct _BenchmarkDialog BenchmarkDialog;
struct _BenchmarkDialog {
GtkWidget *dialog;
- double result;
+ bench_value r;
};
static gboolean do_benchmark_handler(GIOChannel *source,
@@ -371,25 +421,19 @@ static gboolean do_benchmark_handler(GIOChannel *source,
BenchmarkDialog *bench_dialog = (BenchmarkDialog*)data;
GIOStatus status;
gchar *result;
- gchar *buffer;
- float float_result;
+ bench_value r = EMPTY_BENCH_VALUE;
status = g_io_channel_read_line(source, &result, NULL, NULL, NULL);
if (status != G_IO_STATUS_NORMAL) {
DEBUG("error while reading benchmark result");
-
- bench_dialog->result = -1.0f;
+ r.result = -1.0f;
+ bench_dialog->r = r;
gtk_widget_destroy(bench_dialog->dialog);
return FALSE;
}
- float_result = strtof(result, &buffer);
- if (buffer == result) {
- DEBUG("error while converting floating point value");
- bench_dialog->result = -1.0f;
- } else {
- bench_dialog->result = float_result;
- }
+ r = bench_value_from_str(result);
+ bench_dialog->r = r;
gtk_widget_destroy(bench_dialog->dialog);
g_free(result);
@@ -412,6 +456,9 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
GSpawnFlags spawn_flags = G_SPAWN_STDERR_TO_DEV_NULL;
gchar *bench_status;
+ bench_value r = EMPTY_BENCH_VALUE;
+ bench_results[entry] = r;
+
bench_status = g_strdup_printf(_("Benchmarking: <b>%s</b>."), entries[entry].name);
shell_view_set_enabled(FALSE);
@@ -427,7 +474,7 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
GtkWidget *content_area;
GtkWidget *hbox;
GtkWidget *label;
-
+
bench_dialog = gtk_dialog_new_with_buttons("",
NULL,
GTK_DIALOG_MODAL,
@@ -442,14 +489,13 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
gtk_box_pack_end(GTK_BOX(hbox), label, TRUE, TRUE, 5);
gtk_container_add(GTK_CONTAINER (content_area), hbox);
gtk_widget_show_all(bench_dialog);
-#else
+#else
bench_dialog = gtk_message_dialog_new(GTK_WINDOW(shell_get_main_shell()->window),
GTK_DIALOG_MODAL,
GTK_MESSAGE_INFO,
GTK_BUTTONS_NONE,
_("Benchmarking. Please do not move your mouse " \
"or press any keys."));
- g_object_set_data(G_OBJECT(bench_dialog), "result", "0.0");
gtk_dialog_add_buttons(GTK_DIALOG(bench_dialog),
_("Cancel"), GTK_RESPONSE_ACCEPT, NULL);
gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(bench_dialog), bench_image);
@@ -461,7 +507,7 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
benchmark_dialog = g_new0(BenchmarkDialog, 1);
benchmark_dialog->dialog = bench_dialog;
- benchmark_dialog->result = -1.0f;
+ benchmark_dialog->r = r;
if (!g_path_is_absolute(params.argv0)) {
spawn_flags |= G_SPAWN_SEARCH_PATH;
@@ -495,7 +541,7 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
kill(bench_pid, SIGINT);
}
- bench_results[entry] = benchmark_dialog->result;
+ bench_results[entry] = benchmark_dialog->r;
g_io_channel_unref(channel);
shell_view_set_enabled(TRUE);
@@ -518,94 +564,6 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
setpriority(PRIO_PROCESS, 0, old_priority);
}
-void scan_gui(gboolean reload)
-{
- SCAN_START();
-
- if (params.run_benchmark) {
- int argc = 0;
-
- ui_init(&argc, NULL);
- }
-
- if (params.gui_running || params.run_benchmark) {
- do_benchmark(benchmark_gui, BENCHMARK_GUI);
- } else {
- bench_results[BENCHMARK_GUI] = 0.0f;
- }
- SCAN_END();
-}
-
-void scan_fft(gboolean reload)
-{
- SCAN_START();
- do_benchmark(benchmark_fft, BENCHMARK_FFT);
- SCAN_END();
-}
-
-void scan_nqueens(gboolean reload)
-{
- SCAN_START();
- do_benchmark(benchmark_nqueens, BENCHMARK_NQUEENS);
- SCAN_END();
-}
-
-void scan_raytr(gboolean reload)
-{
- SCAN_START();
- do_benchmark(benchmark_raytrace, BENCHMARK_RAYTRACE);
- SCAN_END();
-}
-
-void scan_bfsh(gboolean reload)
-{
- SCAN_START();
- do_benchmark(benchmark_fish, BENCHMARK_BLOWFISH);
- SCAN_END();
-}
-
-void scan_cryptohash(gboolean reload)
-{
- SCAN_START();
- do_benchmark(benchmark_cryptohash, BENCHMARK_CRYPTOHASH);
- SCAN_END();
-}
-
-void scan_fib(gboolean reload)
-{
- SCAN_START();
- do_benchmark(benchmark_fib, BENCHMARK_FIB);
- SCAN_END();
-}
-
-void scan_zlib(gboolean reload)
-{
- SCAN_START();
- do_benchmark(benchmark_zlib, BENCHMARK_ZLIB);
- SCAN_END();
-}
-
-const gchar *hi_note_func(gint entry)
-{
- switch (entry) {
- case BENCHMARK_CRYPTOHASH:
- return _("Results in MiB/second. Higher is better.");
-
- case BENCHMARK_ZLIB:
- case BENCHMARK_GUI:
- return _("Results in HIMarks. Higher is better.");
-
- case BENCHMARK_FFT:
- case BENCHMARK_RAYTRACE:
- case BENCHMARK_BLOWFISH:
- case BENCHMARK_FIB:
- case BENCHMARK_NQUEENS:
- return _("Results in seconds. Lower is better.");
- }
-
- return NULL;
-}
-
gchar *hi_module_get_name(void)
{
return g_strdup(_("Benchmarks"));
@@ -658,7 +616,7 @@ static gchar *get_benchmark_results()
if (!scan_callback)
continue;
- if (bench_results[i] < 0.0) {
+ if (bench_results[i].result < 0.0) {
/* benchmark was cancelled */
scan_callback(TRUE);
} else {
@@ -694,7 +652,24 @@ static gchar *run_benchmark(gchar *name)
if ((scan_callback = entries[i].scan_callback)) {
scan_callback(FALSE);
- return g_strdup_printf("%f", bench_results[i]);
+#define CHK_RESULT_FORMAT(F) (params.result_format && strcmp(params.result_format, F) == 0)
+
+ if (params.run_benchmark) {
+ if (CHK_RESULT_FORMAT("conf") ) {
+ bench_result *b = bench_result_this_machine(name, bench_results[i]);
+ char *temp = bench_result_benchmarkconf_line(b);
+ bench_result_free(b);
+ return temp;
+ } else if (CHK_RESULT_FORMAT("shell") ) {
+ bench_result *b = bench_result_this_machine(name, bench_results[i]);
+ char *temp = bench_result_more_info_complete(b);
+ bench_result_free(b);
+ return temp;
+ }
+ /* defaults to "short" which is below*/
+ }
+
+ return bench_value_to_str(bench_results[i]);
}
}
}
@@ -706,7 +681,7 @@ ShellModuleMethod *hi_exported_methods(void)
{
static ShellModuleMethod m[] = {
{"runBenchmark", run_benchmark},
- {NULL}
+ {NULL}
};
return m;
@@ -730,9 +705,10 @@ void hi_module_init(void)
sync_manager_add_entry(&se[0]);
sync_manager_add_entry(&se[1]);
+ bench_value er = EMPTY_BENCH_VALUE;
int i;
for (i = 0; i < G_N_ELEMENTS(entries) - 1; i++) {
- bench_results[i] = -1.0f;
+ bench_results[i] = er;
}
}