睡眠准确的时间 [英] Sleeping for an exact duration

查看:161
本文介绍了睡眠准确的时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对睡眠功能的理解是,它遵循至少语义,即睡眠(5)将保证线程睡眠5秒,但是它可以保持阻塞超过5秒,这取决于其他因素。

解决方案

正如其他人所说,你真的需要使用实时操作系统来尝试实现这一点。



但是...虽然不完美,但通过提高优先级,可以获得比正常更好的结果需要更好的时机的过程。在Windows中,您可以使用 SetPriorityClass 函数。如果您将优先级设置为最高级别( REALTIME_PRIORITY_CLASS:0x00000100 ),您将获得更多的定时结果。再次 - 这不会像你要求的那样完美。



这在Windows以外的平台上也是可能的,但我从来没有理由因此没有测试它。



编辑:根据Andy T的评论,如果你的应用程序是多线程的,你还需要注意优先级分配到线程。对于Windows,这是此处的文档。






一些背景...



A后面我使用 SetPriorityClass 以提高应用程序的优先级,我对高速视频进行实时分析,我不能错过一个帧。帧以非常正常(由外部帧采集器硬件)频率到达pc的300帧/秒(fps),其在我随后服务的每个帧上触发HW中断。由于时间非常重要,我收集了很多关于中断时间的统计数据(使用 QueryPerformanceCounter ),看看情况真的有多糟糕,并在结果分布中感到震惊。我没有stats方便,但基本上Windows正在服务中断,当它感觉像在正常运行时优先级。直方图非常混乱,stdev比我的〜3ms周期更宽。通常我会在中断服务中有200毫秒或更大的巨大差距(记住大约每3毫秒中断一次)!即:HW中断是从精确的FAR!



但是 - 当我发现了 REALTIME_PRIORITY_CLASS 设置并且以该优先级为基准,显着地 更好,并且服务间隔分布非常紧。我可以运行10分钟的300 fps,而不是错过一个单一的帧。测量的中断服务周期几乎是1/300秒,分布紧密。



此外 - 尝试并尽量减少操作系统正在做的其他事情,以帮助提高赔率你的时间工作更好在应用程序中的重要。例如:没有背景视频转码或磁盘碎片或任何东西,而你试图获得精确的时间与其他代码!



总结:


  1. 如果真的需要这个,请使用实时操作系统

  2. 如果您不能使用实时操作系统不可能或不切实际),提高您的进程优先级很可能会提高您的时间很多,因为它为我

  3. 硬件中断不会这样做...操作系统仍然需要决定


  4. 确保您没有其他运行的操作系统注意操作的进程。
  5. 对你重要,做一些测试。虽然让代码在你想要的时候正确运行并不容易,但测量这个偏差是很容易的。 PC中的高性能计数器(您通过QueryPerformanceCounter获得的)非常好。

因为它可能会有所帮助主题),这里是一个小类,我写了很久以前在Windows机器上使用高性能计数器。对您的测试可能有用:



CHiResTimer.h

  #pragma once 
#includestdafx.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);
};

CHiResTimer.cpp

  #includestdafx.h
#includeCHiResTimer.h

double CHiResTimer :: ConvertCountsToSeconds(LONGLONG Counts)
{
return((double)Counts /(double)frequency.QuadPart);
}

CHiResTimer :: CHiResTimer()
{
QueryPerformanceFrequency(& frequency);
QueryPerformanceCounter(& startCounts); //立即启动计时器
}

void CHiResTimer :: ResetTimer()
{
QueryPerformanceCounter(& startCounts); //复位引用计数器
}

double CHiResTimer :: GetElapsedTime_s()
{
LARGE_INTEGER countsNow;
QueryPerformanceCounter(& countsNow);
return ConvertCountsToSeconds(countsNow.QuadPart - startCounts.QuadPart);
}


My understanding of the Sleep function is that it follows "at least semantics" i.e. sleep(5) will guarantee that the thread sleeps for 5 seconds, but it may remain blocked for more than 5 seconds depending on other factors. Is there a way to sleep for exactly a specified time period (without busy waiting).

解决方案

As others have said, you really need to use a real-time OS to try and achieve this. Precise software timing is quite tricky.

However... although not perfect, you can get a LOT better results than "normal" by simply boosting the priority of the process that needs better timing. In Windows you can achieve this with the SetPriorityClass function. If you set the priority to the highest level (REALTIME_PRIORITY_CLASS: 0x00000100) you'll get much better timing results. Again - this will not be perfect like you are asking for, though.

This is also likely possible on other platforms than Windows, but I've never had reason to do it so haven't tested it.

EDIT: As per the comment by Andy T, if your app is multi-threaded you also need to watch out for the priority assigned to the threads. For Windows this is documented here.


Some background...

A while back I used SetPriorityClass to boost the priority on an application where I was doing real-time analysis of high-speed video and I could NOT miss a frame. Frames were arriving to the pc at a very regular (driven by external framegrabber HW) frequency of 300 frames per second (fps), which fired a HW interrupt on every frame which I then serviced. Since timing was very important, I collected a lot of stats on the interrupt timing (using QueryPerformanceCounter stuff) to see how bad the situation really was, and was appalled at the resulting distributions. I don't have the stats handy, but basically Windows was servicing the interrupt whenever it felt like it when run at normal priority. The histograms were very messy, with the stdev being wider than my ~3ms period. Frequently I would have gigantic gaps of 200 ms or greater in the interrupt servicing (recall that the interrupt fired roughly every 3 ms)!! ie: HW interrupts are FAR from exact! You're stuck with what the OS decides to do for you.

However - when I discovered the REALTIME_PRIORITY_CLASS setting and benchmarked with that priority, it was significantly better and the service interval distribution was extremely tight. I could run 10 minutes of 300 fps and not miss a single frame. Measured interrupt servicing periods were pretty much exactly 1/300 s with a tight distribution.

Also - try and minimize the other things the OS is doing to help improve the odds of your timing working better in the app where it matters. eg: no background video transcoding or disk de-fragging or anything while your trying to get precision timing with other code!!

In summary:

  1. If you really need this, go with a real time OS
  2. If you can't use a real-time OS (impossible or impractical), boosting your process priority will likely improve your timing by a lot, as it did for me
  3. HW interrupts won't do it... the OS still needs to decide to service them!
  4. Make sure that you don't have a lot of other processes running that are competing for OS attention
  5. If timing is really important to you, do some testing. Although getting code to run exactly when you want it to is not very easy, measuring this deviation is quite easy. The high performance counters in PCs (what you get with QueryPerformanceCounter) are extremely good.

Since it may be helpful (although a bit off topic), here's a small class I wrote a long time ago for using the high performance counters on a Windows machine. It may be useful for your testing:

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

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

这篇关于睡眠准确的时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆