diff options
| -rw-r--r-- | include/gensvm_timer.h | 5 | ||||
| -rw-r--r-- | src/gensvm_gridsearch.c | 22 | ||||
| -rw-r--r-- | src/gensvm_timer.c | 34 | ||||
| -rw-r--r-- | tests/src/test_gensvm_timer.c | 34 |
4 files changed, 76 insertions, 19 deletions
diff --git a/include/gensvm_timer.h b/include/gensvm_timer.h index 563576b..5dd4dcb 100644 --- a/include/gensvm_timer.h +++ b/include/gensvm_timer.h @@ -15,7 +15,10 @@ // includes #include "gensvm_globals.h" +/// Timer macro for easily recording time +#define Timer(spec) clock_gettime(CLOCK_MONOTONIC_RAW, &spec) + // function declarations -double gensvm_elapsed_time(clock_t s_time, clock_t e_time); +double gensvm_elapsed_time(struct timespec *start, struct timespec *stop); #endif diff --git a/src/gensvm_gridsearch.c b/src/gensvm_gridsearch.c index 50b0020..a79c31e 100644 --- a/src/gensvm_gridsearch.c +++ b/src/gensvm_gridsearch.c @@ -283,7 +283,7 @@ void consistency_repeats(struct GenQueue *q, long repeats, TrainType traintype) **test_folds = NULL; struct GenModel *model = gensvm_init_model(); struct GenTask *task = NULL; - clock_t loop_s, loop_e; + struct timespec loop_s, loop_e; nq = create_top_queue(q); N = nq->N; @@ -328,11 +328,11 @@ void consistency_repeats(struct GenQueue *q, long repeats, TrainType traintype) test_folds[f]); } - loop_s = clock(); + Timer(loop_s); p = gensvm_cross_validation(model, train_folds, test_folds, task->folds, task->train_data->n); - loop_e = clock(); - time[i] += gensvm_elapsed_time(loop_s, loop_e); + Timer(loop_e); + time[i] += gensvm_elapsed_time(&loop_s, &loop_e); matrix_set(perf, repeats, i, r, p); mean[i] += p/((double) repeats); note("%3.3f\t", p); @@ -476,7 +476,7 @@ void start_training(struct GenQueue *q) struct GenTask *task = get_next_task(q); struct GenTask *prevtask = NULL; struct GenModel *model = gensvm_init_model(); - clock_t main_s, main_e, loop_s, loop_e; + struct timespec main_s, main_e, loop_s, loop_e; // in principle this can change between tasks, but this shouldn't be // the case TODO @@ -500,7 +500,7 @@ void start_training(struct GenQueue *q) test_folds[f], cv_idx, f); } - main_s = clock(); + Timer(main_s); while (task) { make_model_from_task(task, model); if (kernel_changed(task, prevtask)) { @@ -519,24 +519,24 @@ void start_training(struct GenQueue *q) } print_progress_string(task, q->N); - loop_s = clock(); + Timer(loop_s); perf = gensvm_cross_validation(model, train_folds, test_folds, folds, task->train_data->n); - loop_e = clock(); + Timer(loop_e); current_max = maximum(current_max, perf); note("\t%3.3f%% (%3.3fs)\t(best = %3.3f%%)\n", perf, - gensvm_elapsed_time(loop_s, loop_e), + gensvm_elapsed_time(&loop_s, &loop_e), current_max); q->tasks[task->ID]->performance = perf; prevtask = task; task = get_next_task(q); } - main_e = clock(); + Timer(main_e); note("\nTotal elapsed training time: %8.8f seconds\n", - gensvm_elapsed_time(main_s, main_e)); + gensvm_elapsed_time(&main_s, &main_e)); // make sure no double free occurs with the copied kernelparam model->kernelparam = NULL; diff --git a/src/gensvm_timer.c b/src/gensvm_timer.c index 04d93b1..0e020fe 100644 --- a/src/gensvm_timer.c +++ b/src/gensvm_timer.c @@ -1,25 +1,45 @@ /** - * @file timer.c + * @file gensvm_timer.c * @author Gertjan van den Burg * @date January, 2014 * @brief Utility functions relating to time * * @details * This file contains a simple function for calculating the time in seconds - * elapsed between two clock() calls. + * elapsed between two Timer() calls. * */ #include "gensvm_timer.h" /** - * @brief Calculate the time between two clocks + * @brief Calculate the time between two time recordings * - * @param[in] s_time starting time - * @param[in] e_time end time + * @detail + * This function should be used with time recordings done by clock_gettime() + * using CLOCK_MONOTONIC_RAW. For this, the Timer() macro has been defined in + * the header file. Example usage: + * + * @code + * struct timespec start, stop; + * Timer(start); + * // do some work // + * Timer(stop); + * double duration = gensvm_elapsed_time(&start, &stop); + * @endcode + * + * This approach to measuring time has been chosen since CLOCK_MONOTONIC_RAW + * is guaranteed to be monotonically increasing, and is not affected by leap + * seconds or other changes to the system clock. It is therefore thread-safe + * and can be used to accurately measure time intervals. + * + * @param[in] start starting time + * @param[in] stop end time * @returns time elapsed in seconds */ -double gensvm_elapsed_time(clock_t s_time, clock_t e_time) +double gensvm_elapsed_time(struct timespec *start, struct timespec *stop) { - return ((double) (e_time - s_time))/((double) CLOCKS_PER_SEC); + double delta_s = stop->tv_sec - start->tv_sec; + double delta_ns = stop->tv_nsec - start->tv_nsec; + return delta_s + delta_ns * 1e-9; } diff --git a/tests/src/test_gensvm_timer.c b/tests/src/test_gensvm_timer.c new file mode 100644 index 0000000..78e968f --- /dev/null +++ b/tests/src/test_gensvm_timer.c @@ -0,0 +1,34 @@ +/** + * @file test_gensvm_timer.c + * @author Gertjan van den Burg + * @date October, 2016 + * @brief Unit tests for gensvm_timer.c functions + * + */ + +#include "minunit.h" +#include "gensvm_timer.h" + +char *test_timer() +{ + struct timespec start, stop; + Timer(start); + + stop.tv_sec = start.tv_sec + 1; + stop.tv_nsec = start.tv_nsec; + + mu_assert(gensvm_elapsed_time(&start, &stop) == 1.0, + "Incorrect time computed"); + + return NULL; +} + +char *all_tests() +{ + mu_suite_start(); + mu_run_test(test_timer); + + return NULL; +} + +RUN_TESTS(all_tests); |
