【问题标题】:C++11 Most accurate way to pause execution for a certain amount of time? [duplicate]C ++ 11暂停执行一段时间的最准确方法? [复制]
【发布时间】:2019-02-21 00:14:25
【问题描述】:

我目前正在编写一些从视频文件中读取的 C++ 代码,将视频/音频流解析为其组成单元(例如 FLV tag)并将其发送回以“重新流式传输”它。

因为我的输入来自文件,但我想在重新流式传输此数据时模拟适当的帧速率,所以我正在考虑我可能会休眠在文件上执行 read 的线程以尝试提取以通常 30 或 60 FPS 的给定速率帧。

一种解决方案是使用明显的 std::this_thread::sleep_for 调用并根据我的 FPS 传递毫秒数。我正在考虑的另一个解决方案是使用条件变量,并以相同的想法使用std::condition_variable::wait_for

我有点卡住了,因为我知道第一个解决方案不能保证精确的精度——只要我传入的参数,睡眠就会持续一段时间,但理论上可能会更长。而且我知道std::condition_variable::wait_for 调用将需要重新获取锁,这也需要一些时间。有比我正在考虑的更好的解决方案吗?否则,尝试以尽可能精确的粒度暂停执行的最佳方法是什么?

【问题讨论】:

  • 比以精确粒度暂停执行更重要的是正确计算暂停多长时间。
  • 使用absolute计时:stackoverflow.com/a/47964169/3807729
  • 以固定频率运行线程在游戏中很常见,例如“物理引擎”。对于 Windows,它是通过结合睡眠和轮询高频计时器来完成的。这是example fixed frequency thread Windows code 的链接。示例代码被编写为尽可能接近固定频率运行,没有漂移,(延迟基于高频定时器的一次性读数)。我认为 Linux 也有类似的东西。

标签: c++ c++11 sleep


【解决方案1】:

C++11 暂停执行一段时间的最准确方法?

这个:

auto start = now();
while(now() < start + wait_for);

now() 是系统可用的最准确时间测量方法的占位符。

这类似于sleep,就像自旋锁对互斥锁一样。像自旋锁一样,它会在暂停时消耗所有 CPU 周期,但它正是您所要求的:暂停执行的最准确方式。在准确性和 CPU 使用效率之间进行权衡:您必须选择对您的程序更重要的。

为什么比std::this_thread::sleep_for更准确?

因为sleep_for 产生线程的执行。因此,它永远不会比操作系统的进程调度程序具有更好的粒度(假设还有其他进程在争夺时间)。

上面显示的实时循环不会主动放弃其时间片,将达到用于测量的时钟提供的最高粒度。

当然,调度程序授予的时间片最终会用完,这可能会在我们应该恢复的时间附近发生。减少这种影响的唯一方法是增加线程的优先级。在 C++ 中没有影响线程优先级的标准方法。完全消除这种影响的唯一方法是在非多任务系统上运行。

在多 CPU 系统上,您可能想要做的一个技巧是设置线程亲和性,以便操作系统线程不会迁移到会引入延迟的其他硬件线程。同样,您可能希望设置其他线程的线程亲和性以远离时间测量线程。没有设置线程亲和性的标准工具。


令 T 为您希望睡眠的时间,令 G 为 sleep_for 可能超调的最长时间。

如果 T 大于 G,则将 sleep_for 用于 T - G 时间单位会更有效,并且仅对最终 G - O 时间单位使用实时循环(其中 O 是 @ 987654328@ 被观察到过冲)。

但是,弄清楚 G 对您的目标系统来说是什么可能非常棘手。没有标准的工具。如果您高估,您将浪费不必要的周期。如果您低估,您的睡眠可能会超出目标。


如果您想知道now() 的最佳选择是什么,标准库提供的最合适的工具是std::chrono::steady_clock。但是,这不一定是您系统上可用的最准确的工具。哪种工具最准确取决于您所针对的系统。

【讨论】:

  • “它会在暂停时消耗所有的 CPU 周期” 哎哟!!!!!! ..........
  • 嗯...为什么比std::this_thread::sleep_for更准确?加上“now() 是系统可用的最准确时间测量方法的占位符”似乎是一种奇怪的方式来回答“暂停执行的最准确方法是什么 [...]? ”。您能否详细说明您的陈述和示例?
  • @Fureeish 我已经添加了解释。
  • 老实说,我不相信这比sleep_forsleep_until 更准确,因为操作系统仍然会抢占线程,即使你不自愿放弃使用sleep_for。此外,对now() 的持续调用可能比内核对sleep_for 唤醒的响应时间更长——这使得它不如等待准确。
  • @eerorika 好吧,你赢了。在我的测试中,您的自旋时间比sleep_until 准确得多:)
猜你喜欢
  • 2015-11-05
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 2021-10-17
  • 2020-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多