3

私は、lmbench の作成者によるMHZ - Anatomy of a Benchmark の論文を読んでいて、ソースと一緒にコードを閲覧していました。

  1. ペーパーは @ MHz からダウンロードできます: マイクロベンチマークの解剖学
  2. ソース コード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);    \
}
  1. 私が理解したことから、BENCH_INNER は、選択したタイミング間隔 (「十分」) の最適な反復回数を自動計算するために使用されます。ループは、5 ミリ秒から 1 秒の範囲で選択したタイミング間隔の少なくとも 95% を占めるコード「loop_body」を反復し続けるまで実行されます。

  2. 簡単にするために、「十分」に 10000 マイクロ秒を考えてみましょう

  3. __iterations = 1 から始めます
  4. 時間の経過とともに、__result > 1.2 * '十分な'、つまり __result > 12000 マイクロ秒の段階に到達したとします。
  5. ここで __result > 150 マイクロ秒なので、先に進んで __iterations の値をスケーリングし、__result が 1.1 * '十分' にほぼ等しくなるようにします。
  6. しかし、__result を再計算する前に、以前の __result > .95 * 'enough' であるため、ループを中断します。
  7. 先に進み、__result の値と変更された値 __iterations を保存します (ここで __result の値は、保存した __iterations の値ではありません)。

そのような場合、コードは __result を再計算すべきではありませんか? 私は何か基本的なことを見逃しましたか?

4

1 に答える 1

6

はい、ここに問題があります。__resultをゼロに設定する必要があります。

そして、私はあなたのコードでもう1つの考えられる問題を見ることができます-結果は0.99*enough、ある場合と0.95*enough他の場合との比較であり、それはタイプミスであることが非常に疑わしいです。このマクロを書き直して、「満足のいく」条件を明示的に示し、ロジックを単純化して、最初に良好な条件を確認することをお勧めします。このような:

#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);    \
}

1<<27, 1.1, 3, 150.0また、、、、、などの意味のある名前を付けるなど、MAX_ITERCORRECTION_RATEの魔法の定数を定義することをお勧めします。INCREASE_RATERESULT_OVERFLOW

于 2013-01-16T07:50:01.940 に答える