c++ - Debug 和 Release 之间的不同结果

标签 c++ visual-studio-2010 openmp release-mode debug-mode

我的问题是,在比较调试版和发布版时,我的代码返回了不同的结果。我检查过这两种模式都使用/fp:precise,所以这应该不是问题所在。我对此的主要问题是完整的图像分析(它是一个图像理解项目)是完全确定的,其中绝对没有任何随机性。

另一个问题是我的发布版本实际上总是返回相同的结果(图像为 23.014),而调试返回 22 到 23 之间的一些随机值,这不应该是.我已经检查过它是否可能与线程相关,但算法中唯一的多线程部分为调试和发布返回完全相同的结果。

这里还可能发生什么?

Update1:​​我现在发现的导致此行为的代码:

float PatternMatcher::GetSADFloatRel(float* sample, float* compared, int sampleX, int compX, int offX)
{
    if (sampleX != compX)
    {
        return 50000.0f;
    }
    float result = 0;

    float* pTemp1 = sample;
    float* pTemp2 = compared + offX;

    float w1 = 0.0f;
    float w2 = 0.0f;
    float w3 = 0.0f;

    for(int j = 0; j < sampleX; j ++)
    {
        w1 += pTemp1[j] * pTemp1[j];
        w2 += pTemp1[j] * pTemp2[j];
        w3 += pTemp2[j] * pTemp2[j];
    }               
    float a = w2 / w3;
    result = w3 * a * a - 2 * w2 * a + w1;
    return result / sampleX;
}

更新 2: 这不能用 32 位代码重现。虽然调试和发布代码对于 32 位总是产生相同的值,但它仍然与 64 位发布版本不同,64 位调试仍然返回一些完全随机的值。

更新 3: 好的,我发现它肯定是由 OpenMP 引起的。当我禁用它时,它工作正常。 (Debug 和 Release 都使用相同的代码,并且都激活了 OpenMP)。

以下是给我带来麻烦的代码:

#pragma omp parallel for shared(last, bestHit, cVal, rad, veneOffset)
for(int r = 0; r < 53; ++r)
{
    for(int k = 0; k < 3; ++k)
    {
        for(int c = 0; c < 30; ++c)
        {
            for(int o = -1; o <= 1; ++o)
            {
                /*
                r: 2.0f - 15.0f, in 53 steps, representing the radius of blood vessel
                c: 0-29, in steps of 1, representing the absorption value (collagene)
                iO: 0-2, depending on current radius. Signifies a subpixel offset (-1/3, 0, 1/3)
                o: since we are not sure we hit the middle, move -1 to 1 pixels along the samples
                */

                int offset = r * 3 * 61 * 30 + k * 30 * 61 + c * 61 + o + (61 - (4*w+1))/2;

                if(offset < 0 || offset == fSamples.size())
                {
                    continue;
                }
                last = GetSADFloatRel(adapted, &fSamples.at(offset), 4*w+1, 4*w+1, 0);
                if(bestHit > last)
                {
                    bestHit = last;
                    rad = (r+8)*0.25f;
                    cVal = c * 2;
                    veneOffset =(-0.5f + (1.0f / 3.0f) * k + (1.0f / 3.0f) / 2.0f);
                    if(fabs(veneOffset) < 0.001)
                        veneOffset = 0.0f;
                }
                last = GetSADFloatRel(input, &fSamples.at(offset), w * 4 + 1, w * 4 + 1, 0);
                if(bestHit > last)
                {
                    bestHit = last;
                    rad = (r+8)*0.25f;
                    cVal = c * 2;
                    veneOffset = (-0.5f + (1.0f / 3.0f) * k + (1.0f / 3.0f) / 2.0f);
                    if(fabs(veneOffset) < 0.001)
                        veneOffset = 0.0f;
                }
            }
        }
    }
}

注意:在 Release模式和 OpenMP 激活的情况下,我得到的结果与停用 OpenMP 的结果相同。 Debug模式和 OpenMP 激活得到不同的结果,OpenMP 停用得到与 Release 相同的结果。

最佳答案

至少有两种可能:

  1. 开启优化可能会导致编译器重新排序操作。与在 Debug模式下执行的顺序相比,这可能会在浮点计算中引入微小差异,在 Debug模式下不会发生操作重新排序。这可能解释了调试和发布之间的数值差异,但解释了在 Debug模式下从一次运行到下一次运行的数值差异。
  2. 您的代码中存在与内存相关的错误,例如读取/写入超出数组边界、使用未初始化的变量、使用未分配的指针等。尝试通过内存检查器运行它,例如优秀的valgrind,识别此类问题。与内存相关的错误可能会导致非确定性行为。

如果您使用的是 Windows,则 Valgrind不可用(可惜),但你可以看看here获取备选方案列表。

关于c++ - Debug 和 Release 之间的不同结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11954238/

相关文章:

c# - 为什么 VS2010 "Lose"我的引用构建?

c++ - 在不同的 main() 之间轻松切换

c++ - omp 并行 block 外的 omp pragma

java - 尝试编译 jomp hello world 时出错

c++ - OpenMP 2 中的共享 vector

c++ - 是否有基于范围的类案例控制结构

c++ - 将 D 库链接到 C++ 代码

visual-studio-2010 - 如何在 VS 而不是 JIT 调试器中进行调试?

c++ - 在 C++ 中没有修饰符的 RegisterHotKey

c++ - C++ 模板中的类型优先级和整数类型