簡體   English   中英

限制循環中的 fps c++

[英]Limit fps in loop c++

我有一個簡單的 fps 限制器,它可以工作:
時鍾.h

#include <chrono>
using namespace std::chrono; 

class Clock 
{ 
    high_resolution_clock::time_point startTime;
public:
    Clock(); 
    duration<double> restart();
};

時鍾.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;
}

主文件

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

但在這種情況下,CPU 的負載很高。 我用 std::this_thread::sleep_for 嘗試了另一種解決方案,但它們不能以很小的間隔(如 16 毫秒)工作。 關於實現 std::this_thread::sleep_for 的任何想法?

  • 不要使用sleep_for 請改用sleep_until 這將使您從所需幀速率的漂移平均為零。 這是通過休眠直到電流開始加上所需的幀持續時間來完成的。

  • 使用system_clock以便您的幀速率在很長一段時間內保持准確。 沒有時鍾是完美的。 但是system_clock偶爾會被少量調整到正確的時間。 這將影響您的幀速率在電影長度上與所需速率一致。 如果您擔心具有管理員權限的進程會按總金額調整系統時鍾,請不要遵循此建議。 在這種情況下,請改用steady_clock

  • 創建 1/60 s 持續時間類型以消除浮點舍入誤差。

  • 消除代碼中的轉換常數,如1000 ,以減少出現邏輯錯誤的可能性。

  • 在你的sleep_until中,早點醒來,然后忙循環直到所需的時間。 您將不得不嘗試提前多長時間。 太早了,你會燒掉太多的 CPU(和電池)。 太少了,而且當 CPU 處於高負載下時, sleep_until偶爾會喚醒太晚。

總而言之,這可能看起來像:

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

這是該想法的更詳細草圖,其中包括“繪制”每幀的當前幀速率和平均幀速率。 它使用 C++17 的 chrono chrono::round function 和這個免費的開源 C++20 chrono 預覽庫用於“繪圖”。

#include "date/date.h"
#include <chrono>
#include <iostream>
#include <thread>

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 prev = system_clock::now();
    auto next = prev + framerate{1};
    int N = 0;
    system_clock::duration sum{0};

    while (true)
    {
        ::sleep_until(next);
        next += framerate{1};

        // do drawing
        using namespace date;
        auto now = system_clock::now();
        sum += now - prev;
        ++N;
        cerr << "This frame: " << round<milliseconds>(now-prev)
             << "  average: " << round<milliseconds>(sum/N) << '\n';
        prev = now;
    }
}

Output 對我來說:

...
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

此代碼可能會對您有所幫助。 它對我來說效果很好(精度很好):


#include <iostream>
#include <thread>
#include <chrono>
    
int main()
{
    std::chrono::high_resolution_clock::time_point prev = 
        std::chrono::high_resolution_clock::now();
    std::chrono::high_resolution_clock::time_point current = 
        std::chrono::high_resolution_clock::now();
    
    int i = 0; 
    
    while (true) {
    
        current = std::chrono::high_resolution_clock::now();
    
        if (std::chrono::duration_cast<std::chrono::microseconds>(current - prev).count() >= 16000) {
            prev = current;
            i++;
            std::cout << i << std::endl;
        } else {
            std::this_thread::sleep_for(std::chrono::microseconds(1));
        }  
    
    }  
    
    return 0; 
}
```    ‍‍‍‍‍‍‍

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM