3

pstackこのコードがデッドロックにつながることに驚いています。同じ理由がわかりません。

pthread_mutex_t lock;

_Cilk_for (int i = 0; i < N; ++i) {
  int ai = A[i];
  if (ai < pivot) {
    pthread_mutex_lock(&lock);
    A[ia++] = ai;
    pthread_mutex_unlock(&lock);
  }
  else if (ai > pivot) {
    pthread_mutex_lock(&lock);
    A[ib++] = ai;
    pthread_mutex_unlock(&lock);
  }
  else {
    pthread_mutex_lock(&lock);
    A[ic++] = ai;
    pthread_mutex_unlock(&lock);
  }
}

A へのアクセスがアトミックでシリアル化されていることを確認するためにミューテックスを使用しているだけです。

  • デッドロックにつながるこのコードの何が問題なのですか?
  • これを実装するより良い方法はありますか?
4

3 に答える 3

5

それが関数内のコードである場合、ミューテックスを正しく初期化していません。PTHREAD_MUTEX_INITIALIZER(単純なデフォルトのミューテックスの場合) に設定するか、(pthread_mutex_init()より複雑な要件の場合) 実行する必要があります。適切に初期化しないと、ミューテックスがどの状態で開始されるかわかりません。その位置でスタック上にあったものがロックされたミューテックスのように見えたという理由だけで、ロックされた状態になっている可能性があります。

そのため、初期状態に疑いがないように、常に何らかの方法で初期化する必要があります。

あなたが持つかもしれない別の潜在的な問題はこれです:

int ai = A[i];

おそらく、同じミューテックスでそのアクセスを保護する必要があります。そうしないと、「半分の状態」で読み取る可能性があるためです (別のスレッドが変数の更新の途中にある場合)。


そして、ここでスレッドが賢明に使用されているかどうかはわかりません。A[ia++] = aiミューテックスを使用すると、大部分の時間がミューテックスのロックとロック解除に費やされるほど、ステートメントが圧倒される可能性があります。通常、ロック中に処理されるコードがもう少し重要な場合に便利です。

スレッド化されていないバリアントがこれを水から吹き飛ばすことに気付くかもしれません (ただし、もちろん、私の言葉を鵜呑みにしないでください - 私の主な最適化のマントラは「測定する、推測しないでください」です)。

于 2012-09-03T04:33:31.020 に答える
3

あなたのpthread_mutex_t lockは適切に初期化されていないため、ローカル変数であるため、ゴミが含まれている可能性があり、奇妙にロックされた状態になっている可能性があります。pthread_mutex_initを呼び出すか、初期化する必要lockがありますPTHREAD_MUTEX_INITIALIZER

他の人が不平を言ったように、あなたはミューテックスを賢く使っていません。コードのクリティカル セクションが小さすぎます。

于 2012-09-03T04:23:34.770 に答える
1

実際に初期化していることを修正または確認した後lock

pstack_Cilk_forによって導入されたメカニズムを制御することに関与している可能性がありpthreadます。

簡単に検索すると、Cilk で使用するミューテックス ソリューションがあることがわかります。Cilk と pthread の混在については言及されていません。Cilk は pthread の上にあるレイヤーのように見えます。そのため、Cilk がラッパーを配置することを選択した場合mutex,は、正当な理由がある可能性があります。Cilk API を使用することをお勧めします。

それはさておき、アルゴリズムにはもっと根本的な問題があります。 あなたの場合、並列スレッドを作成してそれらを同期するためのオーバーヘッドは、for ループの本体でコードを実行するコストを小さくする可能性があります。これを並列化せずに高速に実行できる可能性は非常に高いです。

于 2012-09-03T04:46:32.473 に答える