I was reading the MHZ - Anatomy of a Benchmark paper by the creators of lmbench and source browsing the code alongside.
Inside the BENCH_INNER() macro I have a doubt :
#define BENCH_INNER(loop_body, enough) { \
static iter_t __iterations = 1; \
int __enough = get_enough(enough); \
iter_t __n; \
double __result = 0.; \
\
while(__result < 0.95 * __enough) { \
start(0); \
for (__n = __iterations; __n > 0; __n--) { \
loop_body; \
} \
__result = stop(0,0); \
if (__result < 0.99 * __enough \
|| __result > 1.2 * __enough) { \
if (__result > 150.) { \
double tmp = __iterations / __result; \
tmp *= 1.1 * __enough; \
__iterations = (iter_t)(tmp + 1); \
} else { \
if (__iterations > (iter_t)1<<27) { \
__result = 0.; \
break; \
} \
__iterations <<= 3; \
} \
} \
} /* while */ \
save_n((uint64)__iterations); settime((uint64)__result); \
}
From what I understood, BENCH_INNER is used to auto compute the optimal number of iterations for a chosen timing interval ('enough'). The loop executes till we keep iterating over a piece of code 'loop_body' that would take at least 95% of our chosen timing interval which could range from 5ms to a 1second.
For simplicity sake let us take 'enough' to be 10000 microseconds
Shouldn't the code in such a case recompute __result ? Did I miss something fundamental ?
Yes there is a problem here, __result must be set to zero.
And I can see one more possible problem in your code -- result is comparing with0.99*enough in one case and with0.95*enough in other case, that is highly suspicious to be a typo. I suggest you to rewrite this macro, explicitly stating "satisfying" conditions and to simplify logic, checking good conditions first. Like this:
#define SEARCH_EXIT_CASE(__result, __enough) ((__result) > 0.95 * (__enough) && (__result) < 1.2 * (__enough))
#define BENCH_INNER(loop_body, enough) { \
static iter_t __iterations = 1; \
int __enough = get_enough(enough); \
iter_t __n; \
double __result = 0.; \
\
while(!SEARCH_EXIT_CASE(__result, __enough)) { \
start(0); \
for (__n = __iterations; __n > 0; __n--) { \
loop_body; \
} \
__result = stop(0,0); \
/* good result */ \
if (SEARCH_EXIT_CASE(__result, __enough)) { \
break; \
} \
/* failure cases */ \
if (__result > 150.) { \
double tmp = __iterations / __result; \
tmp *= 1.1 * __enough; \
__iterations = (iter_t)(tmp + 1); \
} else { \
if (__iterations > (iter_t)1<<27) { \
__result = 0.; \
break; \
} \
__iterations <<= 3; \
} \
__result = 0.; \
} /* while */ \
save_n((uint64)__iterations); settime((uint64)__result); \
}
Also I suggest to define other magical constants like 1<<27, 1.1, 3, 150.0 to have meaningful names likeMAX_ITER, CORRECTION_RATE,INCREASE_RATE,RESULT_OVERFLOW, etc...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With