c++ - 使用 std::chrono 库来调整应用程序 fps 但出现奇怪的行为

标签 c++ windows thread-sleep frame-rate c++-chrono

我使用 std::chrono c++ 库编写了下面的代码,我想做的是 将应用程序的 FPS 修复为 60 ,但我得到了 50 FPS,这肯定不是性能问题 因为我什么也没计算。但这肯定是无效的用法或错误。

TARGET_FPS宏设置为我想要获取的目标FPS,然后是控制台窗口 显示真正的实际 FPS ,以下几行显示我设置 TARGET_FPS 的值,每个值都与最终 FPS 相关联。

 TARGET_FPS---->FPS

       60----->50
       90----->50
       100----->100
     1000----->100
     10000----->100
   whatever ----->100

即使我将 TARGET_FPS 定义为 1000000000,我也会得到 100 FPS,即使我将其定义为 458 或任何大于 100 的值,我也会得到 100 FPS 作为输出。

#include <chrono> /// to use std::chrono namespace 
#include <iostream> /// for console output
#include <thread> /// for std::this_thread::sleep_for()
#define TARGET_FPS 60// our target FPS    
using frame_len_type = std::chrono::duration<float,std::ratio<1,TARGET_FPS>>; /// this is the     duration that defines the length of a frame
using fsecond = std::chrono::duration<float>; /// this duration    represents once second and uses 'float' type as internal representation
const frame_len_type target_frame_len(1); /// we will define this    constant here , to represent on frame duration ( defined to avoid    construction inside a loop )
void app_logic(){ /** ... All application logic goes here ... **/}
int main() /// our main function !
{
    using sys_clock = std::chrono::system_clock; /// simplify the type    name to make the code readable
     sys_clock::time_point frame_begin,frame_end; /// we will use these time points to point to frame begin and end
     while (true)
     {
      frame_begin = sys_clock::now(); /// there we go !
      app_logic(); /// lets be logical here :)
      frame_end = sys_clock::now(); /// we are done so quick !
      std::this_thread::sleep_for( target_frame_len-    (frame_end.time_since_epoch()-frame_begin.time_since_epoch()) ); /// we will take a rest that is equal to what we where supposed to take to finish the actual target frame length
      std::cout<< fsecond(1) / ( sys_clock::now() - frame_begin) <<std::endl; /// this will show ass the current FPS
     }
    return 0; /// return to OS
} /// end of code

最佳答案

std::chrono 的计时分辨率取决于系统:

After the sleep interval has passed, the thread is ready to run. If you specify 0 milliseconds, the thread will relinquish the remainder of its time slice but remain ready. Note that a ready thread is not guaranteed to run immediately. Consequently, the thread may not run until some time after the sleep interval elapses.

  • 无论您使用什么操作系统,C++ 标准库都不会为 sleep_for 提供更好的保证:

30.3.2/7: Effect: Blocks the calling thread for the relative timeout (...)

后果:

  • 如果 FPS 设置为 60,则每 16.6 毫秒就会出现一帧。因此,假设您的 app_logic() 速度超快,您的线程将休眠至少 15.6 毫秒。如果逻辑执行时间为 1 毫秒,则帧速率恰好为 60 FPS。
  • 但是,根据 API 文档,如果 [等待时间] 大于 1 个刻度但小于 2 个刻度,则等待时间可以是 1 到 2 个刻度之间的任意时间,因此平均 sleep 时间将在 15.6 到 31.2 毫秒之间,这反过来意味着您的 FPS 将在 60 到 32 FPS 之间。这解释了为什么您只能达到 50 FPS。

  • 当您将 FPS 设置为 100 时,每 10 毫秒应该有一帧。这低于计时器的精度。可能根本就睡不着。如果没有其他线程准备运行,该函数将立即返回,以便您达到最大吞吐量。如果您设置更高的 FPS,您将处于完全相同的情况,因为预期等待时间将始终低于计时器精度。因此,结果不会改善。

关于c++ - 使用 std::chrono 库来调整应用程序 fps 但出现奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46258641/

相关文章:

java - 处理字符串 : Java client & C++ server 的正确方法是什么

c++ - 窗口名称未打印

linux - 如何使用 UEFI 备份笔记本电脑 SSD

windows - 如何让旧的 VB6 应用程序在 Windows Vista 和 Windows 7 中运行?

java - 如何让我的 android 应用程序等待 isInteractive() 方法有效地返回 false?

c# - 在 C# 中 sleep 直到

c++ - 阻塞许多锁/ future /等。直到任何准备就绪

c++ - 在 C++ 中,* 用于哪三件事?

python - 以编程方式从共享邮箱发送 outlook 电子邮件

java - 每个类默认都有自己的Thread吗?