Rus*_*uss 14
正如其他人所说,你真的需要使用实时操作系统来尝试实现这一目标.精确的软件定时非常棘手.
然而......虽然不完美,但通过简单地提高需要更好时间的过程的优先级,您可以获得比"正常"更好的结果.在Windows中,您可以使用该SetPriorityClass
功能实现此目的.如果您设置优先级为最高级别(REALTIME_PRIORITY_CLASS: 0x00000100
),你会得到很多更好的时序结果.再一次 - 这不会像你要求的那样完美.
这也可能在Windows以外的其他平台上实现,但我从来没有理由这样做,所以没有测试过.
编辑:根据Andy T的评论,如果您的应用程序是多线程的,您还需要注意分配给线程的优先级.对于Windows,这里记录了这一点.
一些背景......
不久前,我曾经SetPriorityClass
在一个应用程序中提升优先级,我正在对高速视频进行实时分析,我不能错过一个帧.帧以非常规的(由外部帧抓取器硬件驱动)频率以每秒300帧(fps)的速度到达计算机,这会在我接下来服务的每一帧上发出一个HW中断.由于时间非常重要,我收集了很多关于中断时间(使用QueryPerformanceCounter
东西)的统计数据,看看情况真的有多糟糕,并对结果发行版感到震惊.我没有方便的统计数据,但基本上Windows正在服务中断,只要它在正常优先级运行时感觉它.直方图非常混乱,stdev比我的~3ms时期宽.在中断服务中经常会有200 ms或更大的巨大间隙(回想一下中断大约每3 ms发出一次)!即:硬件中断是确切的FAR!你坚持操作系统决定为你做的事情.
但是 - 当我发现REALTIME_PRIORITY_CLASS
设置并使用该优先级进行基准测试时,它显着更好,并且服务间隔分布非常紧张.我可以运行10分钟300 fps而不会错过任何一帧.测量的中断服务周期几乎完全是1/300秒,分布严密.
此外 - 尝试并尽量减少操作系统正在做的其他事情,以帮助提高您的计划在应用程序中更好地工作的几率.例如:当你试图用其他代码获得精确计时时,没有背景视频转码或磁盘去碎片或任何东西!!
综上所述:
因为它可能有用(虽然有点偏离主题),这是我很久以前在Windows机器上使用高性能计数器写的一个小类.它可能对您的测试有用:
CHiResTimer.h
#pragma once
#include "stdafx.h"
#include <windows.h>
class CHiResTimer
{
private:
LARGE_INTEGER frequency;
LARGE_INTEGER startCounts;
double ConvertCountsToSeconds(LONGLONG Counts);
public:
CHiResTimer(); // constructor
void ResetTimer(void);
double GetElapsedTime_s(void);
};
Run Code Online (Sandbox Code Playgroud)
CHiResTimer.cpp
#include "stdafx.h"
#include "CHiResTimer.h"
double CHiResTimer::ConvertCountsToSeconds(LONGLONG Counts)
{
return ((double)Counts / (double)frequency.QuadPart) ;
}
CHiResTimer::CHiResTimer()
{
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&startCounts); // starts the timer right away
}
void CHiResTimer::ResetTimer()
{
QueryPerformanceCounter(&startCounts); // reset the reference counter
}
double CHiResTimer::GetElapsedTime_s()
{
LARGE_INTEGER countsNow;
QueryPerformanceCounter(&countsNow);
return ConvertCountsToSeconds(countsNow.QuadPart - startCounts.QuadPart);
}
Run Code Online (Sandbox Code Playgroud)
没有.
它至少是"语义"的原因是因为在那5秒之后,其他一些线程可能会忙.
每个线程都从操作系统获取时间片.操作系统控制线程的运行顺序.
当你将线程置于休眠状态时,操作系统会将线程置于等待列表中,当计时器结束时,操作系统会"唤醒"该线程.
这意味着线程被添加回活动线程列表,但不保证首先添加t.(如果需要在特定的第二个线程中唤醒100个线程怎么办?谁先走?)