睡觉一段确切的时间

Raa*_*aam 7 c c++ multithreading real-time

我对Sleep函数的理解是它遵循"至少语义",即sleep(5)将保证线程休眠5秒,但是根据其他因素,它可能会被阻塞超过5秒.有没有办法在指定的时间段内睡觉(没有忙碌的等待).

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秒,分布严密.

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

综上所述:

  1. 如果你真的需要这个,请使用实时操作系统
  2. 如果您无法使用实时操作系统(不可能或不切实际),提高您的流程优先级可能会大大改善您的时间安排,就像它对我所做的那样
  3. 硬件中断不会这样做......操作系统仍然需要决定为它们提供服务!
  4. 确保您没有运行其他正在竞争操作系统注意的进程
  5. 如果时间对您来说非常重要,请进行一些测试.虽然让代码在你想要的时候准确运行并不容易,但测量这种偏差非常容易.PC中的高性能计数器(使用QueryPerformanceCounter得到的)非常好.

因为它可能有用(虽然有点偏离主题),这是我很久以前在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)

  • 很棒的故事和提供的大量代码:)可惜我只有+1给. (2认同)

Yoc*_*mer 5

没有.

它至少是"语义"的原因是因为在那5秒之后,其他一些线程可能会忙.

每个线程都从操作系统获取时间片.操作系统控制线程的运行顺序.

当你将线程置于休眠状态时,操作系统会将线程置于等待列表中,当计时器结束时,操作系统会"唤醒"该线程.
这意味着线程被添加回活动线程列表,但不保证首先添加t.(如果需要在特定的第二个线程中唤醒100个线程怎么办?谁先走?)