【问题标题】:Time differences between Release and Debug builds发布和调试版本之间的时间差异
【发布时间】:2011-12-15 03:44:06
【问题描述】:

我的程序应该每 180 秒触发一次事件。

mFoodSpawnTime += dt;
if (mFoodSpawnTime > mFoodSpawnCycleLength)
{
       ..... etc;
}

mFoodSpawnCycleLength = 180.0f,mFoodSpawnTime 是另一个浮点数,每次循环都会累积时间。

我的问题是,如果 mFoodSpawnCycleLength 大约是 180.0f,那么在发布版本中它似乎永远不会到达,mFoodSpawnTime 比 mFoodSpawnCycleLength 需要长达 10 分钟!我已经对调试构建进行了计时,它确实在 180 秒后执行了循环,并且我已经使用秒表进行了验证。回到发布版本:只要 mFoodSpawnCycleLength 不在 180.0f 附近,它也会匹配秒表并执行代码。我曾经将它设置为 120.0f,当它执行秒表时读取 2 分 30 秒。没有可能导致此问题的#ifdef DEBUG 代码。 所以我要说的是:mFoodSpawnCycleLength 越接近 180.0f,时间就越不精确,但仅限于发布版本!

我刚刚打印出 mFoodSpawnTime,当我的时钟读数为 3 分钟时,它的时间只有 160 秒左右,我发现随着计时器接近 150 秒,时间增量会慢慢停止。我在每个循环中跟踪了 dt,它似乎与开始时没有任何不同。

这可能是由侵入式编译器优化引起的吗? 32 位浮点错误? 我会继续研究这个问题,但我们非常感谢您的帮助。

我还在学习,所以我正在使用 DirectX Book。 我使用书中提供的演示中的时间码:

int D3DApp::run()
{
MSG  msg;
msg.message = WM_NULL;

__int64 cntsPerSec = 0;
QueryPerformanceFrequency((LARGE_INTEGER*)&cntsPerSec);
float secsPerCnt = 1.0f / (float)cntsPerSec;

__int64 prevTimeStamp = 0;
QueryPerformanceCounter((LARGE_INTEGER*)&prevTimeStamp);

while(msg.message != WM_QUIT)
{
    // If there are Window messages then process them.
    if(PeekMessage( &msg, 0, 0, 0, PM_REMOVE ))
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    // Otherwise, do animation/game stuff.
    else
    {   

        if( mTimeReset )
        {
            QueryPerformanceCounter((LARGE_INTEGER*)&prevTimeStamp);
            mTimeReset = false;
        }

        if( !isDeviceLost() )
        {
            static float frameLimit = 0.0f;
            __int64 currTimeStamp = 0;
            QueryPerformanceCounter((LARGE_INTEGER*)&currTimeStamp);
            float dt = (currTimeStamp - prevTimeStamp)*secsPerCnt;

            if (dt > 2.0f) dt = 0.0f;

            frameLimit +=dt;

            updateScene(dt);
            if (frameLimit > 0.0167f)
            {
                drawScene();
                frameLimit = 0.0f;
            }

            // Prepare for next iteration: The current time stamp 
            // the previous time stamp for the next iteration.
            prevTimeStamp = currTimeStamp;
                    }
         }
    }
return (int)msg.wParam;
}

【问题讨论】:

  • 这个条件的评估频率是多少?即它多久循环一次?
  • dt 是“增量时间”——本次迭代与上次迭代之间的秒数差异?
  • 是的,是时代的变迁。
  • 如果没有看到实际的计时代码,我会说使用“每个循环累积时间”的float 值的计时不会很可靠。我建议使用一个单独的计时器线程,你可以保证有一定的准确性(~20ms——如果你用秒表分析就足够了)。请注意,可用的各种线程模型取决于目标系统(Windows、Linux 等)。
  • 我认为我们需要查看更多代码 - 某处肯定存在错误;我真的怀疑这是编译器优化。

标签: c++ debugging compiler-construction time release


【解决方案1】:

您可能想在这里尝试使用 double 而不是 float。在这种情况下,性能差异将很小,我怀疑您可能会遇到一个问题,即您将一个非常小的数字添加到一个大数字 - 保持大数字的浮点值不变。

浮点数只能为您提供大约六位数的精度。如果性能计数器周期为 ns 数量级,那么当 frameLimit 达到几毫秒时,您将开始遇到问题。

调试模式往往会运行得更慢,导致增量更大,这可能是您在那里看不到问题的原因。

【讨论】:

  • 我刚刚包含了 updateScene(dt);在 if (frameLimit...) 语句下,并更改了 updateScene(dt);更新场景(frameLimit);现在它完美地工作了。感谢您帮助我找出它发生的原因!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
相关资源
最近更新 更多