一定の間隔でイベントを起動するためのビジー待機ループのパフォーマンスを評価しています。私は、次のコードを使用して、いくつかの奇妙な行動に気づいた:ビジー待機ループの可変パフォーマンスですか?
試験機(デュアル14コアE5-2683 V3する@ 2.00Ghz、256ギガバイトDDR4)、forループの20万回の繰り返しで#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
int timespec_subtract(struct timespec *, struct timespec, struct timespec);
int main(int argc, char *argv[]) {
int iterations = atoi(argv[1])+1;
struct timespec t[2], diff;
for (int i = 0; i < iterations; i++) {
clock_gettime(CLOCK_MONOTONIC, &t[0]);
static volatile int i;
for (i = 0; i < 200000; i++)
;
clock_gettime(CLOCK_MONOTONIC, &t[1]);
timespec_subtract(&diff, t[1], t[0]);
printf("%ld\n", diff.tv_sec * 1000000000 + diff.tv_nsec);
}
}
は約1ミリ秒です。またはそうでないかもしれない時間は三時間をシフトダウンするとき
1030854
1060237
1012797
1011479
1025307
1017299
1011001
1038725
1017361
... (about 700 lines later)
638466
638546
638446
640422
638468
638457
638468
638398
638493
640242
... (about 200 lines later)
606460
607013
606449
608813
606542
606484
606990
606436
606491
606466
... (about 3000 lines later)
404367
404307
404309
404306
404270
404370
404280
404395
404342
406005
、彼らは時折、数百回の反復約450usにジャンプアップを除いて、(約2〜3マイクロ秒以内に)ほとんど一貫とどまります。この動作は、同様のマシン上で繰り返し実行されます。
私は、ビジーなループはコンパイラによって最適化できることを理解していますが、ここではそれが問題ではないと思います。私はキャッシュがそれに影響を与えているとは思わない。なぜなら、無効化が行われてはならないし、突然の最適化を説明しないからだ。また、ループカウンタにレジスタintを使用してみましたが、顕著な効果はありませんでした。
何が起こっているのか、これを(もっと)一貫性のあるものにするための考えはありますか?
EDIT:このプログラムをusleep、nanosleep、または10k回の繰り返しで表示すると、すべてのプログラムはtime -v
で約20000個の非自発的コンテキストスイッチを表示します。
ジャンプを呼び出す/スリープ遅延から差し引くことができる時間間隔を計算するためにはgettimeofday使用することができ、おそらくコンテキストスイッチです。 – Mysticial
申し訳ありませんが、あなたのアプローチは完全に間違っています。そういう意味では、aPCのようなシステムでは、本当に信頼できるタイミングを得ることはできません。これは確かにXY問題です。 **実際に**達成したいことと関連するすべての詳細を述べてください。 – Olaf
私が実際に達成したいのは、質問タイトルに述べたように、なぜビジーループのパフォーマンスが変化するのかを理解することです。私は自分のプログラムのタイミングを決める別の方法を知っています。 – Rakurai