返されるデータの解像度について話していると仮定すると、POSIX 仕様は次のようにgettimeofday
述べています。
システム クロックの分解能は規定されていません。
これは、システムが短い期間を追跡する能力が大きく異なる可能性があるという事実によるものです。ISO規格のclock()
機能でも、このような注意点があります。
それを呼び出すのにかかる時間について話している場合、標準はそれらの線に沿ったパフォーマンスについて保証しません。実装は、時間を与える前に完全に自由に125分待つことができますが、そのような実装が市場で多くの成功を収めるとは思えません:-)
限られた解像度の例として、次のコードを入力してシステムで確認しました。
#include <stdio.h>
#include <sys/time.h>
#define NUMBER 30
int main (void) {
struct timeval tv[NUMBER];
int count[NUMBER], i, diff;
gettimeofday (&tv[0], NULL);
for (i = 1; i < NUMBER; i++) {
gettimeofday (&tv[i], NULL);
count[i] = 1;
while ((tv[i].tv_sec == tv[i-1].tv_sec) &&
(tv[i].tv_usec == tv[i-1].tv_usec))
{
count[i]++;
gettimeofday (&tv[i], NULL);
}
}
printf ("%2d: secs = %d, usecs = %6d\n", 0, tv[0].tv_sec, tv[0].tv_usec);
for (i = 1; i < NUMBER; i++) {
diff = (tv[i].tv_sec - tv[i-1].tv_sec) * 1000000;
diff += tv[i].tv_usec - tv[i-1].tv_usec;
printf ("%2d: secs = %d, usecs = %6d, count = %5d, diff = %d\n",
i, tv[i].tv_sec, tv[i].tv_usec, count[i], diff);
}
return 0;
}
コードは基本的に、基になる時間の変化を記録しgettimeofday()
、時間が実際に変化するまでにかかった呼び出しの数を数えます。これはかなり強力なマシン上にあるため、処理能力が不足しているわけではありません (カウントは、5,800 マーク前後の各時間クォンタムを呼び出すことができた頻度を示します。そのクォンタムでいつ開始したgettimeofday()
かわからないため、最初のクォンタムは無視されます)測定値)。
出力は次のとおりです。
0: secs = 1318554836, usecs = 990820
1: secs = 1318554836, usecs = 991820, count = 5129, diff = 1000
2: secs = 1318554836, usecs = 992820, count = 5807, diff = 1000
3: secs = 1318554836, usecs = 993820, count = 5901, diff = 1000
4: secs = 1318554836, usecs = 994820, count = 5916, diff = 1000
5: secs = 1318554836, usecs = 995820, count = 5925, diff = 1000
6: secs = 1318554836, usecs = 996820, count = 5814, diff = 1000
7: secs = 1318554836, usecs = 997820, count = 5814, diff = 1000
8: secs = 1318554836, usecs = 998820, count = 5819, diff = 1000
9: secs = 1318554836, usecs = 999820, count = 5901, diff = 1000
10: secs = 1318554837, usecs = 820, count = 5815, diff = 1000
11: secs = 1318554837, usecs = 1820, count = 5866, diff = 1000
12: secs = 1318554837, usecs = 2820, count = 5849, diff = 1000
13: secs = 1318554837, usecs = 3820, count = 5857, diff = 1000
14: secs = 1318554837, usecs = 4820, count = 5867, diff = 1000
15: secs = 1318554837, usecs = 5820, count = 5852, diff = 1000
16: secs = 1318554837, usecs = 6820, count = 5865, diff = 1000
17: secs = 1318554837, usecs = 7820, count = 5867, diff = 1000
18: secs = 1318554837, usecs = 8820, count = 5885, diff = 1000
19: secs = 1318554837, usecs = 9820, count = 5864, diff = 1000
20: secs = 1318554837, usecs = 10820, count = 5918, diff = 1000
21: secs = 1318554837, usecs = 11820, count = 5869, diff = 1000
22: secs = 1318554837, usecs = 12820, count = 5866, diff = 1000
23: secs = 1318554837, usecs = 13820, count = 5875, diff = 1000
24: secs = 1318554837, usecs = 14820, count = 5925, diff = 1000
25: secs = 1318554837, usecs = 15820, count = 5870, diff = 1000
26: secs = 1318554837, usecs = 16820, count = 5877, diff = 1000
27: secs = 1318554837, usecs = 17820, count = 5868, diff = 1000
28: secs = 1318554837, usecs = 18820, count = 5874, diff = 1000
29: secs = 1318554837, usecs = 19820, count = 5862, diff = 1000
解像度が 1,000 マイクロ秒以下に制限されているように見えることを示しています。もちろん、システムはそれとは異なる場合があります。要するに、実装や環境に依存するということです。
この種の制限を回避する 1 つの方法は、何かを 1 回実行するのではなく、何回か実行してからN
、経過時間を で割ることN
です。
たとえば、関数を呼び出して、タイマーが 125 ミリ秒かかったと言っているとします。これは少し高いと思われます。次に、ループで1000回呼び出して、1000回全体にかかった時間を測定することをお勧めします。
それが 125 秒であることが判明した場合、はい、おそらく遅いです。ただし、27 秒しかかからない場合は、タイマーの解像度が一見大きな時間の原因であることを示しています。これは、反復ごとに 27 ミリ秒に相当するため、他の結果から見たものと同等です。
これを考慮してコードを変更すると、次のようになります。
int main() {
const int count = 1000;
timeval tim;
gettimeofday(&tim, NULL);
double t1 = 1.0e6 * tim.tv_sec + tim.tv_usec;
int v;
for (int i = 0; i < count; ++i)
v = a(3, 4);
gettimeofday(&tim, NULL);
double t2 = 1.0e6 * tim.tv_sec + tim.tv_usec;
cout << v << '\n' << ((t2 - t1) / count) << '\n';
return 0;
}