2012-01-28 27 views
5

私は数ミリ秒の短い時間間隔を測定しようとしています。ユビキタスなtime()関数は全秒精度で動作するため、これは重要な作業ではありません。いくつかの研究の後、私は以下のコードサンプルで見られる4つの方法で出てきた:私はのカップルを紹介するgetchar()コールを使用Ubuntu/VMwareでCで短い時間間隔を測定する

gcc -lrt -o timer.e timer.c; time ./timer.e 

:次に

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <sys/time.h> 

int main(int argc, char *argv[]) 
{ 
    clock_t t0, t1; 
    double dt0; 

    struct timespec t2, t3; 
    double dt1; 

    struct timespec t4, t5; 
    double dt2; 

    struct timeval t6, t7; 
    double dt3; 

    volatile long long i; 

    t2.tv_sec = 0; 
    t2.tv_nsec = 0; 
    clock_settime(CLOCK_MONOTONIC, &t2); 
    clock_settime(CLOCK_REALTIME, &t2); 

    t0 = clock(); 
    clock_gettime(CLOCK_REALTIME, &t2); 
    clock_gettime(CLOCK_MONOTONIC, &t4); 
    gettimeofday(&t6, NULL); 

    getchar(); 
    for (i=0; i<1e9; i++) {}; 

    gettimeofday(&t7, NULL); 
    clock_gettime(CLOCK_MONOTONIC, &t5); 
    clock_gettime(CLOCK_REALTIME, &t3); 
    t1 = clock(); 

    dt0 = (double) (t1 - t0)/CLOCKS_PER_SEC; 
    dt1 = (double) (t3.tv_nsec - t2.tv_nsec)/1e9; 
    dt2 = (double) (t5.tv_nsec - t4.tv_nsec)/1e9; 
    dt3 = (double) (t7.tv_usec - t6.tv_usec)/1e6; 

    printf("1. clock():   [0]=%10.0f, [1]=%10.0f, [1-0]=%10.6f sec\n", (double) t0, (double) t1, dt0); 
    printf("2. clock_gettime(R): [2]=%10ld, [3]=%10ld, [3-2]=%10f sec\n", (long) t2.tv_nsec, (long) t3.tv_nsec, dt1); 
    printf("3. clock_gettime(M): [2]=%10ld, [3]=%10ld, [3-2]=%10f sec\n", (long) t4.tv_nsec, (long) t5.tv_nsec, dt2); 
    printf("4. gettimeofday(): [4]=%10ld, [5]=%10ld, [5-4]=%10f sec\n", (long) t6.tv_usec, (long) t7.tv_usec, dt3); 

    return 0; 
} 

、私はコンパイルして、それを実行します秒はrealuser時間レポートの違いを見るために遅らせ、その結果は以下のとおりであった:

1. clock():   [0]=   0, [1]= 3280000, [1-0]= 3.280000 sec 
2. clock_gettime(R): [2]= 823922476, [3]= 478650549, [3-2]= -0.345272 sec 
3. clock_gettime(M): [2]= 671137949, [3]= 325864897, [3-2]= -0.345273 sec 
4. gettimeofday(): [4]= 823924, [5]= 478648, [5-4]= -0.345276 sec 

real 0m6.659s 
user 0m3.280s 
sys  0m0.010s 

あなたが見ることができるように、唯一の意味のある結果は、方法1とtimeコマンドによって報告された時刻userの間の相関関係です。

これは2つの質問をもたらします: 1.なぜ結果2-4が無意味なのですか? 2. realの番号timeのように、プログラムの実行に費やしたリアルタイムを測定するにはどうすればよいですか?

私の環境は、AMDベースのHPノートPCのWindows 7のVMwareのUbuntu 10.04 LTS 64ビットです。

+0

これはテスト目的であるならば、あなたはそれが役に立つ反復回数を増やすことかもしれません。もちろん、このテストは長く実行されますが、より低い解像度のタイミング測定を使用することができます。 –

+0

@MichaelMior - これは非常にラフなベンチマークに使用されています。ホスト(Linux)上で実行されるアルゴリズムと、USB経由で接続されたハードウェアアクセラレータの実行時間を比較しようとしています。どちらの場合でも、発信者は同じプログラム、ホストプログラムであり、外部ハードウェアが作業を完了するのに「待っている」という合計時間を得る方法が必要です。これは、clock()が答えではないためです。b/c(getchar()コールでここに示すように)待機時間にカウントされません。 – ysap

答えて

12

あなたはclock_gettime()と正しい軌道に乗っています。

しかし、あなたはclock_settime()コールを取り除く必要があります:単にコードブロックの前と後にclock_gettime()と呼んで違いを見てください。

また、差を計算するときは、tv_sectv_nsecの両方を考慮する必要があります。現在のコードでは、ナノ秒のコンポーネントを調べ、フル秒を無視します。私のUbuntuシステムに

次のコードは、ループを実行するのにかかる時間のかなり正確な測定を提供します:

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#include <sys/time.h> 

int main(int argc, char *argv[]) 
{ 
    struct timespec t2, t3; 
    double dt1; 

    volatile long long i; 

    clock_gettime(CLOCK_MONOTONIC, &t2); 
    for (i=0; i<1e9; i++) {}; 
    clock_gettime(CLOCK_MONOTONIC, &t3); 
    //time in seconds 
    dt1 = (t3.tv_sec - t2.tv_sec) + (double) (t3.tv_nsec - t2.tv_nsec) * 1e-9; 
    printf("%f\n", dt1); 

    return 0; 
} 
+0

ありがとう!この訂正は、私が探していることを行います。たまには、明白なことを見逃すだけです。私は、_secと_nsecフィールドが異なる精度で同じデータを扱っていると考えましたが、今はタイムスタンプの全体とナノ秒の部分です。 – ysap

1

いくつかのダウンマイクロまでの時間を測定に関するヒントもナノ秒http://en.wikipedia.org/wiki/Time_Stamp_Counter

+0

rdtscの説明を指摘してくれてありがとう。いくつかのコンテキストで役に立つかもしれませんが、私が書いたコードが期待した結果をもたらさない理由を理解しようとしています。 – ysap

1

あなたの電話番号clock_settimeはあなたの意見ではありません。あなたが許可を持っていれば、システムワイドクロックを0に設定するだけで、おそらくあなたが望むものではないでしょう。ほぼすべてのPOSIX関数には、呼び出しが成功したかどうかを示す戻り値があります。通常、その値を無視するのは悪い考えです。特に、あなたのケースのために私はそれがmanページで見つけることができるよう、それはこの値を与えているはずだと思います:

EPERMのがclock_settime()クロック 指示を設定する権限がありません。

幸いにも、あなたは、単にこのように、クロックを設定する権限がありません:)

+0

gettimeから奇妙な結果を受け取った後、settimeを追加しました。明らかに、結果には何の影響も与えませんでした。 – ysap

+0

@ysap、これはまさに私が言っていることです。 **失敗したため、結果には何の影響もありません。それ以外の場合は、システムクロックを1970年1月1日などに設定して、マシンに劇的な影響を与えます。それをしないでください。システムコールが成功したかどうかを確認してください。 –

+0

はい、このコードはプログラムから削除されました。 – ysap

関連する問題