gpt4 book ai didi

c++ - std::this_thread::sleep_until 时序完全偏离约 2 倍,莫名其妙

转载 作者:行者123 更新时间:2023-12-05 03:43:26 27 4
gpt4 key购买 nike

好吧,我真的不知道为什么会这样。我目前正在实现一个线程容器,它以分离的方式运行无限循环,限制在每次迭代之间的特定速度。

标题:

class timeloop
{
public:
std::thread thread = { };
bool state = true;

void (*function_pointer)() = nullptr;

double ratio = 1.0f;
std::chrono::nanoseconds elapsed = { };

timeloop(
void (*function_pointer)() = nullptr
);

void function();
};

定义:

void timeloop::start()
{
this->thread = std::thread(
&loop::function,
this
);
}

void timeloop::function()
{
std::chrono::steady_clock::time_point next;

std::chrono::steady_clock::time_point start;
std::chrono::steady_clock::time_point end;

while (
this->state
)
{
start = std::chrono::high_resolution_clock::now();
next = start + std::chrono::nanoseconds(
(long long) (this->ratio * (double) std::chrono::nanoseconds::period::den)
);

if (
this->function_pointer != nullptr
)
{
this->function_pointer();
}

/***************************
this is the culprit
***************************/
std::this_thread::sleep_until(
next
);

end = std::chrono::high_resolution_clock::now();
this->elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(
end - start
);
}
}

调用代码:

timeloop* thread_draw = new timeloop(
&some_void_function
);
thread_draw->ratio = 1.0 / 128.0;

thread_draw->start();
thread_draw->thread.detach();

定义代码表现异常,特别是 std::this_thread::sleep_until。使用 this->ratio = 1.0/128.0 我期望帧率为 128 左右,startnext 的计算值强化了这一点,但它莫名其妙地徘徊在 60 左右。是的,我尝试将 next 除以 2,但实际上它降到了 40 左右。

验证正常 sleep 时间的额外代码:

auto diff = std::chrono::nanoseconds(
next - start
).count() / (double) std::chrono::nanoseconds::period::den;
auto equal = diff == this->ratio;

其中 equal 的计算结果为 true

帧率计算:

double time = (double) thread_draw->elapsed.count() / (double) std::chrono::nanoseconds::period::den;
double fps = 1.0 / time;

虽然我也使用外部 FPS 计数器来验证(NVIDIA ShadowPlay 和 RivaTuner/MSI Afterburner),但它们在计算值的大约 +-5 范围内。

我知道它是 std::this_thread::sleep_until 因为一旦我注释掉它,帧率就会跳到 2000 左右。是的......

我真的对此感到困惑,尤其是看到我找不到任何其他人遇到过这个问题的证据。是的,我知道 sleep 功能并不完全准确,而且肯定会时不时地打嗝,但持续 sleep 时间几乎是预定时间的两倍是荒谬的。

我是否可能错误配置了编译器选项或其他什么?这绝对不是性能问题,而且我有理由相信这也不是逻辑错误(查看所有计算结果)[除非我在某处滥用 chrono]。

最佳答案

不保证sleep_until的分辨率,您只能保证线程不会在时间点之前被唤醒。如果您要实现主游戏循环,请阅读 Fix your timestep .

使用 sleep 来保证计时是一种糟糕的方法。您受制于操作系统调度程序,例如我相信 Windows 的最小 sleep 时间约为 10 毫秒。 (如果实现实际上要求操作系统让线程进入休眠状态,并且操作系统决定进行上下文切换。)

如果您正在调用 glfwSwapBuffers 或类似的,延迟也可能是由绘图线程中的 VSync 引起的。这可以解释为什么您的帧数限制为 60FPS,但不能解释为什么评论 sleep 可以解决问题。

所以我猜是上面操作系统的 sleep 。我建议取消 sleep 并依赖 VSync,无论如何,这是您想要绘制的正确频率。与逻辑线程同步会很痛苦……但情况总是如此。

关于c++ - std::this_thread::sleep_until 时序完全偏离约 2 倍,莫名其妙,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66841735/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com