谁能说出以下示例的问题所在?
它每秒产生 65 帧而不是 300 帧。
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <Thread>
#include <Chrono>
#include <String>
int main(int argc, const char* argv[]) {
using namespace std::chrono_literals;
constexpr unsigned short FPS_Limit = 300;
std::chrono::duration<double, std::ratio<1, FPS_Limit>> FrameDelay = std::chrono::duration<double, std::ratio<1, FPS_Limit>>(1.0f);
unsigned int FPS = 0;
std::chrono::steady_clock SecondTimer;
std::chrono::steady_clock ProcessTimer;
std::chrono::steady_clock::time_point TpS = SecondTimer.now();
std::chrono::steady_clock::time_point TpP = ProcessTimer.now();
while (true) {
// ...
// Count FPS
FPS++;
if ((TpS + (SecondTimer.now() - TpS)) > (TpS + 1s)) {
OutputDebugString(std::to_string(FPS).c_str()); OutputDebugString("\n");
FPS = 0;
TpS = SecondTimer.now();
}
// Sleep
std::this_thread::sleep_for(FrameDelay - (ProcessTimer.now() - TpP)); // FrameDelay minus time needed to execute other things
TpP = ProcessTimer.now();
}
return 0;
}
我想这与std::chrono::duration<double, std::ratio<1, FPS_Limit>>
有关, 但当它乘以 FPS_Limit
每秒产生正确的 1 帧。
请注意,每秒 300 帧的限制只是一个示例。 它可以替换为任何其他数字,程序仍然会休眠太久。
最佳答案
简而言之,问题在于您根本不使用 std::this_thread::sleep_for
。或者,就此而言,任何一种“ sleep ”。 sleep 以限制帧速率是完全错误的。
sleep 功能的目的是,好吧……老实说我不知道。它几乎没有什么好的用途,实际上在每种情况下,不同的机制会更好。
std::this_thread::sleep_for
所做的(提供或采取几行健全性测试和错误检查)是,它调用 Win32 Sleep
函数(或,在不同的操作系统上,不同的,类似的功能,例如 nanosleep
)。
现在,Sleep
做了什么?它会在操作系统的小红皮书某处记录您的线程需要在未来某个时间再次准备就绪,然后呈现您的线程未就绪。未就绪仅意味着您的线程不在要安排获取 CPU 时间的候选列表中。
有时,最终,硬件定时器会触发中断。这可以是一个周期性计时器(Windows 8 之前的版本),其默认分辨率非常糟糕,或者是可编程的单次中断,等等。您甚至可以调整该计时器的分辨率,但这样做是全局的事情,会大大增加上下文切换的次数。另外,它不能解决实际 问题。当 OS 处理中断时,它会在其簿中查找哪些线程需要准备就绪,然后它就会这样做。
然而,这与运行您的线程不同是一样的。它只是再次运行的候选者(也许,某个时候)。
因此,存在计时器粒度、测量不准确以及时间安排……这些都非常非常不适合短的周期性间隔。此外,已知不同的 Windows 版本会以不同的方式舍入到调度程序的粒度。
解决办法:不要 sleep 。启用垂直同步,或让用户自行启用。
关于c++ - std::this_thread::sleep_for sleep 时间过长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58436872/