在C#中,我正在使用Stopwatch
类。我可以得到滴答,毫秒没有问题。
现在我在学习C ++的同时测试代码,但我尝试进行测量 我不知道结果与C#Stopwatch等效解决方案的匹配程度。我试图搜索,但信息太广泛,我无法找到绝对的解决方案。
double PCFreq = 0.0;
__int64 CounterStart = 0;
void StartCounter()
{
LARGE_INTEGER li;
if(!QueryPerformanceFrequency(&li))
std::cout << "QueryPerformanceFrequency failed!\n";
PCFreq = double(li.QuadPart)/1000.0;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
double GetCounter()
{
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return double(li.QuadPart-CounterStart)/PCFreq;
}
因为这给了我两个不同的结果,我倾向于相信时钟。 :)
start = StartCounter()
//some function or for loop
end = GetCounter()
marginPc = end - start;
start = clock();
// ...same
end= clock();
marginClck = end - start;
std::cout<< "Res Pc: " << marginPc << "\r\nRes Clck: " marginClck<< std::endl;
使用时钟版本我同时尝试了unsigned int
和double
,但结果仍然不同。
与C#秒表相当的正确方法是什么?
答案 0 :(得分:1)
你的错误就是这个。您StartCounter
返回CounterStart = li.QuadPart;
但GetCounter
会返回double(li.QuadPart-CounterStart)/PCFreq
。
即。一个除以PCFreq
,另一个不是。然后从另一个中减去一个是无效的。
答案 1 :(得分:1)
clock()
为您提供自程序启动以来的毫秒数。例如,以下程序将打印一个接近500的数字:
int main()
{
Sleep(500);
cout << clock() << endl;
/*
POSIX version:
std::cout << clock() * 1000.0 / CLOCKS_PER_SEC << std::endl;
CLOCKS_PER_SEC is 1000 in Windows
*/
return 0;
}
QueryPerformanceCounter
有点类似于GetTickCount64
,它基于计算机启动的时间。当您执行Stop-Watch类型减法时,结果非常接近。 QueryPerformanceCounter
更准确。来自@ BoPersson链接的chrono
方法也基于QueryPerformanceCounter
。
MSDN建议将QueryPerformanceCounter(QPC)用于高分辨率标记:
Acquiring high-resolution time stamps
在托管代码中使用相同的QPC函数:
对于托管代码,
System.Diagnostics.Stopwatch
类使用 QPC作为其精确时间基础
此功能应具有合理的准确度:
long long getmicroseconds()
{
LARGE_INTEGER fq, t;
QueryPerformanceFrequency(&fq);
QueryPerformanceCounter(&t);
return 1000000 * t.QuadPart / fq.QuadPart;
}
计算机时钟通常精确到每天+/- 1秒。
从以上链接:
Duration Uncertainty
1 microsecond ± 10 picoseconds (10-12)
1 millisecond ± 10 nanoseconds (10-9)
1 second ± 10 microseconds
1 hour ± 60 microseconds
1 day ± 0.86 seconds
1 week ± 6.08 seconds
为了简化您的其他功能,您可以避免double
结果。 QuadPart
为long long
,因此请在整个函数中使用它:
long long PCFreq = 0;
long long CounterStart = 0;
void StartCounter()
{
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
PCFreq = li.QuadPart;
QueryPerformanceCounter(&li);
CounterStart = li.QuadPart;
}
long long GetCounter()
{
if (PCFreq < 1) return 0;
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
//for milliseconds: 1,000
return 1000 * (li.QuadPart - CounterStart) / PCFreq;
//for microseconds: 1,000,000
//return 1000000 * (li.QuadPart - CounterStart) / PCFreq;
}