ページ更新: 2013-07-03 (水) (1391日前)

関連: 規格/IEEE/754#ARM VFP, NEON, Java/リフレクション/currentTimeMillisとnanoTimeを選択

(2013-07-01 新規作成)

Raspberry Pi についてのメモ。持ってないけど。

目次

[編集]

ARM1176JZF-S プロセッサ (2013-07-01) #

[編集]

時間計測 (2013-07-03) #

[編集]

libc clock_gettime / clock_getres (2013-07-03) #

以下で、clock_gettime() を使っているようなので、x86 と同様に clock_gettime() が使えそうだ。 (以下は実行時間を計っているわけではないが、clock_gettime() を使っている)

[編集]

clock_gettimeの精度(分解能?) を調べる (2013-07-03) #

(2013-07-03)

clock() や clock_gettime() の値をビジーループで取得して、直前の値と変化していたときに記録するプログラムを作った。

これを実行すれば、clock() や clock_gettime() の実際の精度(分解能?) がわかるはず。

(とはいえ、Raspberry Piを持っていれば、strace/ltrace でトレースしてから、その部分のカーネルやライブラリのコードとハードウェアの仕様をつき合わせれば判るはずだが)

注意:現在は std::vector::push_back() 使っているので、単純な配列+カウンタに置き換えたほうがオーバーヘッドが減って正確になるはず。 (でも、オーバーヘッドは高々 ナノ秒単位だと思ったので、std::vector で済ませている)

check_clock_accurary.cpp

/* how to build: g++ -O2 -Wall -Wextra check_clock_accuracy.cpp -lrt -o accuracy

#include <vector>
#include <cstdio>
#include <ctime>

void
check_clock_accuracy() {
    // check accuracy
    const size_t LIST_MAX = 20;
    std::vector<clock_t> clocks;
    clocks.reserve(LIST_MAX);

    {
        clock_t prev = clock();
        clocks.push_back(prev);

        while (clocks.size() < LIST_MAX) {
             const clock_t curr = clock();
             const clock_t diff = curr - prev;
             if (diff != 0) {
                 clocks.push_back(curr);
             }
             prev = curr;
        }
    }

    if (clocks.empty()) {
        // 
        puts("BUG: clocks is empty\n");
        return;
    }

    // show report
    puts("---------------------------------------------- check_clock");
    printf("CLOCKS_PER_SEC = %ld\n", CLOCKS_PER_SEC);

    {
        clock_t prev = clocks[0];
        for (size_t i = 0, s = clocks.size(); i < s; ++i) {
            const clock_t curr = clocks[i];
            printf("prev %8ld  curr %8ld  accr %8ld\n",
                 prev, curr, (curr - prev));
            prev = curr;
        }
    }
}

void
check_clock_gettime_accuracy(const clockid_t clk_id, char const * const clk_id_name) {
    // check accuracy

    timespec ts;
    const int result = clock_getres(clk_id, &ts);
    if (result != 0) {
        printf("ERROR: clock_getres: %s result=%d\n", clk_id_name, result);
        return;
    }

    const size_t LIST_MAX = 20;
    std::vector<timespec> clocks;
    clocks.reserve(LIST_MAX);

    {
        timespec prev, curr, diff;

        clock_gettime(clk_id, &prev);
        clocks.push_back(prev);

        while (clocks.size() < LIST_MAX) {
             clock_gettime(clk_id, &curr);

             diff.tv_sec  = curr.tv_sec  - prev.tv_sec;
             diff.tv_nsec = curr.tv_nsec - prev.tv_nsec;
             prev = curr;
             if (diff.tv_nsec != 0) {
                 clocks.push_back(curr);
             }
        }
    }

    // show report
    if (clocks.empty()) {
        // 
        printf("BUG: clocks is empty: %s\n", clk_id_name);
        return;
    }

    printf("---------------------------------------------- check_clock_gettime: %s\n", clk_id_name);

    clock_getres(CLOCK_REALTIME, &ts);
    printf("clock_getres: tv_sec=%ld  tv_nsec=%ld\n", ts.tv_sec, ts.tv_nsec);

    {
        timespec prev = clocks[0];
        for (size_t i = 0, s = clocks.size(); i < s; ++i) {
            const timespec curr = clocks[i];
            printf("prev %8ld  curr %8ld  accr %8ld\n",
                 prev.tv_nsec, curr.tv_nsec, (curr.tv_nsec - prev.tv_nsec));
            prev = curr;
        }
    }
}

int
main() {
    check_clock_accuracy();

    check_clock_gettime_accuracy(CLOCK_REALTIME          , "CLOCK_REALTIME");
    //    check_clock_gettime_accuracy(CLOCK_REALTIME_COARSE   , "CLOCK_REALTIME_COARSE");
    check_clock_gettime_accuracy(CLOCK_MONOTONIC         , "CLOCK_MONOTONIC");
    //    check_clock_gettime_accuracy(CLOCK_MONOTONIC_COARSE  , "CLOCK_MONOTONIC_COARSE");
    //    check_clock_gettime_accuracy(CLOCK_MONOTONIC_RAW     , "CLOCK_MONOTONIC_RAW");
    //    check_clock_gettime_accuracy(CLOCK_BOOTTIME          , "CLOCK_BOOTTIME");
    check_clock_gettime_accuracy(CLOCK_PROCESS_CPUTIME_ID, "CLOCK_PROCESS_CPUTIME_ID");
    check_clock_gettime_accuracy(CLOCK_THREAD_CPUTIME_ID , "CLOCK_THREAD_CPUTIME_ID");

    return 0;
}

実行例 (注意: Raspberry Pi ではなく、Pentium 4 3.00GHz を使っている)

---------------------------------------------- check_clock
CLOCKS_PER_SEC = 1000000
prev        0  curr        0  accr        0
prev        0  curr    10000  accr    10000
prev    10000  curr    20000  accr    10000  ★ 10000/1000000 = 0.01秒 = 10ミリ秒
prev    20000  curr    30000  accr    10000
(略)
prev   160000  curr   170000  accr    10000
prev   170000  curr   180000  accr    10000
prev   180000  curr   190000  accr    10000
---------------------------------------------- check_clock_gettime: CLOCK_REALTIME
clock_getres: tv_sec=0  tv_nsec=1
prev 285149564  curr 285149564  accr        0
prev 285149564  curr 285150373  accr      809
prev 285150373  curr 285150992  accr      619 ★ 619 ナノ秒
(略)
prev 285159057  curr 285159634  accr      577
prev 285159634  curr 285160207  accr      573
prev 285160207  curr 285160784  accr      577
---------------------------------------------- check_clock_gettime: CLOCK_MONOTONIC
clock_getres: tv_sec=0  tv_nsec=1
prev 293144044  curr 293144044  accr        0
prev 293144044  curr 293144819  accr      775
prev 293144819  curr 293145513  accr      694
prev 293145513  curr 293146097  accr      584
(略)
prev 293153691  curr 293154274  accr      583
prev 293154274  curr 293154859  accr      585
prev 293154859  curr 293155442  accr      583
---------------------------------------------- check_clock_gettime: CLOCK_PROCESS_CPUTIME_ID
clock_getres: tv_sec=0  tv_nsec=1
prev 196071244  curr 196071244  accr        0
prev 196071244  curr 196072419  accr     1175
prev 196072419  curr 196073288  accr      869
(略)
prev 196085146  curr 196085993  accr      847
prev 196085993  curr 196086842  accr      849
prev 196086842  curr 196087688  accr      846
---------------------------------------------- check_clock_gettime: CLOCK_THREAD_CPUTIME_ID
clock_getres: tv_sec=0  tv_nsec=1
prev 196106147  curr 196106147  accr        0
prev 196106147  curr 196107094  accr      947
prev 196107094  curr 196107945  accr      851
(略)
prev 196118944  curr 196119731  accr      787
prev 196119731  curr 196120515  accr      784
prev 196120515  curr 196121302  accr      787
[編集]

ARM11 C15 register と Linux kernel での利用箇所 #

kernel: