2011-12-29 21 views
5

私はvalgrindでマルチスレッドソケットプログラムを実行しています。クライアントはTCP経由でサーバーに要求を送信し、ブール値でビジー状態を待機します。ブール値は、サーバーからの応答を処理するコールバック関数が呼び出されたときに設定されます。応答が受信されると(ブーリアンフラグが設定されると)、サーバーは要求を再度送信し、これをループで繰り返し実行します。valgrindはマルチスレッドソケットプログラムで停止します

共有変数(ブール値)への非暗号化アクセスがスレッドの問題を引き起こす可能性があることに気づきましたが、pthread mutexを使用しようとしましたが、プログラムの速度は約20%遅くなります。私は共有ブール変数への書き込みは、1回のサイクルで行うことができるので大丈夫だと確信しています。

プログラムはvalgrindの外側で正常に動作しますが、valgrindで実行すると停止することがよくあります。私はプログラムを一晩中実行したままにしておきました。通常は完了するまでに数秒かかりますので、プログラムが終了するのに十分長い間待機していないと思いません。スレッドはオープンソースのエンジンフレームワーク(クイックフィックス)によって管理されているので、スレッドの作成/管理方法に問題はないとは思いません。

マルチスレッドプログラム/ビジーウェイトループ/ソケット通信(またはこれらの組み合わせ)に関するvalgrindの問題を知っている人はいますか?

+1

共有ブール変数のビジー待機は、「1サイクルで完了」ではなく、ループごとに複数のサイクルで実行されます。ビジーループがネットワーク上のTCP往復で待機している場合、ループが数十億回繰り返される可能性があります(したがって、他の場所で使用されている可能性がある数十億のCPUサイクルを無駄にする)。あなたが言及したことのいずれかより良い解決策は、条件変数を待つことであり、コールバック関数が条件変数を通知して、データが準備できたらスレッドを起動させます。 –

+0

私はブール変数への書き込みが1サイクル(ビジー待機プロセス全体ではない)で行われると述べました。私はブール変数への書き込みが原子的に行われていると述べていたはずです(キャッシュミスなどが単一のCPUサイクルを過ぎて1バイトの書き込みをプッシュできるため) – Taras

+0

Jeremyが言ったこと - ビジー状態は悪い考えです。 – BillT

答えて

6

標準的な同期アプローチ(私が完全に同意したこと)を主張することに重点を置いていますが、代わりにValgrindに関する質問に答えるべきだと思いました。

私が知る限り、Valgrindはマルチスレッド環境で動作していません。私はValgrindがアプリケーションを単一のコア上で動作させると信じていますが、それ以外のスレッドには影響しないはずです。

Valgrindはおそらく、スタンドアロンで実行しているときに通常は表示されないコード内のバグや競合状態を露呈させるような方法で、スレッド間のタイミングや相互作用を変更しています。

あなたが使用しているオープンソーススレッドフレームワークにバグが存在しないと判断したのと同じロジックが、私の考えではValgrindにも当てはまります。これらのハングをコード内のバグと見なしてデバッグすることをお勧めします。なぜなら、その可能性が最も高いからです。

ミューテックスを使用することは、説明した問題のためにおそらく過剰です。代わりに、セマフォまたは条件変数を調べる必要があります。

幸運。

+0

私のコードにバグがあるとは確信していませんが、あなたの投稿には注意が必要です。サイドノート - pthreadライブラリを使用して条件変数を調べました。これらは、実際の条件自体で競合条件を停止するためにmutexを必要とします。 – Taras

+1

@Taras:条件変数で正しい。この場合、セマフォが私の好みになります。ミューテックスよりもずっと軽いハングの問題について、gdbでハングしているプロセスを調べて、何をしているのか調べてみませんか? – Miguel

3

ブール値の読み取り/書き込みは、x86ではアトミックな操作ではありません。

ここで私の質問を参照してください:Is volatile a proper way to make a single byte atomic in C/C++?

+0

答えは、ほとんどの書き込みではブール値がアトミックであることを示しています。「CPUは通常、1バイトを原子的に読み書きします。問題の答えから、問題はアトミックではなく、すべてのCPUが新しい値を見るのはその時です。 – Taras

2

あなたのブール値を書くことはアトミック操作である場合でも、他のメモリ周りcompiler and the CPU are free to re-order the updateでアクセスします。ビジー状態のスレッドがビジー・ループから起きて、共有データ構造がではなく、が実際に更新されていることがわかります。

一貫性のあるのプログラムを、一度に1回だけ実行することを強くお勧めします。

+0

2つのスレッド間で共有される唯一のものはブール値フラグです(信号として使用されています)。ビジー待機スレッドは、フラグが設定されている場合にのみ起動します。つまり、フラグの変更がビジー待機スレッドを実行しているCPUに伝播していなければなりません。これを考えると、コードはまだ正しく機能しませんか? – Taras

+0

ええ、あなたはまだシグナルを得ましたか?それはトリックを行うかもしれない。 :) – sarnold

関連する問題