00001
00007 #if !defined(INC_UTIL_TIMING_H)
00008
00009 #define INC_UTIL_TIMING_H
00010
00011 #include <oski/timer.h>
00012 #include "stat.h"
00013
00048 #define TIMING_LOOP_CORE( CODE, PRE_CODE, POST_CODE, outer_iters, inner_iters, times ) \
00049 { \
00050 oski_timer_t timer_; \
00051 \
00052 size_t i_outer_; \
00053 \
00054 \
00055 timer_ = oski_CreateTimer(); \
00056 ABORT( timer_ == NULL, TIMING_LOOP_CORE, ERR_OUT_OF_MEMORY ); \
00057 ABORT( (times) == NULL, TIMING_LOOP_CORE, ERR_BAD_ARG ); \
00058 ABORT( (inner_iters) <= 0, TIMING_LOOP_CORE, ERR_BAD_ARG ); \
00059 \
00060 for( i_outer_ = 0; i_outer_ < (outer_iters); i_outer_++ ) \
00061 { \
00062 size_t i_inner; \
00063 { \
00064 PRE_CODE; \
00065 } \
00066 oski_RestartTimer( timer_ ); \
00067 for( i_inner = 0; i_inner < (inner_iters); i_inner++ ) \
00068 { \
00069 CODE; \
00070 } \
00071 oski_StopTimer( timer_ ); \
00072 { \
00073 POST_CODE; \
00074 } \
00075 (times)[i_outer_] = oski_ReadElapsedTime(timer_) / (inner_iters); \
00076 } \
00077 \
00078 oski_DestroyTimer( timer_ ); \
00079 }
00080
00093 #define CALC_MIN_ITERS( CODE, PRE_CODE, POST_CODE, min_time, num_iters ) \
00094 { \
00095 size_t inner_iters_ = 0; \
00096 oski_timer_t timer_ = oski_CreateTimer(); \
00097 double t_cumulative_ = 0.0; \
00098 \
00099 oski_PrintDebugMessage( 1, \
00100 "Estimating minimum # of inner iterations needed" \
00101 " to get %g seconds of execution time...", \
00102 (double)min_time ); \
00103 \
00104 ABORT( timer_ == NULL, CALC_MIN_ITERS, ERR_OUT_OF_MEMORY ); \
00105 \
00106 do \
00107 { \
00108 size_t i_inner; \
00109 inner_iters_ = (inner_iters_ == 0) ? 1 : 2*inner_iters_; \
00110 { \
00111 PRE_CODE; \
00112 } \
00113 oski_RestartTimer( timer_ ); \
00114 for( i_inner = 0; i_inner < inner_iters_; i_inner++ ) \
00115 { \
00116 CODE; \
00117 } \
00118 oski_StopTimer( timer_ ); \
00119 { \
00120 POST_CODE; \
00121 } \
00122 t_cumulative_ += oski_ReadElapsedTime( timer_ ); \
00123 } while( t_cumulative_ < (min_time) ); \
00124 \
00125 oski_DestroyTimer( timer_ ); \
00126 \
00127 \
00128 oski_PrintDebugMessage( 1, "Need at least %d inner iterations.", \
00129 inner_iters_ ); \
00130 (num_iters) = inner_iters_; \
00131 }
00132
00134 #define DUMMY_CODE
00135
00147 #define TIMING_LOOP_BASIC( CODE, num_trials, num_ops, speed ) \
00148 { \
00149 double* outer_times_; \
00150 size_t min_inner_; \
00151 \
00152 outer_times_ = oski_Malloc( double, (num_trials) ); \
00153 ABORT( outer_times_ == NULL, TIMING_LOOP_BASIC, ERR_OUT_OF_MEMORY ); \
00154 \
00155 CALC_MIN_ITERS( CODE, DUMMY_CODE, DUMMY_CODE, .2, min_inner_ ); \
00156 TIMING_LOOP_CORE( CODE, DUMMY_CODE, DUMMY_CODE, \
00157 (num_trials), min_inner_, outer_times_ ); \
00158 (speed) = \
00159 (double)(num_ops) / stat_CalcMin(outer_times_, num_trials); \
00160 \
00161 oski_Free( outer_times_ ); \
00162 }
00163
00164 #endif
00165
00166