複数のコンシューマー スレッドと 1 つのプロデューサー スレッドがあります。プロデューサ スレッドは、特定のコンシューマ スレッドに属するマップにデータを書き込み、コンシューマ スレッドにシグナルを送信します。データを挿入および消去するときに、マップの周りでミューテックスを使用しています。ただし、このアプローチは速度パフォーマンスの点で効率的ではないようです。ミューテックスのロックとロック解除を必要とするマップの代わりに別のアプローチを提案できますか。ミューテックスは送信を遅くすると思います。
2 に答える
ただし、このアプローチは速度パフォーマンスの点で効率的ではないようです。ミューテックスのロックとロック解除を必要とするマップの代わりに別のアプローチを提案できますか。ミューテックスは送信を遅くすると思います。
プロファイラーを使用して、ボトルネックがどこにあるかを特定する必要があります。
プロデューサ スレッドは、特定のコンシューマ スレッドに属するマップにデータを書き込み、コンシューマ スレッドにシグナルを送信します。
プロデューサは、コンシューマが使用するデータ構造の種類を気にする必要はありません。これは、コンシューマの実装の詳細です。値をマップに挿入するにはメモリ割り当てが必要であり (カスタム アロケータを使用していない場合)、メモリ割り当てはヒープの状態を保護するために内部的にロックを取得することに注意してください。最終的な結果として、ミューテックスの周りのmap::insert
操作をロックすると、実際にはあまりにも長い間ロックされる可能性があります。
よりシンプルで効率的な設計は、プロデューサーとコンシューマーの間にアトミック キューを配置することです (例: pipe、ストレージを事前に割り当てるTBB concurrent_bounded_queueにより、プッシュ/ポップ操作が非常に高速になります)。プロデューサは各コンシューマと直接通信するため、そのキューは 1 ライター 1 リーダーであり、ウェイトフリー キュー (またはリング バッファー a-la C++ ディスラプター) として実装できます。
Andrei Alexandrescu は、コードを測定する必要があるという点で良い点を指摘しました ( https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920 )。これは私がするのと同じアドバイスです。これは、コードを測定し、ベースライン テストとシングル スレッドで実行しているテストの間で得られるパフォーマンスの違いを確認することです。
- シングル スレッドを使用してデータを挿入し、上記のデータにマップするのに必要な時間
- シングル スレッドを使用して上記のデータにマップし、ミューテックス ロックを使用してデータを挿入するのに必要な時間
それでもスレッドセーフなコンテナーを探している場合は、http://www.threadingbuildingblocks.org/docs/help/reference/containers_overview/concurrent_queue_cls.htm にある Intel のスレッドセーフ コンテナーのオープンソース実装を参照してください。 .
また、消費者スレッドの実装に関する提案として、Herb Sutterが彼の Web サイトに投稿したActiveObjectの記事を読むことをお勧めします: http://herbsutter.com/2010/07/12/effective-concurrency-prefer-using-active -裸のスレッドの代わりにオブジェクト/
マップを常にロックする必要がある理由など、さらに詳細を提供していただければ、よりパフォーマンスの高いメカニズムを作成できる可能性があります。