C++ 限制循环c和x2B中的fps+;

C++ 限制循环c和x2B中的fps+;,c++,sleep,frame-rate,chrono,C++,Sleep,Frame Rate,Chrono,我有一个简单的fps限制器,它可以工作: 时钟 #包括 使用名称空间std::chrono; 上课钟 { 高分辨率时钟:时间点开始时间; 公众: 时钟(); 持续时间重新启动(); }; Clock.cpp #include "Clock.h" Clock::Clock() : startTime(high_resolution_clock::now()) { } duration<double> Clock::restart() { high

我有一个简单的fps限制器,它可以工作:
时钟

#包括
使用名称空间std::chrono;
上课钟
{ 
高分辨率时钟:时间点开始时间;
公众:
时钟();
持续时间重新启动();
};
Clock.cpp


#include "Clock.h"

Clock::Clock()
: startTime(high_resolution_clock::now())
{

}

duration<double> Clock::restart()
{
    high_resolution_clock::time_point now = high_resolution_clock::now();
    duration<double> elapsed = now - startTime;
    startTime = now;

    return elapsed;
}

#包括“Clock.h”
时钟::时钟()
:开始时间(高分辨率时钟::现在()
{
}
持续时间时钟::重新启动()
{
高分辨率时钟::现在的时间点=高分辨率时钟::现在();
持续时间=现在-开始时间;
开始时间=现在;
返回时间已过;
}
main.cpp

    duration<double> stepInterval(1.f / 60.f);
    duration<double> deltaTime(0);

    Clock clock;
    while(isRunning)
    {
        deltaTime += clock.restart();
        if(deltaTime > stepInterval)
        {
            std::cout << deltaTime.count() * 1000 << std::endl;
            deltaTime = seconds(0);
        }
    }
持续时间步长间隔(1.f/60.f);
持续时间增量(0);
时钟;
同时(正在运行)
{
deltaTime+=时钟。重新启动();
if(增量时间>步长间隔)
{

std::cout此代码可能会帮助您。它对我很有效(精度很高):


#包括
#包括
#包括
int main()
{
标准::时钟::高分辨率时钟::时间点上一个=
标准::时钟::高分辨率时钟::现在();
标准::时钟::高分辨率时钟::时间点电流=
标准::时钟::高分辨率时钟::现在();
int i=0;
while(true){
当前=标准::时钟::高分辨率时钟::现在();
if(std::chrono::duration_cast(current-prev).count()>=16000){
prev=当前值;
i++;

std::cout此代码可能会帮助您。它对我很有效(精度很高):


#包括
#包括
#包括
int main()
{
标准::时钟::高分辨率时钟::时间点上一个=
标准::时钟::高分辨率时钟::现在();
标准::时钟::高分辨率时钟::时间点电流=
标准::时钟::高分辨率时钟::现在();
int i=0;
while(true){
当前=标准::时钟::高分辨率时钟::现在();
if(std::chrono::duration_cast(current-prev).count()>=16000){
prev=当前值;
i++;
标准::cout
  • 不要对
使用
sleep\u。改用
sleep\u直到
为止。这将平均从所需帧速率到零的漂移。这是通过睡眠直到当前帧开始加上所需帧持续时间来完成的

  • 使用
    system\u clock
    可以使您的帧速率在很长一段时间内保持准确。没有一个时钟是完美的。但是
    system\u clock
    偶尔会被少量调整到正确的时间。这会使您的帧速率在整个电影长度内都与所需的帧速率保持一致。不要遵循这一点如果您关心的是具有管理员权限的进程,请按总量调整系统时钟。在这种情况下,请使用
    稳定时钟

  • 创建1/60秒持续时间类型以消除浮点舍入错误

  • 消除代码中的转换常量,如
    1000
    ,以减少逻辑错误的可能性

  • 在您的
    睡眠时间
    中,早起一点,然后忙碌地循环直到所需的时间。您必须测试早起的时间。太早会消耗太多的CPU(和电池)。太少,而
    睡眠时间
    在CPU负载较高时偶尔会醒来太晚

  • 总而言之,这可能看起来像:

    template <class Clock, class Duration>
    void
    sleep_until(std::chrono::time_point<Clock, Duration> tp)
    {
        using namespace std::chrono;
        std::this_thread::sleep_until(tp - 10us);
        while (tp >= Clock::now())
            ;
    }
    
    int
    main()
    {
        using namespace std;
        using namespace std::chrono;
    
        using framerate = duration<int, ratio<1, 60>>;
        auto tp = system_clock::now() + framerate{1};
    
        while (isRunning)
        {
            // do drawing
            ::sleep_until(tp);
            tp += framerate{1};
        }
    }
    
    我的输出:

    ...
    This frame: 16ms  average: 17ms
    This frame: 15ms  average: 17ms
    This frame: 19ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 17ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 17ms  average: 17ms
    This frame: 17ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 18ms  average: 17ms
    This frame: 16ms  average: 17ms
    
    • 不要对
    使用
    sleep\u。改用
    sleep\u直到
    为止。这将平均从所需帧速率到零的漂移。这是通过睡眠直到当前帧开始加上所需帧持续时间来完成的

  • 使用
    system\u clock
    可以使您的帧速率在很长一段时间内保持准确。没有一个时钟是完美的。但是
    system\u clock
    偶尔会被少量调整到正确的时间。这会使您的帧速率在整个电影长度内都与所需的帧速率保持一致。不要遵循这一点如果您关心的是具有管理员权限的进程,请按总量调整系统时钟。在这种情况下,请使用
    稳定时钟

  • 创建1/60秒持续时间类型以消除浮点舍入错误

  • 消除代码中的转换常量,如
    1000
    ,以减少逻辑错误的可能性

  • 在您的
    睡眠时间
    中,早起一点,然后忙碌地循环直到所需的时间。您必须测试早起的时间。太早会消耗太多的CPU(和电池)。太少,而
    睡眠时间
    在CPU负载较高时偶尔会醒来太晚

  • 总而言之,这可能看起来像:

    template <class Clock, class Duration>
    void
    sleep_until(std::chrono::time_point<Clock, Duration> tp)
    {
        using namespace std::chrono;
        std::this_thread::sleep_until(tp - 10us);
        while (tp >= Clock::now())
            ;
    }
    
    int
    main()
    {
        using namespace std;
        using namespace std::chrono;
    
        using framerate = duration<int, ratio<1, 60>>;
        auto tp = system_clock::now() + framerate{1};
    
        while (isRunning)
        {
            // do drawing
            ::sleep_until(tp);
            tp += framerate{1};
        }
    }
    
    我的输出:

    ...
    This frame: 16ms  average: 17ms
    This frame: 15ms  average: 17ms
    This frame: 19ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 17ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 17ms  average: 17ms
    This frame: 17ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 16ms  average: 17ms
    This frame: 18ms  average: 17ms
    This frame: 16ms  average: 17ms
    

    您可能需要使用特定于操作系统的高精度时钟和计时器。例如,
    sleep\u for
    使用的“正常”计时器可能没有足够的分辨率。您可能需要使用特定于操作系统的高精度时钟和计时器。“正常”计时器例如
    sleep\u for
    使用的计时器可能没有足够的分辨率。我认为使用
    std::this\u thread::sleep\u for(std::chrono::microseconds(1));
    不是个好主意。我认为使用
    std::this\u thread::sleep\u for(std::chrono::microseconds(1));
    不是个好主意。谢谢你的建议。你能检查一下你的代码吗?它对我不起作用,CPU仍然有很高的负载。对不起,我在忙循环中的比较不正确。现在已修复。嗯,我有不同的输出,如
    31.774 1.5591 28.7145 16.7661
    ,你知道如何修复它吗?我已经更新了我的答案来测量和报告actual瞬时和平均帧速率。非常好!但不管怎样,有时我的帧速率为0到30毫秒,平均为17毫秒。谢谢你的建议。你能检查一下你的代码吗?它对我不起作用,CPU仍然有很高的负载抱歉,我在忙循环中的比较不正确。现在已修复。嗯,我有不同的输出,如... This frame: 16ms average: 17ms This frame: 15ms average: 17ms This frame: 19ms average: 17ms This frame: 16ms average: 17ms This frame: 17ms average: 17ms This frame: 16ms average: 17ms This frame: 17ms average: 17ms This frame: 17ms average: 17ms This frame: 16ms average: 17ms This frame: 16ms average: 17ms This frame: 16ms average: 17ms This frame: 18ms average: 17ms This frame: 16ms average: 17ms