0

問題の新しい説明:

現在、新しいデータ取得ソフトウェアをテスト環境で実行しています。このソフトウェアには 2 つのメイン スレッドがあります。1 つには、ハードウェアと通信してデータをデュアル バッファにプッシュする高速ループが含まれています。数秒ごとに、このループは 200 ミリ秒フリーズします。いくつかのテストを行いましたが、ソフトウェアが何を待っているかを理解することはできませんでした。ソフトウェアはかなり複雑で、テスト環境もソフトウェアに干渉する可能性があるため、レコーダー スレッドが 200 ミリ秒ブロックされている間に何を待機しているかをテストするためのツール/手法が必要です。これを達成するには、どのツールが役立ちますか?

元の質問:

データ取得ソフトウェアには、主な機能を提供する 2 つのスレッドがあります。1 つのスレッドがさまざまなセンサーからデータを収集し、2 つ目のスレッドがデータを大きなブロックでディスクに保存します。データはダブル バッファに収集されます。通常、アイテムごとに 100000 バイトが含まれ、1 秒あたり最大 300 アイテムを収集します。1 つのバッファーはデータ収集スレッドでの書き込みに使用され、1 つのバッファーはデータの読み取りと 2 番目のスレッドでのディスクへの保存に使用されます。すべてのデータが読み取られると、バッファが切り替えられます。バッファの切り替えは、主要なパフォーマンスの問題のようです。バッファーが切り替わるたびに、データ収集スレッドが約 200 ミリ秒ブロックされますが、これは長すぎます。ただし、切り替えがはるかに高速で、ほとんど時間がかからない場合があります。(テスト PC: Windows 7 64 ビット、

私の推測では、パフォーマンスの問題はコア間で交換されるデータに関連しているということです。スレッドがたまたま同じコアで実行されている場合にのみ、交換ははるかに高速になります。両方のスレッドが同じコアで実行されるようにスレッド アフィニティ マスクを設定することを考えましたが、これは実際の並列処理が失われることも意味します。もう 1 つのアイデアは、切り替え前にバッファがより多くのデータを収集できるようにすることでしたが、新しいデータにアクセスする前にバッファが切り替わるのを待たなければならないため、データ表示の更新頻度が大幅に低下します。

私の質問は次のとおりです。収集スレッドを妨げずに、あるスレッドから別のスレッドにデータを移動する手法はありますか?

編集: ダブル バッファーは、リング バッファーとして使用される 2 つの std::vectors として実装されます。bool (int) 変数は、どのバッファがアクティブな書き込みバッファであるかを示すために使用されます。ダブル バッファがアクセスされるたびに、bool 値がチェックされ、どのベクトルを使用する必要があるかが判断されます。ダブル バッファーでバッファーを切り替えることは、この bool 値を切り替えることを意味します。もちろん、トグル中はすべての読み取りと書き込みがミューテックスによってブロックされます。このミューテックスが 200 ミリ秒ブロックしている可能性はないと思います。ところで、200 ミリ秒は各スイッチ イベントで非常に再現性があります。

4

3 に答える 3

0

チャットで問題について話し合った結果、Windows Performance Analyzer が使用に適したツールであることがわかりました。このソフトウェアは Windows SDK の一部であり、コマンド ウィンドウでコマンド wprui を使用して開くことができます。(Alois Krausは、チャットでhttp://geekswithblogs.net/akraus1/archive/2014/04/30/156156.aspxという便利なリンクを投稿しました)。次の手順により、ソフトウェアが何を待っていたかが明らかになりました。

  • デフォルト設定を使用して WPR で情報を記録し、保存したファイルを WPA に読み込みます。
  • 関連するスレッドを特定します。この場合、記録スレッドと保存スレッドの CPU 負荷が明らかに最も高くなりました。保存スレッドは簡単に特定できます。データをディスクに保存するため、ファイルアクセスが可能なものです。(メモリ - >ハードフォールトを見てください)
  • Computation->CPU usage (Precise) を確認し、Utilization by Process、Thread を選択します。分析しているプロセスを選択します。列を次の順序で表示するのが最適です: NewProcess、ReadyingProcess、ReadyingThreadId、NewThreadID、[黄色のバー]、Ready (µs) sum、Wait(µs) sum、Count...
  • ReadyingProcess の下で、Wait (µs) が最大のプロセスを探しました。これが遅延の原因であると予想していたからです。
  • ReadyingThreadID の下で、NewThreadId 列に遅延があるスレッドを参照する各行を確認しました。短い検索の後、約 100 ミリ秒の待機が頻繁に発生し、常にペアとして表示されるスレッドを見つけました。ReadyingThreadID 列で、記録ループが待機していたスレッドの ID を読み取ることができました。
  • その CPU 使用率によると、このスレッドは基本的に何もしませんでした。私たちの特別なケースでは、これにより、シリアルポートの io コマンドがこの待機を引き起こす可能性があるという仮定に至りました。それらを無効にした後、遅延はなくなりました。重要な発見は、200 ミリ秒の遅延が実際には 2 つの 100 ミリ秒の遅延で構成されていたことです。

さらに分析したところ、仮想シリアル ポート ペアを介したフェッチ データ コマンドが時々失われることがわかりました。これは、データ保存および圧縮ループでの非常に高い CPU 負荷に関連している可能性があります。fetch コマンドが失われると、データが受信されず、1 回目と 2 回目のデータ受信の試行が 100 ミリ秒のタイムアウト時間でタイムアウトになります。

于 2014-11-20T14:03:50.113 に答える