0

マルチスレッドとシングルスレッドの結果が異なるというコードの問題があります。

入力画像を取り、中心を中心に n ステップで回転し、その画像を分析する関数があります。その速度を上げるために、入力として開始角度と終了角度を取り、その間の値を計算するように関数を書き直しました。

プロトタイプは

void rotateImageConvolution(float* image, int startMin, int startMax)

その関数を 0..180 で呼び出すと、毎回同じ結果が返され、正常に動作します。私は 4 コアの CPU を持っているので、0..60、60..120、120..180 の 3 つのスレッドが実行されています (int i = startMin; i < startMax)

グローバルメモリへの唯一の書き込みは

            if(convolution_image[i] < convrst)
            {
                WaitForSingleObject( mLock[i],    // handle to mutex
                    INFINITE);  // no time-out interval
                if(convolution_image[i] < convrst)
                {   
                    convolution_image[i] = convrst;
                    r_map_image[i] = (unsigned char)r0;
                    orientation_map_image[i] = (unsigned char)a;
                }
                ReleaseMutex(mLock[i]);
            }

ここで、convrst は畳み込みの結果であり、convolution_image は計算された値を保存します。i は画像のインデックスで、0 になります。imagesize mLock はハンドルのブロックです。

mLock = new HANDLE[imgsize];
for(int i = 0; i < imgsize; ++i)
{
    mLock[i] = CreateMutex( NULL, FALSE, NULL);
}

使用される他のすべてのメモリは関数で割り当てられ、再び解放されます。面白いことに、convrst 部分で Mutex を無効にすると、さまざまなランダムな結果が得られます。それらを有効にすると、2 つの結果のうちの 1 つが得られます。1 つは正しい結果 (シングル スレッドと同じ) で、半分は別の結果です。

ここで何が起こっているのか理解できず、そこで何が問題になっているのかわかりません。

問題は何ですか?

4

1 に答える 1

1

ミューテックスがifステートメント全体をラップする場合はどうなりますか?別のスレッドが書き込みの途中で、ifステートメントがconvolution_image[i]を読み取っている可能性があることに注意してください。

あなたをつまずかせるかもしれないシナリオ:

  1. スレッド1はクリティカルセクションのロックを終了しました
  2. 次に、スレッド2はifステートメントを評価します。
  3. その後、スレッド2はミューテックスによってブロックされます
  4. スレッド1はミューテックスのロックを解除します(そして、暗黙のうちに、convolution_image [i]を計算しました)。
  5. 次に、スレッド2はクリティカルセクションをロックし、次に、スレッド1がステップ#4で行ったのと同じconvolution_image[i]を計算します。
于 2012-07-02T10:55:15.363 に答える