ページ更新: 2013-07-03 (水) (3495日前)
関連: 規格/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:
|