4

私は現在、リアルタイムでデータをポーリング、処理、および表示する必要があるプログラムのために、C++ で GUI を開発しています。

私が苦労している部分は、別のスレッドで実行され、実際に外部ハードウェアからデータをポーリングして処理するコードです。この作業を行う関数を、一定の周期で定期的に呼び出したい (つまり、呼び出し間の 1/20 秒)。

それが可能かどうか、また、関数を定期的に、1 秒あたり正確に 20 回呼び出す必要があるという事実を強制する方法がわかりません...

リアルタイム プログラミングについて少し読んだ後、特にゲーム開発とメイン ゲーム ループの概念で学んだことに基づいて、私の最初のアプローチは、実行時間に基づいて実行時間を調整するループを使用することです。ポーリング + 処理にかかった時間:

 while(running){
     //Let's assume this function get the time elapsed since
     //the program started
     int start = get_current_time_millisecond();

     //Retrieve the data from the hardware
     pollData();

     //Process the data retrieved
     processData();

     //Queue the data wherever it is needed:
     //- plotting widget of the GUI
     //- recording object
     dispatchProcessedData();

     int elapsed = get_current_time_millisecond() - start;
     int remaining = 50 - elapsed;

     if(remaining > 0){
         sleep(remaining);
     }
 }

しかし、1 回の反復中に経過した時間が、私が固執したい期間よりも長い場合、ドリフトの問題が発生する可能性があるため、これには欠陥があるようです。

これは、計算に時間がかかりすぎるという事実に起因する可能性があります (私はそれを非常に疑っていますが、確信できるほど十分な経験がありません.プロファイリングはこの問題を解消するのに役立つか、少なくともコードに多くの時間がかかる可能性があることを確認できます.時間)、しかし、スレッドのスケジューリングが原因で複数のスレッドを実行するという事実が同じ問題につながる可能性があるかどうかも疑問に思いました(繰り返しますが、私はマルチスレッドにまったく慣れていないため、完全に間違っている可能性があります)。

したがって、私は尋ねたいと思います:

  • リアルタイム プログラミング (関連する場合はマルチスレッド コンテキストで) でそのような制約を強制することは可能ですか?
  • この種のコードを設計する際に従うべき主なガイドラインは何ですか?

(万が一、このトピックに関する明らかな/見つけやすいドキュメントを見逃していた場合はお詫び申し上げます)

ありがとう !

4

2 に答える 2

3

外部の信頼できる中断源がある場合を除いて、このような制約を強制することは非常に困難です。

消費者向け OS でできる最も近いことは次のとおりだと思います。

  • タイミングの変動を最小限に抑えるために、リアルタイム カーネル (Linux の RT パッチなど) を使用していることを確認してください。
  • ポーリング スレッドを可能な限り高い優先度に設定します。
  • ポーリング スレッドではポーリングとディスパッチのみを行い、処理は優先度の低いスレッドに任せて、計算がポーリングに影響を与えないようにします。
  • 高精度のタイマー (Linux では、ミリ秒ではなくナノ秒を使用できます) を使用して、エラー マージンを減らします。
  • ロックフリー キューを使用してポーリング スレッドと処理スレッドの間で通信し、ポーリング スレッドでミューテックスのコストを支払う必要がないようにします (ただし、1 秒あたり 20 サンプルしかない場合、これはおそらく無関係です)。

少なくとも、400 MHz の CPU で 100 Hz (10 ミリ秒) でポーリングする私たちの製品では、それが行われました。この方法でドリフトを完全になくすことはできませんが、ごくわずかです。

于 2013-05-28T15:28:57.943 に答える
1

@Mark が示唆したように、リアルタイム OS を使用するのが最善です。

ある種の「ソフト」な RT が十分である場合は、優先順位の高いスレッドを作成し (たとえば、Linux でスケジューリング クラスのリアルタイム FIFO を使用するなど)、スレッドを起動する循環タイマーを設定する必要があります。たとえば、セマフォによって。

さらに、プロットを処理から分離することをお勧めします。

于 2013-05-28T15:29:14.803 に答える