4

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

这是我的 C# 代码

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

我正在使用视觉工作室 2010。

4

5 回答 5

14

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 在 Elapsed... 属性中返回负数

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

于 2013-01-10T14:35:15.590 回答
1

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

当然,我会接受詹姆斯约翰斯顿的答案作为正确的答案,因为有很好的解释和人们的反馈。

谢谢大家

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;
}
于 2013-01-11T13:17:58.420 回答
0

检查这个:如何在 C++ 中获取系统时间?

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

于 2013-01-10T14:38:13.230 回答
0

使用 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 所需的时间。

于 2013-01-10T14:38:44.503 回答
0

秒表类是 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;
于 2013-01-10T14:38:50.680 回答