私は、lmbench の作成者によるMHZ - Anatomy of a Benchmark の論文を読んでいて、ソースと一緒にコードを閲覧していました。
- ペーパーは @ MHz からダウンロードできます: マイクロベンチマークの解剖学
- ソース コードlmbench-3.0は Carl Staelin と Larry McVoy によって作成されました
BENCH_INNER() マクロの内部では、疑問があります:
#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); \
}
私が理解したことから、BENCH_INNER は、選択したタイミング間隔 (「十分」) の最適な反復回数を自動計算するために使用されます。ループは、5 ミリ秒から 1 秒の範囲で選択したタイミング間隔の少なくとも 95% を占めるコード「loop_body」を反復し続けるまで実行されます。
簡単にするために、「十分」に 10000 マイクロ秒を考えてみましょう
- __iterations = 1 から始めます
- 時間の経過とともに、__result > 1.2 * '十分な'、つまり __result > 12000 マイクロ秒の段階に到達したとします。
- ここで __result > 150 マイクロ秒なので、先に進んで __iterations の値をスケーリングし、__result が 1.1 * '十分' にほぼ等しくなるようにします。
- しかし、__result を再計算する前に、以前の __result > .95 * 'enough' であるため、ループを中断します。
- 先に進み、__result の値と変更された値 __iterations を保存します (ここで __result の値は、保存した __iterations の値ではありません)。
そのような場合、コードは __result を再計算すべきではありませんか? 私は何か基本的なことを見逃しましたか?