【问题标题】:Measuring time in C++ with high precision在 C++ 中以高精度测量时间
【发布时间】:2013-01-10 14:32:34
【问题描述】:

如何在 C++ 中像在 C# 中一样准确地测量某些东西?

这是我的 C# 代码

var elapsedMilliseconds = (double)(sw.ElapsedTicks * 1000L) / Stopwatch.Frequency;

我正在使用 Visual Studio 2010。

【问题讨论】:

标签: c# c++ visual-studio-2010


【解决方案1】:

C# 中的 Stopwatch 类基于这两个 Win32 API 调用,您可以从 C/C++ 调用它们:

调用第一个函数并除以第二个函数得到一个以秒为单位的值。

例子:

LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
// do some long operation here
Sleep(5000);
QueryPerformanceCounter(&end);
// subtract before dividing to improve precision
double durationInSeconds = static_cast<double>(end.QuadPart - start.QuadPart) / freq.QuadPart;

请注意,文档中的以下注释是真实的,应予以考虑。我个人在 VirtualBox 虚拟机中观察到了这种行为。不同处理器之间可能存在几十毫秒的差异,从而导致持续时间为负数和持续时间长于预期等意外结果:

在多处理器计算机上,哪个处理器无关紧要 叫。但是,您可以在不同的处理器上获得不同的结果 由于基本输入/输出系统 (BIOS) 或硬件中的错误 抽象层(HAL)。要指定线程的处理器亲和性, 使用 SetThreadAffinityMask 函数。

您可能对此感兴趣:System.Diagnostics.Stopwatch returns negative numbers in Elapsed... properties

请注意,如果上述两个 API 不可用或返回失败代码,则 Stopwatch 类将使用 GetTickCount。这可能只是为了保持与 Windows 9x 的兼容性;我自己在现代 PC 上使用这些 API 并没有遇到任何问题。但是,GetTickCount 不会有您想要的精度。

【讨论】:

  • 我认为QueryPerformanceCounter等价于StopWatch.GetTimestampQueryPerformanceFrequency等价于StopWatch.Frequency
【解决方案2】:

我需要更具体的测量方法,但我找到了。谢谢其他答案。他们都很好。有了这个答案,如果需要,我可以轻松切换到微秒。

当然,我会接受 James Johnston 的答案作为正确的答案,因为有很好的解释和人们的反馈。

谢谢大家

int main(int argc, char ** argv)
{
unsigned long long nFreq = GetPerformanceTicksInSecond();
unsigned long long nBefore = GetPerformanceTicks();
timer start1 = timer::start();

CallSomeFunction();

unsigned long long nAfter = GetPerformanceTicks();
const unsigned long long nDiff = nAfter - nBefore;
const unsigned long long nMicroseconds = GetTickMicroseconds(nDiff,nFreq);

cout << "CallSomeFunction() took " << nMicroseconds << " " << time << endl;

return 0;

}

unsigned long long GetPerformanceTicks()
{
    LARGE_INTEGER nValue;

    ::QueryPerformanceCounter(&nValue);

    return nValue.QuadPart;
}

unsigned long long GetPerformanceTicksInSecond()
{
    LARGE_INTEGER nFreq;

    ::QueryPerformanceFrequency(&nFreq);

    return nFreq.QuadPart;
}

double GetTickSeconds(unsigned long long nTicks,unsigned long long nFreq)
{
    return static_cast<double>(nTicks) / static_cast<double>(nFreq);
}

unsigned long long GetTickMilliseconds(unsigned long long nTicks,unsigned long long nFreq)
{
    unsigned long long nTicksInMillisecond = nFreq / 1000;

    return nTicks / nTicksInMillisecond;
}

unsigned long long GetTickMicroseconds(unsigned long long nTicks,unsigned long long nFreq)
{
    unsigned long long nTicksInMicrosecond = nFreq / 1000000;

    return nTicks / nTicksInMicrosecond;
}

【讨论】:

    【解决方案3】:

    检查这个:How to get system time in C++?

    您也可以使用 GetTickCount : 检索自系统启动以来经过的毫秒数,最长为 49.7 天。

    【讨论】:

    • GetTickCount 不会有提问者想要的精度;秒表课更好。
    【解决方案4】:

    使用 QueryPerformanceFrequency 和 QueryPerformanceCounter API 函数。

    LARGE_INTEGER freq;
    ::QueryPerformanceFrequency(&freq);
    
    LARGE_INTEGER start, end;
    ::QueryPerformanceCounter(&start);
    // do some work
    ::QueryPerformanceCounter(&end);
    
    double const t = double(end.QuadPart - start.QuadPart) / double(freq.QuadPart);
    

    为了提高准确性,您可能需要从结果中减去调用 QueryPerformanceCounter 所需的时间。

    【讨论】:

      【解决方案5】:

      秒表类是 QueryPerformanceCounter 的包装器:

      uint64_t startTime, endTime;
      uint64_t frequency;
      QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
      QueryPerformanceCounter((LARGE_INTEGER*)&startTime);
      //DoStuff
      QueryPerformanceCounter((LARGE_INTEGER*)&endTime);
      double seconds = (endTime-startTime)/(double) frequency;
      

      【讨论】:

        猜你喜欢
        • 2010-12-21
        • 1970-01-01
        • 1970-01-01
        • 2018-03-17
        • 2017-10-20
        • 2010-10-04
        • 1970-01-01
        • 2013-04-06
        相关资源
        最近更新 更多