0

我的代码有一个问题,即多线程和单线程之间的结果不同。

我有一个函数,它获取输入图像,并围绕中心旋转 n 步,并对该图像进行一些分析。为了提高速度,我重写了函数以将起始角度和结束角度作为输入,并计算两者之间的值。

原型是

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

现在,当我用 0..180 调用该函数时,它每次都会返回相同的结果,效果很好。由于我有一个 4 核 CPU,我有 3 个线程在运行,运行 0..60、60..120、120..180,因为它运行 (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,我会得到随机结果,很多不同的结果。如果我启用它们,我会得到两个结果之一,一个是正确的结果(与单线程相同),一半是不同的结果。

我无法弄清楚这里发生了什么,也看不出那里出了什么问题。

可能是什么问题?

4

1 回答 1

1

如果您的互斥体包装了整个 if 语句怎么办?请记住,您的 if 语句可能正在读取 convolution_image[i] 而另一个线程正在编写它。

可能会绊倒你的场景:

  1. 线程 1 刚刚完成锁定关键部分
  2. 然后线程 2 评估 if 语句。
  3. 然后线程 2 被互斥锁阻塞
  4. 线程 1 解锁了互斥锁(并且隐含地计算了卷积图像 [i])。
  5. 然后线程 2 锁定临界区,然后继续计算与线程 1 在步骤 4 中相同的卷积图像 [i]。
于 2012-07-02T10:55:15.363 回答