C/C++ で発生するタスクを正確にスケジュールできる粒度を判断しようとしています。現時点では、タスクを 5 マイクロ秒ごとに確実にスケジュールできますが、これをさらに下げることができるかどうかを確認しようとしています。
これを達成する方法/可能であればアドバイスをいただければ幸いです。
タイマーの粒度は OS に依存することが多いことを知っているので、現在 Linux で実行していますが、タイミングの粒度がより良い場合は Windows を使用します (ただし、QueryPerformanceCounter で見つけたものに基づいて、そうであるとは思いません)。
ベアメタル (VM なし) ですべての測定を実行します。/proc/timer_info
私のCPUのナノ秒タイマーの解像度を確認します(ただし、ナノ秒のアラーム解像度に変換されないことはわかっています)
現時点の
私の現在のコードは、Gist here として見つけることができます
現時点では、5 マイクロ秒 (5000 ナノ秒) ごとに 1% 未満の到着遅延でリクエストを実行できます。遅延到着が発生した場合、通常は 1 サイクル (5000 ナノ秒) しか遅れていません。
現在3つのことをやっています
プロセスをリアルタイムの優先度に設定します(@ Spudd86 hereによって指摘されたものもあります)
struct sched_param schedparm;
memset(&schedparm, 0, sizeof(schedparm));
schedparm.sched_priority = 99; // highest rt priority
sched_setscheduler(0, SCHED_FIFO, &schedparm);
タイマーのスラックを最小限に抑える
prctl(PR_SET_TIMERSLACK, 1);
timerfds の使用 (2.6 Linux カーネルの一部)
int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
struct itimerspec timspec;
bzero(&timspec, sizeof(timspec));
timspec.it_interval.tv_sec = 0;
timspec.it_interval.tv_nsec = nanosecondInterval;
timspec.it_value.tv_sec = 0;
timspec.it_value.tv_nsec = 1;
timerfd_settime(timerfd, 0, &timspec, 0);
可能な改善
- プロセッサをこのプロセス専用にしますか?
- ブロックするのではなく、タイトなループを作成できるように、ノンブロッキングの timerfd を使用します (タイトなループはより多くの CPU を浪費しますが、アラームへの応答も速くなる可能性があります)。
- トリガーに外部組み込みデバイスを使用する (なぜこれが良いのか想像できません)
どうして
現在、ベンチマーク エンジン用のワークロード ジェネレーターの作成に取り組んでいます。ワークロード ジェネレーターは、ポアソン プロセスを使用して到着率 (X リクエスト/秒など) をシミュレートします。ポアソン プロセスから、ベンチマーク エンジンから要求を行う必要がある相対的な時間を判断できます。
たとえば、1 秒あたり 10 リクエストの場合、t = 0.02、0.04、0.05、0.056、0.09 秒でリクエストが行われる可能性があります。
これらのリクエストは、事前にスケジュールしてから実行する必要があります。1 秒あたりのリクエスト数が増加するにつれて、これらのリクエストのスケジューリングに必要な粒度が増加します (1 秒あたり数千のリクエストにはミリ秒未満の精度が必要です)。その結果、私はこのシステムをさらに拡張する方法を見つけようとしています。