2013-01-10 38 views
4

如何在C++中精确地测量C++中的某些内容?以高精度在C++中测量时间

这是我的C#代码

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

我使用Visual Studio 2010中

+0

只是好奇,为什么不在'Stopwatch'财产使用build ['ElapsedMilliseconds'](http://msdn.microsoft.com/en-us/library/system.diagnostics .stopwatch.elapsedmilliseconds.aspx)在C#中? – NominSim

+0

此链接是否有帮助:[如何在Windows上使用C++进行高分辨率计时?](http://cplus.about.com/od/howtodothingsi2/a/timing.htm)? –

回答

14

C#中的秒表类是基于这两个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

注意,秒表类倒在GetTickCount的,如果上述两个API不可用或返回故障代码。这可能只是为了保持与Windows 9x的兼容性;我在现代PC上使用这些API没有遇到任何问题。但是,GetTickCount不会达到你想要的精度。

+0

我相信'QueryPerformanceCounter'相当于'StopWatch.GetTimestamp',而'QueryPerformanceFrequency'相当于'StopWatch.Frequency'。 – Matthew

0

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

也可以使用的GetTickCount其中: 检索,因为这个系统被启动,高达49.7天即所经过的毫秒数。

+1

GetTickCount不会具有提问者想要的精度;秒表班更好。 –

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所花费的时间。

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; 
0

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

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

THX所有

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; 
}